From 67970ba497e952e3fe178f764256074afb4bf728 Mon Sep 17 00:00:00 2001 From: Rmys Date: Mon, 1 Mar 2021 20:37:17 +0300 Subject: [PATCH] kernel-5.10.19 --- .../kernel/files/configs/kernel-x86_64-config | 2 +- .../change-default-console-loglevel.patch | 11 - .../fix_CPU0_microcode_on_resume.patch | 21 - .../gentoo/1500_XATTR_USER_PREFIX.patch | 54 - ...ink-security-restrictions-by-default.patch | 22 - ...0_ThinkPad-30-brightness-control-fix.patch | 67 - .../gentoo/2900_dev-root-proc-mount-fix.patch | 30 - .../gentoo/2905_2disk-resume-image-fix.patch | 24 - .../patches/gentoo/4200_fbcondecor-3.19.patch | 2119 - .../gentoo/4567_distro-Gentoo-Kconfig.patch | 143 - ...kconfig-build-bits-for-BFQ-v7r7-3.19.patch | 104 - ...duce-the-BFQ-v7r7-I-O-sched-for-3.19.patch | 6966 --- ...the-BFQ-v7r7-I-O-sched-for-3.19.patch1.txt | 6966 --- ...eue-Merge-EQM-to-BFQ-v7r7-for-3.19.0.patch | 1222 - ...tional-cpu-optimizations-for-gcc-4.9.patch | 387 - .../files/patches/linux/patch-5.10.11.xz | Bin 397188 -> 0 bytes .../files/patches/linux/patch-5.10.19.xz | Bin 0 -> 535612 bytes .../files/patches/linux/patch-5.10.3.xz | Bin 16432 -> 0 bytes .../files/patches/linux/patch-5.10.5.xz | Bin 223376 -> 0 bytes .../files/patches/linux/patch-5.9.13.xz | Bin 621916 -> 0 bytes .../kernel/files/patches/mageia/aufs5.patch | 38152 ---------------- .../patches/mageia/fs-aufs-5.6-fix.patch | 39 - .../patches/mageia/fs-aufs-5.6-modular.patch | 312 - .../files/patches/mageia/fs-aufs-5.6.patch | 37834 --------------- .../files/patches/mageia/fs-aufs5.patch | 37934 --------------- kernel/kernel/pspec.xml | 14 +- 26 files changed, 14 insertions(+), 132409 deletions(-) delete mode 100644 kernel/kernel/files/patches/archlinux/change-default-console-loglevel.patch delete mode 100644 kernel/kernel/files/patches/archlinux/fix_CPU0_microcode_on_resume.patch delete mode 100644 kernel/kernel/files/patches/gentoo/1500_XATTR_USER_PREFIX.patch delete mode 100644 kernel/kernel/files/patches/gentoo/1510_fs-enable-link-security-restrictions-by-default.patch delete mode 100644 kernel/kernel/files/patches/gentoo/2700_ThinkPad-30-brightness-control-fix.patch delete mode 100644 kernel/kernel/files/patches/gentoo/2900_dev-root-proc-mount-fix.patch delete mode 100644 kernel/kernel/files/patches/gentoo/2905_2disk-resume-image-fix.patch delete mode 100644 kernel/kernel/files/patches/gentoo/4200_fbcondecor-3.19.patch delete mode 100644 kernel/kernel/files/patches/gentoo/4567_distro-Gentoo-Kconfig.patch delete mode 100644 kernel/kernel/files/patches/gentoo/5001_block-cgroups-kconfig-build-bits-for-BFQ-v7r7-3.19.patch delete mode 100644 kernel/kernel/files/patches/gentoo/5002_block-introduce-the-BFQ-v7r7-I-O-sched-for-3.19.patch delete mode 100644 kernel/kernel/files/patches/gentoo/5002_block-introduce-the-BFQ-v7r7-I-O-sched-for-3.19.patch1.txt delete mode 100644 kernel/kernel/files/patches/gentoo/5003_block-bfq-add-Early-Queue-Merge-EQM-to-BFQ-v7r7-for-3.19.0.patch delete mode 100644 kernel/kernel/files/patches/gentoo/5010_enable-additional-cpu-optimizations-for-gcc-4.9.patch delete mode 100644 kernel/kernel/files/patches/linux/patch-5.10.11.xz create mode 100644 kernel/kernel/files/patches/linux/patch-5.10.19.xz delete mode 100644 kernel/kernel/files/patches/linux/patch-5.10.3.xz delete mode 100644 kernel/kernel/files/patches/linux/patch-5.10.5.xz delete mode 100644 kernel/kernel/files/patches/linux/patch-5.9.13.xz delete mode 100644 kernel/kernel/files/patches/mageia/aufs5.patch delete mode 100644 kernel/kernel/files/patches/mageia/fs-aufs-5.6-fix.patch delete mode 100644 kernel/kernel/files/patches/mageia/fs-aufs-5.6-modular.patch delete mode 100644 kernel/kernel/files/patches/mageia/fs-aufs-5.6.patch delete mode 100644 kernel/kernel/files/patches/mageia/fs-aufs5.patch diff --git a/kernel/kernel/files/configs/kernel-x86_64-config b/kernel/kernel/files/configs/kernel-x86_64-config index f24fb359..a9133362 100644 --- a/kernel/kernel/files/configs/kernel-x86_64-config +++ b/kernel/kernel/files/configs/kernel-x86_64-config @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/x86_64 5.10.15 Kernel Configuration +# Linux/x86_64 5.10.19 Kernel Configuration # CONFIG_CC_VERSION_TEXT="gcc (Pisi Linux) 10.2.1 20201212" CONFIG_CC_IS_GCC=y diff --git a/kernel/kernel/files/patches/archlinux/change-default-console-loglevel.patch b/kernel/kernel/files/patches/archlinux/change-default-console-loglevel.patch deleted file mode 100644 index 11da2a9d..00000000 --- a/kernel/kernel/files/patches/archlinux/change-default-console-loglevel.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- linux-3.16/include/linux/printk.h.old 2014-08-04 18:48:30.686043266 +0200 -+++ linux-3.16/include/linux/printk.h 2014-08-04 18:48:47.706218528 +0200 -@@ -37,7 +37,7 @@ - #define CONSOLE_LOGLEVEL_SILENT 0 /* Mum's the word */ - #define CONSOLE_LOGLEVEL_MIN 1 /* Minimum loglevel we let people use */ - #define CONSOLE_LOGLEVEL_QUIET 4 /* Shhh ..., when booted with "quiet" */ --#define CONSOLE_LOGLEVEL_DEFAULT 7 /* anything MORE serious than KERN_DEBUG */ -+#define CONSOLE_LOGLEVEL_DEFAULT 4 /* anything MORE serious than KERN_DEBUG */ - #define CONSOLE_LOGLEVEL_DEBUG 10 /* issue debug messages */ - #define CONSOLE_LOGLEVEL_MOTORMOUTH 15 /* You can't shut this one up */ - diff --git a/kernel/kernel/files/patches/archlinux/fix_CPU0_microcode_on_resume.patch b/kernel/kernel/files/patches/archlinux/fix_CPU0_microcode_on_resume.patch deleted file mode 100644 index 56f8094f..00000000 --- a/kernel/kernel/files/patches/archlinux/fix_CPU0_microcode_on_resume.patch +++ /dev/null @@ -1,21 +0,0 @@ -diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c -index dd9d6190b08d..181e42bd85d3 100644 ---- a/arch/x86/kernel/cpu/microcode/core.c -+++ b/arch/x86/kernel/cpu/microcode/core.c -@@ -85,6 +85,7 @@ - #include - - #include -+#include - #include - #include - #include -@@ -465,6 +466,8 @@ static void mc_bp_resume(void) - - if (uci->valid && uci->mc) - microcode_ops->apply_microcode(cpu); -+ else if (!uci->mc) -+ load_ucode_intel_ap(); - } - - static struct syscore_ops mc_syscore_ops = { diff --git a/kernel/kernel/files/patches/gentoo/1500_XATTR_USER_PREFIX.patch b/kernel/kernel/files/patches/gentoo/1500_XATTR_USER_PREFIX.patch deleted file mode 100644 index cc15cd51..00000000 --- a/kernel/kernel/files/patches/gentoo/1500_XATTR_USER_PREFIX.patch +++ /dev/null @@ -1,54 +0,0 @@ -From: Anthony G. Basile - -This patch adds support for a restricted user-controlled namespace on -tmpfs filesystem used to house PaX flags. The namespace must be of the -form user.pax.* and its value cannot exceed a size of 8 bytes. - -This is needed even on all Gentoo systems so that XATTR_PAX flags -are preserved for users who might build packages using portage on -a tmpfs system with a non-hardened kernel and then switch to a -hardened kernel with XATTR_PAX enabled. - -The namespace is added to any user with Extended Attribute support -enabled for tmpfs. Users who do not enable xattrs will not have -the XATTR_PAX flags preserved. - -diff --git a/include/uapi/linux/xattr.h b/include/uapi/linux/xattr.h -index e4629b9..6958086 100644 ---- a/include/uapi/linux/xattr.h -+++ b/include/uapi/linux/xattr.h -@@ -63,5 +63,9 @@ - #define XATTR_POSIX_ACL_DEFAULT "posix_acl_default" - #define XATTR_NAME_POSIX_ACL_DEFAULT XATTR_SYSTEM_PREFIX XATTR_POSIX_ACL_DEFAULT - -+/* User namespace */ -+#define XATTR_PAX_PREFIX XATTR_USER_PREFIX "pax." -+#define XATTR_PAX_FLAGS_SUFFIX "flags" -+#define XATTR_NAME_PAX_FLAGS XATTR_PAX_PREFIX XATTR_PAX_FLAGS_SUFFIX - - #endif /* _UAPI_LINUX_XATTR_H */ -diff --git a/mm/shmem.c b/mm/shmem.c -index 1c44af7..f23bb1b 100644 ---- a/mm/shmem.c -+++ b/mm/shmem.c -@@ -2201,6 +2201,7 @@ static const struct xattr_handler *shmem_xattr_handlers[] = { - static int shmem_xattr_validate(const char *name) - { - struct { const char *prefix; size_t len; } arr[] = { -+ { XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN}, - { XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN }, - { XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN } - }; -@@ -2256,6 +2257,12 @@ static int shmem_setxattr(struct dentry *dentry, const char *name, - if (err) - return err; - -+ if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)) { -+ if (strcmp(name, XATTR_NAME_PAX_FLAGS)) -+ return -EOPNOTSUPP; -+ if (size > 8) -+ return -EINVAL; -+ } - return simple_xattr_set(&info->xattrs, name, value, size, flags); - } - diff --git a/kernel/kernel/files/patches/gentoo/1510_fs-enable-link-security-restrictions-by-default.patch b/kernel/kernel/files/patches/gentoo/1510_fs-enable-link-security-restrictions-by-default.patch deleted file mode 100644 index 639fb3c3..00000000 --- a/kernel/kernel/files/patches/gentoo/1510_fs-enable-link-security-restrictions-by-default.patch +++ /dev/null @@ -1,22 +0,0 @@ -From: Ben Hutchings -Subject: fs: Enable link security restrictions by default -Date: Fri, 02 Nov 2012 05:32:06 +0000 -Bug-Debian: https://bugs.debian.org/609455 -Forwarded: not-needed - -This reverts commit 561ec64ae67ef25cac8d72bb9c4bfc955edfd415 -('VFS: don't do protected {sym,hard}links by default'). - ---- a/fs/namei.c -+++ b/fs/namei.c -@@ -651,8 +651,8 @@ static inline void put_link(struct namei - path_put(link); - } - --int sysctl_protected_symlinks __read_mostly = 0; --int sysctl_protected_hardlinks __read_mostly = 0; -+int sysctl_protected_symlinks __read_mostly = 1; -+int sysctl_protected_hardlinks __read_mostly = 1; - - /** - * may_follow_link - Check symlink following for unsafe situations diff --git a/kernel/kernel/files/patches/gentoo/2700_ThinkPad-30-brightness-control-fix.patch b/kernel/kernel/files/patches/gentoo/2700_ThinkPad-30-brightness-control-fix.patch deleted file mode 100644 index b548c6dc..00000000 --- a/kernel/kernel/files/patches/gentoo/2700_ThinkPad-30-brightness-control-fix.patch +++ /dev/null @@ -1,67 +0,0 @@ -diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c -index cb96296..6c242ed 100644 ---- a/drivers/acpi/blacklist.c -+++ b/drivers/acpi/blacklist.c -@@ -269,6 +276,61 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { - }, - - /* -+ * The following Lenovo models have a broken workaround in the -+ * acpi_video backlight implementation to meet the Windows 8 -+ * requirement of 101 backlight levels. Reverting to pre-Win8 -+ * behavior fixes the problem. -+ */ -+ { -+ .callback = dmi_disable_osi_win8, -+ .ident = "Lenovo ThinkPad L430", -+ .matches = { -+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), -+ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L430"), -+ }, -+ }, -+ { -+ .callback = dmi_disable_osi_win8, -+ .ident = "Lenovo ThinkPad T430s", -+ .matches = { -+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), -+ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T430s"), -+ }, -+ }, -+ { -+ .callback = dmi_disable_osi_win8, -+ .ident = "Lenovo ThinkPad T530", -+ .matches = { -+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), -+ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T530"), -+ }, -+ }, -+ { -+ .callback = dmi_disable_osi_win8, -+ .ident = "Lenovo ThinkPad W530", -+ .matches = { -+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), -+ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad W530"), -+ }, -+ }, -+ { -+ .callback = dmi_disable_osi_win8, -+ .ident = "Lenovo ThinkPad X1 Carbon", -+ .matches = { -+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), -+ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X1 Carbon"), -+ }, -+ }, -+ { -+ .callback = dmi_disable_osi_win8, -+ .ident = "Lenovo ThinkPad X230", -+ .matches = { -+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), -+ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X230"), -+ }, -+ }, -+ -+ /* - * BIOS invocation of _OSI(Linux) is almost always a BIOS bug. - * Linux ignores it, except for the machines enumerated below. - */ - diff --git a/kernel/kernel/files/patches/gentoo/2900_dev-root-proc-mount-fix.patch b/kernel/kernel/files/patches/gentoo/2900_dev-root-proc-mount-fix.patch deleted file mode 100644 index 6ea86e29..00000000 --- a/kernel/kernel/files/patches/gentoo/2900_dev-root-proc-mount-fix.patch +++ /dev/null @@ -1,30 +0,0 @@ ---- a/init/do_mounts.c 2014-08-26 08:03:30.000013100 -0400 -+++ b/init/do_mounts.c 2014-08-26 08:11:19.720014712 -0400 -@@ -484,7 +484,10 @@ void __init change_floppy(char *fmt, ... - va_start(args, fmt); - vsprintf(buf, fmt, args); - va_end(args); -- fd = sys_open("/dev/root", O_RDWR | O_NDELAY, 0); -+ if (saved_root_name[0]) -+ fd = sys_open(saved_root_name, O_RDWR | O_NDELAY, 0); -+ else -+ fd = sys_open("/dev/root", O_RDWR | O_NDELAY, 0); - if (fd >= 0) { - sys_ioctl(fd, FDEJECT, 0); - sys_close(fd); -@@ -527,8 +530,13 @@ void __init mount_root(void) - } - #endif - #ifdef CONFIG_BLOCK -- create_dev("/dev/root", ROOT_DEV); -- mount_block_root("/dev/root", root_mountflags); -+ if (saved_root_name[0]) { -+ create_dev(saved_root_name, ROOT_DEV); -+ mount_block_root(saved_root_name, root_mountflags); -+ } else { -+ create_dev("/dev/root", ROOT_DEV); -+ mount_block_root("/dev/root", root_mountflags); -+ } - #endif - } - diff --git a/kernel/kernel/files/patches/gentoo/2905_2disk-resume-image-fix.patch b/kernel/kernel/files/patches/gentoo/2905_2disk-resume-image-fix.patch deleted file mode 100644 index 7e95d298..00000000 --- a/kernel/kernel/files/patches/gentoo/2905_2disk-resume-image-fix.patch +++ /dev/null @@ -1,24 +0,0 @@ -diff --git a/kernel/kmod.c b/kernel/kmod.c -index fb32636..d968882 100644 ---- a/kernel/kmod.c -+++ b/kernel/kmod.c -@@ -575,7 +575,8 @@ - call_usermodehelper_freeinfo(sub_info); - return -EINVAL; - } -- helper_lock(); -+ if (!(current->flags & PF_FREEZER_SKIP)) -+ helper_lock(); - if (!khelper_wq || usermodehelper_disabled) { - retval = -EBUSY; - goto out; -@@ -611,7 +612,8 @@ wait_done: - out: - call_usermodehelper_freeinfo(sub_info); - unlock: -- helper_unlock(); -+ if (!(current->flags & PF_FREEZER_SKIP)) -+ helper_unlock(); - return retval; - } - EXPORT_SYMBOL(call_usermodehelper_exec); diff --git a/kernel/kernel/files/patches/gentoo/4200_fbcondecor-3.19.patch b/kernel/kernel/files/patches/gentoo/4200_fbcondecor-3.19.patch deleted file mode 100644 index 29c379fe..00000000 --- a/kernel/kernel/files/patches/gentoo/4200_fbcondecor-3.19.patch +++ /dev/null @@ -1,2119 +0,0 @@ -diff --git a/Documentation/fb/00-INDEX b/Documentation/fb/00-INDEX -index fe85e7c..2230930 100644 ---- a/Documentation/fb/00-INDEX -+++ b/Documentation/fb/00-INDEX -@@ -23,6 +23,8 @@ ep93xx-fb.txt - - info on the driver for EP93xx LCD controller. - fbcon.txt - - intro to and usage guide for the framebuffer console (fbcon). -+fbcondecor.txt -+ - info on the Framebuffer Console Decoration - framebuffer.txt - - introduction to frame buffer devices. - gxfb.txt -diff --git a/Documentation/fb/fbcondecor.txt b/Documentation/fb/fbcondecor.txt -new file mode 100644 -index 0000000..3388c61 ---- /dev/null -+++ b/Documentation/fb/fbcondecor.txt -@@ -0,0 +1,207 @@ -+What is it? -+----------- -+ -+The framebuffer decorations are a kernel feature which allows displaying a -+background picture on selected consoles. -+ -+What do I need to get it to work? -+--------------------------------- -+ -+To get fbcondecor up-and-running you will have to: -+ 1) get a copy of splashutils [1] or a similar program -+ 2) get some fbcondecor themes -+ 3) build the kernel helper program -+ 4) build your kernel with the FB_CON_DECOR option enabled. -+ -+To get fbcondecor operational right after fbcon initialization is finished, you -+will have to include a theme and the kernel helper into your initramfs image. -+Please refer to splashutils documentation for instructions on how to do that. -+ -+[1] The splashutils package can be downloaded from: -+ http://github.com/alanhaggai/fbsplash -+ -+The userspace helper -+-------------------- -+ -+The userspace fbcondecor helper (by default: /sbin/fbcondecor_helper) is called by the -+kernel whenever an important event occurs and the kernel needs some kind of -+job to be carried out. Important events include console switches and video -+mode switches (the kernel requests background images and configuration -+parameters for the current console). The fbcondecor helper must be accessible at -+all times. If it's not, fbcondecor will be switched off automatically. -+ -+It's possible to set path to the fbcondecor helper by writing it to -+/proc/sys/kernel/fbcondecor. -+ -+***************************************************************************** -+ -+The information below is mostly technical stuff. There's probably no need to -+read it unless you plan to develop a userspace helper. -+ -+The fbcondecor protocol -+----------------------- -+ -+The fbcondecor protocol defines a communication interface between the kernel and -+the userspace fbcondecor helper. -+ -+The kernel side is responsible for: -+ -+ * rendering console text, using an image as a background (instead of a -+ standard solid color fbcon uses), -+ * accepting commands from the user via ioctls on the fbcondecor device, -+ * calling the userspace helper to set things up as soon as the fb subsystem -+ is initialized. -+ -+The userspace helper is responsible for everything else, including parsing -+configuration files, decompressing the image files whenever the kernel needs -+it, and communicating with the kernel if necessary. -+ -+The fbcondecor protocol specifies how communication is done in both ways: -+kernel->userspace and userspace->helper. -+ -+Kernel -> Userspace -+------------------- -+ -+The kernel communicates with the userspace helper by calling it and specifying -+the task to be done in a series of arguments. -+ -+The arguments follow the pattern: -+ -+ -+All commands defined in fbcondecor protocol v2 have the following parameters: -+ virtual console -+ framebuffer number -+ theme -+ -+Fbcondecor protocol v1 specified an additional 'fbcondecor mode' after the -+framebuffer number. Fbcondecor protocol v1 is deprecated and should not be used. -+ -+Fbcondecor protocol v2 specifies the following commands: -+ -+getpic -+------ -+ The kernel issues this command to request image data. It's up to the -+ userspace helper to find a background image appropriate for the specified -+ theme and the current resolution. The userspace helper should respond by -+ issuing the FBIOCONDECOR_SETPIC ioctl. -+ -+init -+---- -+ The kernel issues this command after the fbcondecor device is created and -+ the fbcondecor interface is initialized. Upon receiving 'init', the userspace -+ helper should parse the kernel command line (/proc/cmdline) or otherwise -+ decide whether fbcondecor is to be activated. -+ -+ To activate fbcondecor on the first console the helper should issue the -+ FBIOCONDECOR_SETCFG, FBIOCONDECOR_SETPIC and FBIOCONDECOR_SETSTATE commands, -+ in the above-mentioned order. -+ -+ When the userspace helper is called in an early phase of the boot process -+ (right after the initialization of fbcon), no filesystems will be mounted. -+ The helper program should mount sysfs and then create the appropriate -+ framebuffer, fbcondecor and tty0 devices (if they don't already exist) to get -+ current display settings and to be able to communicate with the kernel side. -+ It should probably also mount the procfs to be able to parse the kernel -+ command line parameters. -+ -+ Note that the console sem is not held when the kernel calls fbcondecor_helper -+ with the 'init' command. The fbcondecor helper should perform all ioctls with -+ origin set to FBCON_DECOR_IO_ORIG_USER. -+ -+modechange -+---------- -+ The kernel issues this command on a mode change. The helper's response should -+ be similar to the response to the 'init' command. Note that this time the -+ console sem is held and all ioctls must be performed with origin set to -+ FBCON_DECOR_IO_ORIG_KERNEL. -+ -+ -+Userspace -> Kernel -+------------------- -+ -+Userspace programs can communicate with fbcondecor via ioctls on the -+fbcondecor device. These ioctls are to be used by both the userspace helper -+(called only by the kernel) and userspace configuration tools (run by the users). -+ -+The fbcondecor helper should set the origin field to FBCON_DECOR_IO_ORIG_KERNEL -+when doing the appropriate ioctls. All userspace configuration tools should -+use FBCON_DECOR_IO_ORIG_USER. Failure to set the appropriate value in the origin -+field when performing ioctls from the kernel helper will most likely result -+in a console deadlock. -+ -+FBCON_DECOR_IO_ORIG_KERNEL instructs fbcondecor not to try to acquire the console -+semaphore. Not surprisingly, FBCON_DECOR_IO_ORIG_USER instructs it to acquire -+the console sem. -+ -+The framebuffer console decoration provides the following ioctls (all defined in -+linux/fb.h): -+ -+FBIOCONDECOR_SETPIC -+description: loads a background picture for a virtual console -+argument: struct fbcon_decor_iowrapper*; data: struct fb_image* -+notes: -+If called for consoles other than the current foreground one, the picture data -+will be ignored. -+ -+If the current virtual console is running in a 8-bpp mode, the cmap substruct -+of fb_image has to be filled appropriately: start should be set to 16 (first -+16 colors are reserved for fbcon), len to a value <= 240 and red, green and -+blue should point to valid cmap data. The transp field is ingored. The fields -+dx, dy, bg_color, fg_color in fb_image are ignored as well. -+ -+FBIOCONDECOR_SETCFG -+description: sets the fbcondecor config for a virtual console -+argument: struct fbcon_decor_iowrapper*; data: struct vc_decor* -+notes: The structure has to be filled with valid data. -+ -+FBIOCONDECOR_GETCFG -+description: gets the fbcondecor config for a virtual console -+argument: struct fbcon_decor_iowrapper*; data: struct vc_decor* -+ -+FBIOCONDECOR_SETSTATE -+description: sets the fbcondecor state for a virtual console -+argument: struct fbcon_decor_iowrapper*; data: unsigned int* -+ values: 0 = disabled, 1 = enabled. -+ -+FBIOCONDECOR_GETSTATE -+description: gets the fbcondecor state for a virtual console -+argument: struct fbcon_decor_iowrapper*; data: unsigned int* -+ values: as in FBIOCONDECOR_SETSTATE -+ -+Info on used structures: -+ -+Definition of struct vc_decor can be found in linux/console_decor.h. It's -+heavily commented. Note that the 'theme' field should point to a string -+no longer than FBCON_DECOR_THEME_LEN. When FBIOCONDECOR_GETCFG call is -+performed, the theme field should point to a char buffer of length -+FBCON_DECOR_THEME_LEN. -+ -+Definition of struct fbcon_decor_iowrapper can be found in linux/fb.h. -+The fields in this struct have the following meaning: -+ -+vc: -+Virtual console number. -+ -+origin: -+Specifies if the ioctl is performed as a response to a kernel request. The -+fbcondecor helper should set this field to FBCON_DECOR_IO_ORIG_KERNEL, userspace -+programs should set it to FBCON_DECOR_IO_ORIG_USER. This field is necessary to -+avoid console semaphore deadlocks. -+ -+data: -+Pointer to a data structure appropriate for the performed ioctl. Type of -+the data struct is specified in the ioctls description. -+ -+***************************************************************************** -+ -+Credit -+------ -+ -+Original 'bootsplash' project & implementation by: -+ Volker Poplawski , Stefan Reinauer , -+ Steffen Winterfeldt , Michael Schroeder , -+ Ken Wimer . -+ -+Fbcondecor, fbcondecor protocol design, current implementation & docs by: -+ Michal Januszewski -+ -diff --git a/drivers/Makefile b/drivers/Makefile -index 7183b6a..d576148 100644 ---- a/drivers/Makefile -+++ b/drivers/Makefile -@@ -17,6 +17,10 @@ obj-y += pwm/ - obj-$(CONFIG_PCI) += pci/ - obj-$(CONFIG_PARISC) += parisc/ - obj-$(CONFIG_RAPIDIO) += rapidio/ -+# tty/ comes before char/ so that the VT console is the boot-time -+# default. -+obj-y += tty/ -+obj-y += char/ - obj-y += video/ - obj-y += idle/ - -@@ -42,11 +46,6 @@ obj-$(CONFIG_REGULATOR) += regulator/ - # reset controllers early, since gpu drivers might rely on them to initialize - obj-$(CONFIG_RESET_CONTROLLER) += reset/ - --# tty/ comes before char/ so that the VT console is the boot-time --# default. --obj-y += tty/ --obj-y += char/ -- - # iommu/ comes before gpu as gpu are using iommu controllers - obj-$(CONFIG_IOMMU_SUPPORT) += iommu/ - -diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig -index fe1cd01..6d2e87a 100644 ---- a/drivers/video/console/Kconfig -+++ b/drivers/video/console/Kconfig -@@ -126,6 +126,19 @@ config FRAMEBUFFER_CONSOLE_ROTATION - such that other users of the framebuffer will remain normally - oriented. - -+config FB_CON_DECOR -+ bool "Support for the Framebuffer Console Decorations" -+ depends on FRAMEBUFFER_CONSOLE=y && !FB_TILEBLITTING -+ default n -+ ---help--- -+ This option enables support for framebuffer console decorations which -+ makes it possible to display images in the background of the system -+ consoles. Note that userspace utilities are necessary in order to take -+ advantage of these features. Refer to Documentation/fb/fbcondecor.txt -+ for more information. -+ -+ If unsure, say N. -+ - config STI_CONSOLE - bool "STI text console" - depends on PARISC -diff --git a/drivers/video/console/Makefile b/drivers/video/console/Makefile -index 43bfa48..cc104b6f 100644 ---- a/drivers/video/console/Makefile -+++ b/drivers/video/console/Makefile -@@ -16,4 +16,5 @@ obj-$(CONFIG_FRAMEBUFFER_CONSOLE) += fbcon_rotate.o fbcon_cw.o fbcon_ud.o \ - fbcon_ccw.o - endif - -+obj-$(CONFIG_FB_CON_DECOR) += fbcondecor.o cfbcondecor.o - obj-$(CONFIG_FB_STI) += sticore.o -diff --git a/drivers/video/console/bitblit.c b/drivers/video/console/bitblit.c -index 61b182b..984384b 100644 ---- a/drivers/video/console/bitblit.c -+++ b/drivers/video/console/bitblit.c -@@ -18,6 +18,7 @@ - #include - #include - #include "fbcon.h" -+#include "fbcondecor.h" - - /* - * Accelerated handlers. -@@ -55,6 +56,13 @@ static void bit_bmove(struct vc_data *vc, struct fb_info *info, int sy, - area.height = height * vc->vc_font.height; - area.width = width * vc->vc_font.width; - -+ if (fbcon_decor_active(info, vc)) { -+ area.sx += vc->vc_decor.tx; -+ area.sy += vc->vc_decor.ty; -+ area.dx += vc->vc_decor.tx; -+ area.dy += vc->vc_decor.ty; -+ } -+ - info->fbops->fb_copyarea(info, &area); - } - -@@ -380,11 +388,15 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode, - cursor.image.depth = 1; - cursor.rop = ROP_XOR; - -- if (info->fbops->fb_cursor) -- err = info->fbops->fb_cursor(info, &cursor); -+ if (fbcon_decor_active(info, vc)) { -+ fbcon_decor_cursor(info, &cursor); -+ } else { -+ if (info->fbops->fb_cursor) -+ err = info->fbops->fb_cursor(info, &cursor); - -- if (err) -- soft_cursor(info, &cursor); -+ if (err) -+ soft_cursor(info, &cursor); -+ } - - ops->cursor_reset = 0; - } -diff --git a/drivers/video/console/cfbcondecor.c b/drivers/video/console/cfbcondecor.c -new file mode 100644 -index 0000000..a2b4497 ---- /dev/null -+++ b/drivers/video/console/cfbcondecor.c -@@ -0,0 +1,471 @@ -+/* -+ * linux/drivers/video/cfbcon_decor.c -- Framebuffer decor render functions -+ * -+ * Copyright (C) 2004 Michal Januszewski -+ * -+ * Code based upon "Bootdecor" (C) 2001-2003 -+ * Volker Poplawski , -+ * Stefan Reinauer , -+ * Steffen Winterfeldt , -+ * Michael Schroeder , -+ * Ken Wimer . -+ * -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file COPYING in the main directory of this archive for -+ * more details. -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "fbcon.h" -+#include "fbcondecor.h" -+ -+#define parse_pixel(shift,bpp,type) \ -+ do { \ -+ if (d & (0x80 >> (shift))) \ -+ dd2[(shift)] = fgx; \ -+ else \ -+ dd2[(shift)] = transparent ? *(type *)decor_src : bgx; \ -+ decor_src += (bpp); \ -+ } while (0) \ -+ -+extern int get_color(struct vc_data *vc, struct fb_info *info, -+ u16 c, int is_fg); -+ -+void fbcon_decor_fix_pseudo_pal(struct fb_info *info, struct vc_data *vc) -+{ -+ int i, j, k; -+ int minlen = min(min(info->var.red.length, info->var.green.length), -+ info->var.blue.length); -+ u32 col; -+ -+ for (j = i = 0; i < 16; i++) { -+ k = color_table[i]; -+ -+ col = ((vc->vc_palette[j++] >> (8-minlen)) -+ << info->var.red.offset); -+ col |= ((vc->vc_palette[j++] >> (8-minlen)) -+ << info->var.green.offset); -+ col |= ((vc->vc_palette[j++] >> (8-minlen)) -+ << info->var.blue.offset); -+ ((u32 *)info->pseudo_palette)[k] = col; -+ } -+} -+ -+void fbcon_decor_renderc(struct fb_info *info, int ypos, int xpos, int height, -+ int width, u8* src, u32 fgx, u32 bgx, u8 transparent) -+{ -+ unsigned int x, y; -+ u32 dd; -+ int bytespp = ((info->var.bits_per_pixel + 7) >> 3); -+ unsigned int d = ypos * info->fix.line_length + xpos * bytespp; -+ unsigned int ds = (ypos * info->var.xres + xpos) * bytespp; -+ u16 dd2[4]; -+ -+ u8* decor_src = (u8 *)(info->bgdecor.data + ds); -+ u8* dst = (u8 *)(info->screen_base + d); -+ -+ if ((ypos + height) > info->var.yres || (xpos + width) > info->var.xres) -+ return; -+ -+ for (y = 0; y < height; y++) { -+ switch (info->var.bits_per_pixel) { -+ -+ case 32: -+ for (x = 0; x < width; x++) { -+ -+ if ((x & 7) == 0) -+ d = *src++; -+ if (d & 0x80) -+ dd = fgx; -+ else -+ dd = transparent ? -+ *(u32 *)decor_src : bgx; -+ -+ d <<= 1; -+ decor_src += 4; -+ fb_writel(dd, dst); -+ dst += 4; -+ } -+ break; -+ case 24: -+ for (x = 0; x < width; x++) { -+ -+ if ((x & 7) == 0) -+ d = *src++; -+ if (d & 0x80) -+ dd = fgx; -+ else -+ dd = transparent ? -+ (*(u32 *)decor_src & 0xffffff) : bgx; -+ -+ d <<= 1; -+ decor_src += 3; -+#ifdef __LITTLE_ENDIAN -+ fb_writew(dd & 0xffff, dst); -+ dst += 2; -+ fb_writeb((dd >> 16), dst); -+#else -+ fb_writew(dd >> 8, dst); -+ dst += 2; -+ fb_writeb(dd & 0xff, dst); -+#endif -+ dst++; -+ } -+ break; -+ case 16: -+ for (x = 0; x < width; x += 2) { -+ if ((x & 7) == 0) -+ d = *src++; -+ -+ parse_pixel(0, 2, u16); -+ parse_pixel(1, 2, u16); -+#ifdef __LITTLE_ENDIAN -+ dd = dd2[0] | (dd2[1] << 16); -+#else -+ dd = dd2[1] | (dd2[0] << 16); -+#endif -+ d <<= 2; -+ fb_writel(dd, dst); -+ dst += 4; -+ } -+ break; -+ -+ case 8: -+ for (x = 0; x < width; x += 4) { -+ if ((x & 7) == 0) -+ d = *src++; -+ -+ parse_pixel(0, 1, u8); -+ parse_pixel(1, 1, u8); -+ parse_pixel(2, 1, u8); -+ parse_pixel(3, 1, u8); -+ -+#ifdef __LITTLE_ENDIAN -+ dd = dd2[0] | (dd2[1] << 8) | (dd2[2] << 16) | (dd2[3] << 24); -+#else -+ dd = dd2[3] | (dd2[2] << 8) | (dd2[1] << 16) | (dd2[0] << 24); -+#endif -+ d <<= 4; -+ fb_writel(dd, dst); -+ dst += 4; -+ } -+ } -+ -+ dst += info->fix.line_length - width * bytespp; -+ decor_src += (info->var.xres - width) * bytespp; -+ } -+} -+ -+#define cc2cx(a) \ -+ ((info->fix.visual == FB_VISUAL_TRUECOLOR || \ -+ info->fix.visual == FB_VISUAL_DIRECTCOLOR) ? \ -+ ((u32*)info->pseudo_palette)[a] : a) -+ -+void fbcon_decor_putcs(struct vc_data *vc, struct fb_info *info, -+ const unsigned short *s, int count, int yy, int xx) -+{ -+ unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; -+ struct fbcon_ops *ops = info->fbcon_par; -+ int fg_color, bg_color, transparent; -+ u8 *src; -+ u32 bgx, fgx; -+ u16 c = scr_readw(s); -+ -+ fg_color = get_color(vc, info, c, 1); -+ bg_color = get_color(vc, info, c, 0); -+ -+ /* Don't paint the background image if console is blanked */ -+ transparent = ops->blank_state ? 0 : -+ (vc->vc_decor.bg_color == bg_color); -+ -+ xx = xx * vc->vc_font.width + vc->vc_decor.tx; -+ yy = yy * vc->vc_font.height + vc->vc_decor.ty; -+ -+ fgx = cc2cx(fg_color); -+ bgx = cc2cx(bg_color); -+ -+ while (count--) { -+ c = scr_readw(s++); -+ src = vc->vc_font.data + (c & charmask) * vc->vc_font.height * -+ ((vc->vc_font.width + 7) >> 3); -+ -+ fbcon_decor_renderc(info, yy, xx, vc->vc_font.height, -+ vc->vc_font.width, src, fgx, bgx, transparent); -+ xx += vc->vc_font.width; -+ } -+} -+ -+void fbcon_decor_cursor(struct fb_info *info, struct fb_cursor *cursor) -+{ -+ int i; -+ unsigned int dsize, s_pitch; -+ struct fbcon_ops *ops = info->fbcon_par; -+ struct vc_data* vc; -+ u8 *src; -+ -+ /* we really don't need any cursors while the console is blanked */ -+ if (info->state != FBINFO_STATE_RUNNING || ops->blank_state) -+ return; -+ -+ vc = vc_cons[ops->currcon].d; -+ -+ src = kmalloc(64 + sizeof(struct fb_image), GFP_ATOMIC); -+ if (!src) -+ return; -+ -+ s_pitch = (cursor->image.width + 7) >> 3; -+ dsize = s_pitch * cursor->image.height; -+ if (cursor->enable) { -+ switch (cursor->rop) { -+ case ROP_XOR: -+ for (i = 0; i < dsize; i++) -+ src[i] = cursor->image.data[i] ^ cursor->mask[i]; -+ break; -+ case ROP_COPY: -+ default: -+ for (i = 0; i < dsize; i++) -+ src[i] = cursor->image.data[i] & cursor->mask[i]; -+ break; -+ } -+ } else -+ memcpy(src, cursor->image.data, dsize); -+ -+ fbcon_decor_renderc(info, -+ cursor->image.dy + vc->vc_decor.ty, -+ cursor->image.dx + vc->vc_decor.tx, -+ cursor->image.height, -+ cursor->image.width, -+ (u8*)src, -+ cc2cx(cursor->image.fg_color), -+ cc2cx(cursor->image.bg_color), -+ cursor->image.bg_color == vc->vc_decor.bg_color); -+ -+ kfree(src); -+} -+ -+static void decorset(u8 *dst, int height, int width, int dstbytes, -+ u32 bgx, int bpp) -+{ -+ int i; -+ -+ if (bpp == 8) -+ bgx |= bgx << 8; -+ if (bpp == 16 || bpp == 8) -+ bgx |= bgx << 16; -+ -+ while (height-- > 0) { -+ u8 *p = dst; -+ -+ switch (bpp) { -+ -+ case 32: -+ for (i=0; i < width; i++) { -+ fb_writel(bgx, p); p += 4; -+ } -+ break; -+ case 24: -+ for (i=0; i < width; i++) { -+#ifdef __LITTLE_ENDIAN -+ fb_writew((bgx & 0xffff),(u16*)p); p += 2; -+ fb_writeb((bgx >> 16),p++); -+#else -+ fb_writew((bgx >> 8),(u16*)p); p += 2; -+ fb_writeb((bgx & 0xff),p++); -+#endif -+ } -+ case 16: -+ for (i=0; i < width/4; i++) { -+ fb_writel(bgx,p); p += 4; -+ fb_writel(bgx,p); p += 4; -+ } -+ if (width & 2) { -+ fb_writel(bgx,p); p += 4; -+ } -+ if (width & 1) -+ fb_writew(bgx,(u16*)p); -+ break; -+ case 8: -+ for (i=0; i < width/4; i++) { -+ fb_writel(bgx,p); p += 4; -+ } -+ -+ if (width & 2) { -+ fb_writew(bgx,p); p += 2; -+ } -+ if (width & 1) -+ fb_writeb(bgx,(u8*)p); -+ break; -+ -+ } -+ dst += dstbytes; -+ } -+} -+ -+void fbcon_decor_copy(u8 *dst, u8 *src, int height, int width, int linebytes, -+ int srclinebytes, int bpp) -+{ -+ int i; -+ -+ while (height-- > 0) { -+ u32 *p = (u32 *)dst; -+ u32 *q = (u32 *)src; -+ -+ switch (bpp) { -+ -+ case 32: -+ for (i=0; i < width; i++) -+ fb_writel(*q++, p++); -+ break; -+ case 24: -+ for (i=0; i < (width*3/4); i++) -+ fb_writel(*q++, p++); -+ if ((width*3) % 4) { -+ if (width & 2) { -+ fb_writeb(*(u8*)q, (u8*)p); -+ } else if (width & 1) { -+ fb_writew(*(u16*)q, (u16*)p); -+ fb_writeb(*(u8*)((u16*)q+1),(u8*)((u16*)p+2)); -+ } -+ } -+ break; -+ case 16: -+ for (i=0; i < width/4; i++) { -+ fb_writel(*q++, p++); -+ fb_writel(*q++, p++); -+ } -+ if (width & 2) -+ fb_writel(*q++, p++); -+ if (width & 1) -+ fb_writew(*(u16*)q, (u16*)p); -+ break; -+ case 8: -+ for (i=0; i < width/4; i++) -+ fb_writel(*q++, p++); -+ -+ if (width & 2) { -+ fb_writew(*(u16*)q, (u16*)p); -+ q = (u32*) ((u16*)q + 1); -+ p = (u32*) ((u16*)p + 1); -+ } -+ if (width & 1) -+ fb_writeb(*(u8*)q, (u8*)p); -+ break; -+ } -+ -+ dst += linebytes; -+ src += srclinebytes; -+ } -+} -+ -+static void decorfill(struct fb_info *info, int sy, int sx, int height, -+ int width) -+{ -+ int bytespp = ((info->var.bits_per_pixel + 7) >> 3); -+ int d = sy * info->fix.line_length + sx * bytespp; -+ int ds = (sy * info->var.xres + sx) * bytespp; -+ -+ fbcon_decor_copy((u8 *)(info->screen_base + d), (u8 *)(info->bgdecor.data + ds), -+ height, width, info->fix.line_length, info->var.xres * bytespp, -+ info->var.bits_per_pixel); -+} -+ -+void fbcon_decor_clear(struct vc_data *vc, struct fb_info *info, int sy, int sx, -+ int height, int width) -+{ -+ int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; -+ struct fbcon_ops *ops = info->fbcon_par; -+ u8 *dst; -+ int transparent, bg_color = attr_bgcol_ec(bgshift, vc, info); -+ -+ transparent = (vc->vc_decor.bg_color == bg_color); -+ sy = sy * vc->vc_font.height + vc->vc_decor.ty; -+ sx = sx * vc->vc_font.width + vc->vc_decor.tx; -+ height *= vc->vc_font.height; -+ width *= vc->vc_font.width; -+ -+ /* Don't paint the background image if console is blanked */ -+ if (transparent && !ops->blank_state) { -+ decorfill(info, sy, sx, height, width); -+ } else { -+ dst = (u8 *)(info->screen_base + sy * info->fix.line_length + -+ sx * ((info->var.bits_per_pixel + 7) >> 3)); -+ decorset(dst, height, width, info->fix.line_length, cc2cx(bg_color), -+ info->var.bits_per_pixel); -+ } -+} -+ -+void fbcon_decor_clear_margins(struct vc_data *vc, struct fb_info *info, -+ int bottom_only) -+{ -+ unsigned int tw = vc->vc_cols*vc->vc_font.width; -+ unsigned int th = vc->vc_rows*vc->vc_font.height; -+ -+ if (!bottom_only) { -+ /* top margin */ -+ decorfill(info, 0, 0, vc->vc_decor.ty, info->var.xres); -+ /* left margin */ -+ decorfill(info, vc->vc_decor.ty, 0, th, vc->vc_decor.tx); -+ /* right margin */ -+ decorfill(info, vc->vc_decor.ty, vc->vc_decor.tx + tw, th, -+ info->var.xres - vc->vc_decor.tx - tw); -+ } -+ decorfill(info, vc->vc_decor.ty + th, 0, -+ info->var.yres - vc->vc_decor.ty - th, info->var.xres); -+} -+ -+void fbcon_decor_bmove_redraw(struct vc_data *vc, struct fb_info *info, int y, -+ int sx, int dx, int width) -+{ -+ u16 *d = (u16 *) (vc->vc_origin + vc->vc_size_row * y + dx * 2); -+ u16 *s = d + (dx - sx); -+ u16 *start = d; -+ u16 *ls = d; -+ u16 *le = d + width; -+ u16 c; -+ int x = dx; -+ u16 attr = 1; -+ -+ do { -+ c = scr_readw(d); -+ if (attr != (c & 0xff00)) { -+ attr = c & 0xff00; -+ if (d > start) { -+ fbcon_decor_putcs(vc, info, start, d - start, y, x); -+ x += d - start; -+ start = d; -+ } -+ } -+ if (s >= ls && s < le && c == scr_readw(s)) { -+ if (d > start) { -+ fbcon_decor_putcs(vc, info, start, d - start, y, x); -+ x += d - start + 1; -+ start = d + 1; -+ } else { -+ x++; -+ start++; -+ } -+ } -+ s++; -+ d++; -+ } while (d < le); -+ if (d > start) -+ fbcon_decor_putcs(vc, info, start, d - start, y, x); -+} -+ -+void fbcon_decor_blank(struct vc_data *vc, struct fb_info *info, int blank) -+{ -+ if (blank) { -+ decorset((u8 *)info->screen_base, info->var.yres, info->var.xres, -+ info->fix.line_length, 0, info->var.bits_per_pixel); -+ } else { -+ update_screen(vc); -+ fbcon_decor_clear_margins(vc, info, 0); -+ } -+} -+ -diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c -index f447734..da50d61 100644 ---- a/drivers/video/console/fbcon.c -+++ b/drivers/video/console/fbcon.c -@@ -79,6 +79,7 @@ - #include - - #include "fbcon.h" -+#include "../console/fbcondecor.h" - - #ifdef FBCONDEBUG - # define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __func__ , ## args) -@@ -94,7 +95,7 @@ enum { - - static struct display fb_display[MAX_NR_CONSOLES]; - --static signed char con2fb_map[MAX_NR_CONSOLES]; -+signed char con2fb_map[MAX_NR_CONSOLES]; - static signed char con2fb_map_boot[MAX_NR_CONSOLES]; - - static int logo_lines; -@@ -286,7 +287,7 @@ static inline int fbcon_is_inactive(struct vc_data *vc, struct fb_info *info) - !vt_force_oops_output(vc); - } - --static int get_color(struct vc_data *vc, struct fb_info *info, -+int get_color(struct vc_data *vc, struct fb_info *info, - u16 c, int is_fg) - { - int depth = fb_get_color_depth(&info->var, &info->fix); -@@ -551,6 +552,9 @@ static int do_fbcon_takeover(int show_logo) - info_idx = -1; - } else { - fbcon_has_console_bind = 1; -+#ifdef CONFIG_FB_CON_DECOR -+ fbcon_decor_init(); -+#endif - } - - return err; -@@ -1007,6 +1011,12 @@ static const char *fbcon_startup(void) - rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); - cols /= vc->vc_font.width; - rows /= vc->vc_font.height; -+ -+ if (fbcon_decor_active(info, vc)) { -+ cols = vc->vc_decor.twidth / vc->vc_font.width; -+ rows = vc->vc_decor.theight / vc->vc_font.height; -+ } -+ - vc_resize(vc, cols, rows); - - DPRINTK("mode: %s\n", info->fix.id); -@@ -1036,7 +1046,7 @@ static void fbcon_init(struct vc_data *vc, int init) - cap = info->flags; - - if (vc != svc || logo_shown == FBCON_LOGO_DONTSHOW || -- (info->fix.type == FB_TYPE_TEXT)) -+ (info->fix.type == FB_TYPE_TEXT) || fbcon_decor_active(info, vc)) - logo = 0; - - if (var_to_display(p, &info->var, info)) -@@ -1260,6 +1270,11 @@ static void fbcon_clear(struct vc_data *vc, int sy, int sx, int height, - fbcon_clear_margins(vc, 0); - } - -+ if (fbcon_decor_active(info, vc)) { -+ fbcon_decor_clear(vc, info, sy, sx, height, width); -+ return; -+ } -+ - /* Split blits that cross physical y_wrap boundary */ - - y_break = p->vrows - p->yscroll; -@@ -1279,10 +1294,15 @@ static void fbcon_putcs(struct vc_data *vc, const unsigned short *s, - struct display *p = &fb_display[vc->vc_num]; - struct fbcon_ops *ops = info->fbcon_par; - -- if (!fbcon_is_inactive(vc, info)) -- ops->putcs(vc, info, s, count, real_y(p, ypos), xpos, -- get_color(vc, info, scr_readw(s), 1), -- get_color(vc, info, scr_readw(s), 0)); -+ if (!fbcon_is_inactive(vc, info)) { -+ -+ if (fbcon_decor_active(info, vc)) -+ fbcon_decor_putcs(vc, info, s, count, ypos, xpos); -+ else -+ ops->putcs(vc, info, s, count, real_y(p, ypos), xpos, -+ get_color(vc, info, scr_readw(s), 1), -+ get_color(vc, info, scr_readw(s), 0)); -+ } - } - - static void fbcon_putc(struct vc_data *vc, int c, int ypos, int xpos) -@@ -1298,8 +1318,13 @@ static void fbcon_clear_margins(struct vc_data *vc, int bottom_only) - struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; - struct fbcon_ops *ops = info->fbcon_par; - -- if (!fbcon_is_inactive(vc, info)) -- ops->clear_margins(vc, info, bottom_only); -+ if (!fbcon_is_inactive(vc, info)) { -+ if (fbcon_decor_active(info, vc)) { -+ fbcon_decor_clear_margins(vc, info, bottom_only); -+ } else { -+ ops->clear_margins(vc, info, bottom_only); -+ } -+ } - } - - static void fbcon_cursor(struct vc_data *vc, int mode) -@@ -1819,7 +1844,7 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir, - count = vc->vc_rows; - if (softback_top) - fbcon_softback_note(vc, t, count); -- if (logo_shown >= 0) -+ if (logo_shown >= 0 || fbcon_decor_active(info, vc)) - goto redraw_up; - switch (p->scrollmode) { - case SCROLL_MOVE: -@@ -1912,6 +1937,8 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir, - count = vc->vc_rows; - if (logo_shown >= 0) - goto redraw_down; -+ if (fbcon_decor_active(info, vc)) -+ goto redraw_down; - switch (p->scrollmode) { - case SCROLL_MOVE: - fbcon_redraw_blit(vc, info, p, b - 1, b - t - count, -@@ -2060,6 +2087,13 @@ static void fbcon_bmove_rec(struct vc_data *vc, struct display *p, int sy, int s - } - return; - } -+ -+ if (fbcon_decor_active(info, vc) && sy == dy && height == 1) { -+ /* must use slower redraw bmove to keep background pic intact */ -+ fbcon_decor_bmove_redraw(vc, info, sy, sx, dx, width); -+ return; -+ } -+ - ops->bmove(vc, info, real_y(p, sy), sx, real_y(p, dy), dx, - height, width); - } -@@ -2130,8 +2164,8 @@ static int fbcon_resize(struct vc_data *vc, unsigned int width, - var.yres = virt_h * virt_fh; - x_diff = info->var.xres - var.xres; - y_diff = info->var.yres - var.yres; -- if (x_diff < 0 || x_diff > virt_fw || -- y_diff < 0 || y_diff > virt_fh) { -+ if ((x_diff < 0 || x_diff > virt_fw || -+ y_diff < 0 || y_diff > virt_fh) && !vc->vc_decor.state) { - const struct fb_videomode *mode; - - DPRINTK("attempting resize %ix%i\n", var.xres, var.yres); -@@ -2167,6 +2201,21 @@ static int fbcon_switch(struct vc_data *vc) - - info = registered_fb[con2fb_map[vc->vc_num]]; - ops = info->fbcon_par; -+ prev_console = ops->currcon; -+ if (prev_console != -1) -+ old_info = registered_fb[con2fb_map[prev_console]]; -+ -+#ifdef CONFIG_FB_CON_DECOR -+ if (!fbcon_decor_active_vc(vc) && info->fix.visual == FB_VISUAL_DIRECTCOLOR) { -+ struct vc_data *vc_curr = vc_cons[prev_console].d; -+ if (vc_curr && fbcon_decor_active_vc(vc_curr)) { -+ /* Clear the screen to avoid displaying funky colors during -+ * palette updates. */ -+ memset((u8*)info->screen_base + info->fix.line_length * info->var.yoffset, -+ 0, info->var.yres * info->fix.line_length); -+ } -+ } -+#endif - - if (softback_top) { - if (softback_lines) -@@ -2185,9 +2234,6 @@ static int fbcon_switch(struct vc_data *vc) - logo_shown = FBCON_LOGO_CANSHOW; - } - -- prev_console = ops->currcon; -- if (prev_console != -1) -- old_info = registered_fb[con2fb_map[prev_console]]; - /* - * FIXME: If we have multiple fbdev's loaded, we need to - * update all info->currcon. Perhaps, we can place this -@@ -2231,6 +2277,18 @@ static int fbcon_switch(struct vc_data *vc) - fbcon_del_cursor_timer(old_info); - } - -+ if (fbcon_decor_active_vc(vc)) { -+ struct vc_data *vc_curr = vc_cons[prev_console].d; -+ -+ if (!vc_curr->vc_decor.theme || -+ strcmp(vc->vc_decor.theme, vc_curr->vc_decor.theme) || -+ (fbcon_decor_active_nores(info, vc_curr) && -+ !fbcon_decor_active(info, vc_curr))) { -+ fbcon_decor_disable(vc, 0); -+ fbcon_decor_call_helper("modechange", vc->vc_num); -+ } -+ } -+ - if (fbcon_is_inactive(vc, info) || - ops->blank_state != FB_BLANK_UNBLANK) - fbcon_del_cursor_timer(info); -@@ -2339,15 +2397,20 @@ static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch) - } - } - -- if (!fbcon_is_inactive(vc, info)) { -+ if (!fbcon_is_inactive(vc, info)) { - if (ops->blank_state != blank) { - ops->blank_state = blank; - fbcon_cursor(vc, blank ? CM_ERASE : CM_DRAW); - ops->cursor_flash = (!blank); - -- if (!(info->flags & FBINFO_MISC_USEREVENT)) -- if (fb_blank(info, blank)) -- fbcon_generic_blank(vc, info, blank); -+ if (!(info->flags & FBINFO_MISC_USEREVENT)) { -+ if (fb_blank(info, blank)) { -+ if (fbcon_decor_active(info, vc)) -+ fbcon_decor_blank(vc, info, blank); -+ else -+ fbcon_generic_blank(vc, info, blank); -+ } -+ } - } - - if (!blank) -@@ -2522,13 +2585,22 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h, - } - - if (resize) { -+ /* reset wrap/pan */ - int cols, rows; - - cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres); - rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); -+ -+ if (fbcon_decor_active(info, vc)) { -+ info->var.xoffset = info->var.yoffset = p->yscroll = 0; -+ cols = vc->vc_decor.twidth; -+ rows = vc->vc_decor.theight; -+ } - cols /= w; - rows /= h; -+ - vc_resize(vc, cols, rows); -+ - if (CON_IS_VISIBLE(vc) && softback_buf) - fbcon_update_softback(vc); - } else if (CON_IS_VISIBLE(vc) -@@ -2657,7 +2729,11 @@ static int fbcon_set_palette(struct vc_data *vc, unsigned char *table) - int i, j, k, depth; - u8 val; - -- if (fbcon_is_inactive(vc, info)) -+ if (fbcon_is_inactive(vc, info) -+#ifdef CONFIG_FB_CON_DECOR -+ || vc->vc_num != fg_console -+#endif -+ ) - return -EINVAL; - - if (!CON_IS_VISIBLE(vc)) -@@ -2683,14 +2759,56 @@ static int fbcon_set_palette(struct vc_data *vc, unsigned char *table) - } else - fb_copy_cmap(fb_default_cmap(1 << depth), &palette_cmap); - -- return fb_set_cmap(&palette_cmap, info); -+ if (fbcon_decor_active(info, vc_cons[fg_console].d) && -+ info->fix.visual == FB_VISUAL_DIRECTCOLOR) { -+ -+ u16 *red, *green, *blue; -+ int minlen = min(min(info->var.red.length, info->var.green.length), -+ info->var.blue.length); -+ int h; -+ -+ struct fb_cmap cmap = { -+ .start = 0, -+ .len = (1 << minlen), -+ .red = NULL, -+ .green = NULL, -+ .blue = NULL, -+ .transp = NULL -+ }; -+ -+ red = kmalloc(256 * sizeof(u16) * 3, GFP_KERNEL); -+ -+ if (!red) -+ goto out; -+ -+ green = red + 256; -+ blue = green + 256; -+ cmap.red = red; -+ cmap.green = green; -+ cmap.blue = blue; -+ -+ for (i = 0; i < cmap.len; i++) { -+ red[i] = green[i] = blue[i] = (0xffff * i)/(cmap.len-1); -+ } -+ -+ h = fb_set_cmap(&cmap, info); -+ fbcon_decor_fix_pseudo_pal(info, vc_cons[fg_console].d); -+ kfree(red); -+ -+ return h; -+ -+ } else if (fbcon_decor_active(info, vc_cons[fg_console].d) && -+ info->var.bits_per_pixel == 8 && info->bgdecor.cmap.red != NULL) -+ fb_set_cmap(&info->bgdecor.cmap, info); -+ -+out: return fb_set_cmap(&palette_cmap, info); - } - - static u16 *fbcon_screen_pos(struct vc_data *vc, int offset) - { - unsigned long p; - int line; -- -+ - if (vc->vc_num != fg_console || !softback_lines) - return (u16 *) (vc->vc_origin + offset); - line = offset / vc->vc_size_row; -@@ -2909,7 +3027,14 @@ static void fbcon_modechanged(struct fb_info *info) - rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); - cols /= vc->vc_font.width; - rows /= vc->vc_font.height; -- vc_resize(vc, cols, rows); -+ -+ if (!fbcon_decor_active_nores(info, vc)) { -+ vc_resize(vc, cols, rows); -+ } else { -+ fbcon_decor_disable(vc, 0); -+ fbcon_decor_call_helper("modechange", vc->vc_num); -+ } -+ - updatescrollmode(p, info, vc); - scrollback_max = 0; - scrollback_current = 0; -@@ -2954,7 +3079,9 @@ static void fbcon_set_all_vcs(struct fb_info *info) - rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); - cols /= vc->vc_font.width; - rows /= vc->vc_font.height; -- vc_resize(vc, cols, rows); -+ if (!fbcon_decor_active_nores(info, vc)) { -+ vc_resize(vc, cols, rows); -+ } - } - - if (fg != -1) -@@ -3596,6 +3723,7 @@ static void fbcon_exit(void) - } - } - -+ fbcon_decor_exit(); - fbcon_has_exited = 1; - } - -diff --git a/drivers/video/console/fbcondecor.c b/drivers/video/console/fbcondecor.c -new file mode 100644 -index 0000000..babc8c5 ---- /dev/null -+++ b/drivers/video/console/fbcondecor.c -@@ -0,0 +1,555 @@ -+/* -+ * linux/drivers/video/console/fbcondecor.c -- Framebuffer console decorations -+ * -+ * Copyright (C) 2004-2009 Michal Januszewski -+ * -+ * Code based upon "Bootsplash" (C) 2001-2003 -+ * Volker Poplawski , -+ * Stefan Reinauer , -+ * Steffen Winterfeldt , -+ * Michael Schroeder , -+ * Ken Wimer . -+ * -+ * Compat ioctl support by Thorsten Klein . -+ * -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file COPYING in the main directory of this archive for -+ * more details. -+ * -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+#include "fbcon.h" -+#include "fbcondecor.h" -+ -+extern signed char con2fb_map[]; -+static int fbcon_decor_enable(struct vc_data *vc); -+char fbcon_decor_path[KMOD_PATH_LEN] = "/sbin/fbcondecor_helper"; -+static int initialized = 0; -+ -+int fbcon_decor_call_helper(char* cmd, unsigned short vc) -+{ -+ char *envp[] = { -+ "HOME=/", -+ "PATH=/sbin:/bin", -+ NULL -+ }; -+ -+ char tfb[5]; -+ char tcons[5]; -+ unsigned char fb = (int) con2fb_map[vc]; -+ -+ char *argv[] = { -+ fbcon_decor_path, -+ "2", -+ cmd, -+ tcons, -+ tfb, -+ vc_cons[vc].d->vc_decor.theme, -+ NULL -+ }; -+ -+ snprintf(tfb,5,"%d",fb); -+ snprintf(tcons,5,"%d",vc); -+ -+ return call_usermodehelper(fbcon_decor_path, argv, envp, UMH_WAIT_EXEC); -+} -+ -+/* Disables fbcondecor on a virtual console; called with console sem held. */ -+int fbcon_decor_disable(struct vc_data *vc, unsigned char redraw) -+{ -+ struct fb_info* info; -+ -+ if (!vc->vc_decor.state) -+ return -EINVAL; -+ -+ info = registered_fb[(int) con2fb_map[vc->vc_num]]; -+ -+ if (info == NULL) -+ return -EINVAL; -+ -+ vc->vc_decor.state = 0; -+ vc_resize(vc, info->var.xres / vc->vc_font.width, -+ info->var.yres / vc->vc_font.height); -+ -+ if (fg_console == vc->vc_num && redraw) { -+ redraw_screen(vc, 0); -+ update_region(vc, vc->vc_origin + -+ vc->vc_size_row * vc->vc_top, -+ vc->vc_size_row * (vc->vc_bottom - vc->vc_top) / 2); -+ } -+ -+ printk(KERN_INFO "fbcondecor: switched decor state to 'off' on console %d\n", -+ vc->vc_num); -+ -+ return 0; -+} -+ -+/* Enables fbcondecor on a virtual console; called with console sem held. */ -+static int fbcon_decor_enable(struct vc_data *vc) -+{ -+ struct fb_info* info; -+ -+ info = registered_fb[(int) con2fb_map[vc->vc_num]]; -+ -+ if (vc->vc_decor.twidth == 0 || vc->vc_decor.theight == 0 || -+ info == NULL || vc->vc_decor.state || (!info->bgdecor.data && -+ vc->vc_num == fg_console)) -+ return -EINVAL; -+ -+ vc->vc_decor.state = 1; -+ vc_resize(vc, vc->vc_decor.twidth / vc->vc_font.width, -+ vc->vc_decor.theight / vc->vc_font.height); -+ -+ if (fg_console == vc->vc_num) { -+ redraw_screen(vc, 0); -+ update_region(vc, vc->vc_origin + -+ vc->vc_size_row * vc->vc_top, -+ vc->vc_size_row * (vc->vc_bottom - vc->vc_top) / 2); -+ fbcon_decor_clear_margins(vc, info, 0); -+ } -+ -+ printk(KERN_INFO "fbcondecor: switched decor state to 'on' on console %d\n", -+ vc->vc_num); -+ -+ return 0; -+} -+ -+static inline int fbcon_decor_ioctl_dosetstate(struct vc_data *vc, unsigned int state, unsigned char origin) -+{ -+ int ret; -+ -+// if (origin == FBCON_DECOR_IO_ORIG_USER) -+ console_lock(); -+ if (!state) -+ ret = fbcon_decor_disable(vc, 1); -+ else -+ ret = fbcon_decor_enable(vc); -+// if (origin == FBCON_DECOR_IO_ORIG_USER) -+ console_unlock(); -+ -+ return ret; -+} -+ -+static inline void fbcon_decor_ioctl_dogetstate(struct vc_data *vc, unsigned int *state) -+{ -+ *state = vc->vc_decor.state; -+} -+ -+static int fbcon_decor_ioctl_dosetcfg(struct vc_data *vc, struct vc_decor *cfg, unsigned char origin) -+{ -+ struct fb_info *info; -+ int len; -+ char *tmp; -+ -+ info = registered_fb[(int) con2fb_map[vc->vc_num]]; -+ -+ if (info == NULL || !cfg->twidth || !cfg->theight || -+ cfg->tx + cfg->twidth > info->var.xres || -+ cfg->ty + cfg->theight > info->var.yres) -+ return -EINVAL; -+ -+ len = strlen_user(cfg->theme); -+ if (!len || len > FBCON_DECOR_THEME_LEN) -+ return -EINVAL; -+ tmp = kmalloc(len, GFP_KERNEL); -+ if (!tmp) -+ return -ENOMEM; -+ if (copy_from_user(tmp, (void __user *)cfg->theme, len)) -+ return -EFAULT; -+ cfg->theme = tmp; -+ cfg->state = 0; -+ -+ /* If this ioctl is a response to a request from kernel, the console sem -+ * is already held; we also don't need to disable decor because either the -+ * new config and background picture will be successfully loaded, and the -+ * decor will stay on, or in case of a failure it'll be turned off in fbcon. */ -+// if (origin == FBCON_DECOR_IO_ORIG_USER) { -+ console_lock(); -+ if (vc->vc_decor.state) -+ fbcon_decor_disable(vc, 1); -+// } -+ -+ if (vc->vc_decor.theme) -+ kfree(vc->vc_decor.theme); -+ -+ vc->vc_decor = *cfg; -+ -+// if (origin == FBCON_DECOR_IO_ORIG_USER) -+ console_unlock(); -+ -+ printk(KERN_INFO "fbcondecor: console %d using theme '%s'\n", -+ vc->vc_num, vc->vc_decor.theme); -+ return 0; -+} -+ -+static int fbcon_decor_ioctl_dogetcfg(struct vc_data *vc, struct vc_decor *decor) -+{ -+ char __user *tmp; -+ -+ tmp = decor->theme; -+ *decor = vc->vc_decor; -+ decor->theme = tmp; -+ -+ if (vc->vc_decor.theme) { -+ if (copy_to_user(tmp, vc->vc_decor.theme, strlen(vc->vc_decor.theme) + 1)) -+ return -EFAULT; -+ } else -+ if (put_user(0, tmp)) -+ return -EFAULT; -+ -+ return 0; -+} -+ -+static int fbcon_decor_ioctl_dosetpic(struct vc_data *vc, struct fb_image *img, unsigned char origin) -+{ -+ struct fb_info *info; -+ int len; -+ u8 *tmp; -+ -+ if (vc->vc_num != fg_console) -+ return -EINVAL; -+ -+ info = registered_fb[(int) con2fb_map[vc->vc_num]]; -+ -+ if (info == NULL) -+ return -EINVAL; -+ -+ if (img->width != info->var.xres || img->height != info->var.yres) { -+ printk(KERN_ERR "fbcondecor: picture dimensions mismatch\n"); -+ printk(KERN_ERR "%dx%d vs %dx%d\n", img->width, img->height, info->var.xres, info->var.yres); -+ return -EINVAL; -+ } -+ -+ if (img->depth != info->var.bits_per_pixel) { -+ printk(KERN_ERR "fbcondecor: picture depth mismatch\n"); -+ return -EINVAL; -+ } -+ -+ if (img->depth == 8) { -+ if (!img->cmap.len || !img->cmap.red || !img->cmap.green || -+ !img->cmap.blue) -+ return -EINVAL; -+ -+ tmp = vmalloc(img->cmap.len * 3 * 2); -+ if (!tmp) -+ return -ENOMEM; -+ -+ if (copy_from_user(tmp, -+ (void __user*)img->cmap.red, (img->cmap.len << 1)) || -+ copy_from_user(tmp + (img->cmap.len << 1), -+ (void __user*)img->cmap.green, (img->cmap.len << 1)) || -+ copy_from_user(tmp + (img->cmap.len << 2), -+ (void __user*)img->cmap.blue, (img->cmap.len << 1))) { -+ vfree(tmp); -+ return -EFAULT; -+ } -+ -+ img->cmap.transp = NULL; -+ img->cmap.red = (u16*)tmp; -+ img->cmap.green = img->cmap.red + img->cmap.len; -+ img->cmap.blue = img->cmap.green + img->cmap.len; -+ } else { -+ img->cmap.red = NULL; -+ } -+ -+ len = ((img->depth + 7) >> 3) * img->width * img->height; -+ -+ /* -+ * Allocate an additional byte so that we never go outside of the -+ * buffer boundaries in the rendering functions in a 24 bpp mode. -+ */ -+ tmp = vmalloc(len + 1); -+ -+ if (!tmp) -+ goto out; -+ -+ if (copy_from_user(tmp, (void __user*)img->data, len)) -+ goto out; -+ -+ img->data = tmp; -+ -+ /* If this ioctl is a response to a request from kernel, the console sem -+ * is already held. */ -+// if (origin == FBCON_DECOR_IO_ORIG_USER) -+ console_lock(); -+ -+ if (info->bgdecor.data) -+ vfree((u8*)info->bgdecor.data); -+ if (info->bgdecor.cmap.red) -+ vfree(info->bgdecor.cmap.red); -+ -+ info->bgdecor = *img; -+ -+ if (fbcon_decor_active_vc(vc) && fg_console == vc->vc_num) { -+ redraw_screen(vc, 0); -+ update_region(vc, vc->vc_origin + -+ vc->vc_size_row * vc->vc_top, -+ vc->vc_size_row * (vc->vc_bottom - vc->vc_top) / 2); -+ fbcon_decor_clear_margins(vc, info, 0); -+ } -+ -+// if (origin == FBCON_DECOR_IO_ORIG_USER) -+ console_unlock(); -+ -+ return 0; -+ -+out: if (img->cmap.red) -+ vfree(img->cmap.red); -+ -+ if (tmp) -+ vfree(tmp); -+ return -ENOMEM; -+} -+ -+static long fbcon_decor_ioctl(struct file *filp, u_int cmd, u_long arg) -+{ -+ struct fbcon_decor_iowrapper __user *wrapper = (void __user*) arg; -+ struct vc_data *vc = NULL; -+ unsigned short vc_num = 0; -+ unsigned char origin = 0; -+ void __user *data = NULL; -+ -+ if (!access_ok(VERIFY_READ, wrapper, -+ sizeof(struct fbcon_decor_iowrapper))) -+ return -EFAULT; -+ -+ __get_user(vc_num, &wrapper->vc); -+ __get_user(origin, &wrapper->origin); -+ __get_user(data, &wrapper->data); -+ -+ if (!vc_cons_allocated(vc_num)) -+ return -EINVAL; -+ -+ vc = vc_cons[vc_num].d; -+ -+ switch (cmd) { -+ case FBIOCONDECOR_SETPIC: -+ { -+ struct fb_image img; -+ if (copy_from_user(&img, (struct fb_image __user *)data, sizeof(struct fb_image))) -+ return -EFAULT; -+ -+ return fbcon_decor_ioctl_dosetpic(vc, &img, origin); -+ } -+ case FBIOCONDECOR_SETCFG: -+ { -+ struct vc_decor cfg; -+ if (copy_from_user(&cfg, (struct vc_decor __user *)data, sizeof(struct vc_decor))) -+ return -EFAULT; -+ -+ return fbcon_decor_ioctl_dosetcfg(vc, &cfg, origin); -+ } -+ case FBIOCONDECOR_GETCFG: -+ { -+ int rval; -+ struct vc_decor cfg; -+ -+ if (copy_from_user(&cfg, (struct vc_decor __user *)data, sizeof(struct vc_decor))) -+ return -EFAULT; -+ -+ rval = fbcon_decor_ioctl_dogetcfg(vc, &cfg); -+ -+ if (copy_to_user(data, &cfg, sizeof(struct vc_decor))) -+ return -EFAULT; -+ return rval; -+ } -+ case FBIOCONDECOR_SETSTATE: -+ { -+ unsigned int state = 0; -+ if (get_user(state, (unsigned int __user *)data)) -+ return -EFAULT; -+ return fbcon_decor_ioctl_dosetstate(vc, state, origin); -+ } -+ case FBIOCONDECOR_GETSTATE: -+ { -+ unsigned int state = 0; -+ fbcon_decor_ioctl_dogetstate(vc, &state); -+ return put_user(state, (unsigned int __user *)data); -+ } -+ -+ default: -+ return -ENOIOCTLCMD; -+ } -+} -+ -+#ifdef CONFIG_COMPAT -+ -+static long fbcon_decor_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { -+ -+ struct fbcon_decor_iowrapper32 __user *wrapper = (void __user *)arg; -+ struct vc_data *vc = NULL; -+ unsigned short vc_num = 0; -+ unsigned char origin = 0; -+ compat_uptr_t data_compat = 0; -+ void __user *data = NULL; -+ -+ if (!access_ok(VERIFY_READ, wrapper, -+ sizeof(struct fbcon_decor_iowrapper32))) -+ return -EFAULT; -+ -+ __get_user(vc_num, &wrapper->vc); -+ __get_user(origin, &wrapper->origin); -+ __get_user(data_compat, &wrapper->data); -+ data = compat_ptr(data_compat); -+ -+ if (!vc_cons_allocated(vc_num)) -+ return -EINVAL; -+ -+ vc = vc_cons[vc_num].d; -+ -+ switch (cmd) { -+ case FBIOCONDECOR_SETPIC32: -+ { -+ struct fb_image32 img_compat; -+ struct fb_image img; -+ -+ if (copy_from_user(&img_compat, (struct fb_image32 __user *)data, sizeof(struct fb_image32))) -+ return -EFAULT; -+ -+ fb_image_from_compat(img, img_compat); -+ -+ return fbcon_decor_ioctl_dosetpic(vc, &img, origin); -+ } -+ -+ case FBIOCONDECOR_SETCFG32: -+ { -+ struct vc_decor32 cfg_compat; -+ struct vc_decor cfg; -+ -+ if (copy_from_user(&cfg_compat, (struct vc_decor32 __user *)data, sizeof(struct vc_decor32))) -+ return -EFAULT; -+ -+ vc_decor_from_compat(cfg, cfg_compat); -+ -+ return fbcon_decor_ioctl_dosetcfg(vc, &cfg, origin); -+ } -+ -+ case FBIOCONDECOR_GETCFG32: -+ { -+ int rval; -+ struct vc_decor32 cfg_compat; -+ struct vc_decor cfg; -+ -+ if (copy_from_user(&cfg_compat, (struct vc_decor32 __user *)data, sizeof(struct vc_decor32))) -+ return -EFAULT; -+ cfg.theme = compat_ptr(cfg_compat.theme); -+ -+ rval = fbcon_decor_ioctl_dogetcfg(vc, &cfg); -+ -+ vc_decor_to_compat(cfg_compat, cfg); -+ -+ if (copy_to_user((struct vc_decor32 __user *)data, &cfg_compat, sizeof(struct vc_decor32))) -+ return -EFAULT; -+ return rval; -+ } -+ -+ case FBIOCONDECOR_SETSTATE32: -+ { -+ compat_uint_t state_compat = 0; -+ unsigned int state = 0; -+ -+ if (get_user(state_compat, (compat_uint_t __user *)data)) -+ return -EFAULT; -+ -+ state = (unsigned int)state_compat; -+ -+ return fbcon_decor_ioctl_dosetstate(vc, state, origin); -+ } -+ -+ case FBIOCONDECOR_GETSTATE32: -+ { -+ compat_uint_t state_compat = 0; -+ unsigned int state = 0; -+ -+ fbcon_decor_ioctl_dogetstate(vc, &state); -+ state_compat = (compat_uint_t)state; -+ -+ return put_user(state_compat, (compat_uint_t __user *)data); -+ } -+ -+ default: -+ return -ENOIOCTLCMD; -+ } -+} -+#else -+ #define fbcon_decor_compat_ioctl NULL -+#endif -+ -+static struct file_operations fbcon_decor_ops = { -+ .owner = THIS_MODULE, -+ .unlocked_ioctl = fbcon_decor_ioctl, -+ .compat_ioctl = fbcon_decor_compat_ioctl -+}; -+ -+static struct miscdevice fbcon_decor_dev = { -+ .minor = MISC_DYNAMIC_MINOR, -+ .name = "fbcondecor", -+ .fops = &fbcon_decor_ops -+}; -+ -+void fbcon_decor_reset(void) -+{ -+ int i; -+ -+ for (i = 0; i < num_registered_fb; i++) { -+ registered_fb[i]->bgdecor.data = NULL; -+ registered_fb[i]->bgdecor.cmap.red = NULL; -+ } -+ -+ for (i = 0; i < MAX_NR_CONSOLES && vc_cons[i].d; i++) { -+ vc_cons[i].d->vc_decor.state = vc_cons[i].d->vc_decor.twidth = -+ vc_cons[i].d->vc_decor.theight = 0; -+ vc_cons[i].d->vc_decor.theme = NULL; -+ } -+ -+ return; -+} -+ -+int fbcon_decor_init(void) -+{ -+ int i; -+ -+ fbcon_decor_reset(); -+ -+ if (initialized) -+ return 0; -+ -+ i = misc_register(&fbcon_decor_dev); -+ if (i) { -+ printk(KERN_ERR "fbcondecor: failed to register device\n"); -+ return i; -+ } -+ -+ fbcon_decor_call_helper("init", 0); -+ initialized = 1; -+ return 0; -+} -+ -+int fbcon_decor_exit(void) -+{ -+ fbcon_decor_reset(); -+ return 0; -+} -+ -+EXPORT_SYMBOL(fbcon_decor_path); -diff --git a/drivers/video/console/fbcondecor.h b/drivers/video/console/fbcondecor.h -new file mode 100644 -index 0000000..3b3724b ---- /dev/null -+++ b/drivers/video/console/fbcondecor.h -@@ -0,0 +1,78 @@ -+/* -+ * linux/drivers/video/console/fbcondecor.h -- Framebuffer Console Decoration headers -+ * -+ * Copyright (C) 2004 Michal Januszewski -+ * -+ */ -+ -+#ifndef __FBCON_DECOR_H -+#define __FBCON_DECOR_H -+ -+#ifndef _LINUX_FB_H -+#include -+#endif -+ -+/* This is needed for vc_cons in fbcmap.c */ -+#include -+ -+struct fb_cursor; -+struct fb_info; -+struct vc_data; -+ -+#ifdef CONFIG_FB_CON_DECOR -+/* fbcondecor.c */ -+int fbcon_decor_init(void); -+int fbcon_decor_exit(void); -+int fbcon_decor_call_helper(char* cmd, unsigned short cons); -+int fbcon_decor_disable(struct vc_data *vc, unsigned char redraw); -+ -+/* cfbcondecor.c */ -+void fbcon_decor_putcs(struct vc_data *vc, struct fb_info *info, const unsigned short *s, int count, int yy, int xx); -+void fbcon_decor_cursor(struct fb_info *info, struct fb_cursor *cursor); -+void fbcon_decor_clear(struct vc_data *vc, struct fb_info *info, int sy, int sx, int height, int width); -+void fbcon_decor_clear_margins(struct vc_data *vc, struct fb_info *info, int bottom_only); -+void fbcon_decor_blank(struct vc_data *vc, struct fb_info *info, int blank); -+void fbcon_decor_bmove_redraw(struct vc_data *vc, struct fb_info *info, int y, int sx, int dx, int width); -+void fbcon_decor_copy(u8 *dst, u8 *src, int height, int width, int linebytes, int srclinesbytes, int bpp); -+void fbcon_decor_fix_pseudo_pal(struct fb_info *info, struct vc_data *vc); -+ -+/* vt.c */ -+void acquire_console_sem(void); -+void release_console_sem(void); -+void do_unblank_screen(int entering_gfx); -+ -+/* struct vc_data *y */ -+#define fbcon_decor_active_vc(y) (y->vc_decor.state && y->vc_decor.theme) -+ -+/* struct fb_info *x, struct vc_data *y */ -+#define fbcon_decor_active_nores(x,y) (x->bgdecor.data && fbcon_decor_active_vc(y)) -+ -+/* struct fb_info *x, struct vc_data *y */ -+#define fbcon_decor_active(x,y) (fbcon_decor_active_nores(x,y) && \ -+ x->bgdecor.width == x->var.xres && \ -+ x->bgdecor.height == x->var.yres && \ -+ x->bgdecor.depth == x->var.bits_per_pixel) -+ -+ -+#else /* CONFIG_FB_CON_DECOR */ -+ -+static inline void fbcon_decor_putcs(struct vc_data *vc, struct fb_info *info, const unsigned short *s, int count, int yy, int xx) {} -+static inline void fbcon_decor_putc(struct vc_data *vc, struct fb_info *info, int c, int ypos, int xpos) {} -+static inline void fbcon_decor_cursor(struct fb_info *info, struct fb_cursor *cursor) {} -+static inline void fbcon_decor_clear(struct vc_data *vc, struct fb_info *info, int sy, int sx, int height, int width) {} -+static inline void fbcon_decor_clear_margins(struct vc_data *vc, struct fb_info *info, int bottom_only) {} -+static inline void fbcon_decor_blank(struct vc_data *vc, struct fb_info *info, int blank) {} -+static inline void fbcon_decor_bmove_redraw(struct vc_data *vc, struct fb_info *info, int y, int sx, int dx, int width) {} -+static inline void fbcon_decor_fix_pseudo_pal(struct fb_info *info, struct vc_data *vc) {} -+static inline int fbcon_decor_call_helper(char* cmd, unsigned short cons) { return 0; } -+static inline int fbcon_decor_init(void) { return 0; } -+static inline int fbcon_decor_exit(void) { return 0; } -+static inline int fbcon_decor_disable(struct vc_data *vc, unsigned char redraw) { return 0; } -+ -+#define fbcon_decor_active_vc(y) (0) -+#define fbcon_decor_active_nores(x,y) (0) -+#define fbcon_decor_active(x,y) (0) -+ -+#endif /* CONFIG_FB_CON_DECOR */ -+ -+#endif /* __FBCON_DECOR_H */ -diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig -index e1f4727..2952e33 100644 ---- a/drivers/video/fbdev/Kconfig -+++ b/drivers/video/fbdev/Kconfig -@@ -1204,7 +1204,6 @@ config FB_MATROX - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT -- select FB_TILEBLITTING - select FB_MACMODES if PPC_PMAC - ---help--- - Say Y here if you have a Matrox Millennium, Matrox Millennium II, -diff --git a/drivers/video/fbdev/core/fbcmap.c b/drivers/video/fbdev/core/fbcmap.c -index f89245b..05e036c 100644 ---- a/drivers/video/fbdev/core/fbcmap.c -+++ b/drivers/video/fbdev/core/fbcmap.c -@@ -17,6 +17,8 @@ - #include - #include - -+#include "../../console/fbcondecor.h" -+ - static u16 red2[] __read_mostly = { - 0x0000, 0xaaaa - }; -@@ -249,14 +251,17 @@ int fb_set_cmap(struct fb_cmap *cmap, struct fb_info *info) - if (transp) - htransp = *transp++; - if (info->fbops->fb_setcolreg(start++, -- hred, hgreen, hblue, -+ hred, hgreen, hblue, - htransp, info)) - break; - } - } -- if (rc == 0) -+ if (rc == 0) { - fb_copy_cmap(cmap, &info->cmap); -- -+ if (fbcon_decor_active(info, vc_cons[fg_console].d) && -+ info->fix.visual == FB_VISUAL_DIRECTCOLOR) -+ fbcon_decor_fix_pseudo_pal(info, vc_cons[fg_console].d); -+ } - return rc; - } - -diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c -index b6d5008..d6703f2 100644 ---- a/drivers/video/fbdev/core/fbmem.c -+++ b/drivers/video/fbdev/core/fbmem.c -@@ -1250,15 +1250,6 @@ struct fb_fix_screeninfo32 { - u16 reserved[3]; - }; - --struct fb_cmap32 { -- u32 start; -- u32 len; -- compat_caddr_t red; -- compat_caddr_t green; -- compat_caddr_t blue; -- compat_caddr_t transp; --}; -- - static int fb_getput_cmap(struct fb_info *info, unsigned int cmd, - unsigned long arg) - { -diff --git a/include/linux/console_decor.h b/include/linux/console_decor.h -new file mode 100644 -index 0000000..04b8d80 ---- /dev/null -+++ b/include/linux/console_decor.h -@@ -0,0 +1,46 @@ -+#ifndef _LINUX_CONSOLE_DECOR_H_ -+#define _LINUX_CONSOLE_DECOR_H_ 1 -+ -+/* A structure used by the framebuffer console decorations (drivers/video/console/fbcondecor.c) */ -+struct vc_decor { -+ __u8 bg_color; /* The color that is to be treated as transparent */ -+ __u8 state; /* Current decor state: 0 = off, 1 = on */ -+ __u16 tx, ty; /* Top left corner coordinates of the text field */ -+ __u16 twidth, theight; /* Width and height of the text field */ -+ char* theme; -+}; -+ -+#ifdef __KERNEL__ -+#ifdef CONFIG_COMPAT -+#include -+ -+struct vc_decor32 { -+ __u8 bg_color; /* The color that is to be treated as transparent */ -+ __u8 state; /* Current decor state: 0 = off, 1 = on */ -+ __u16 tx, ty; /* Top left corner coordinates of the text field */ -+ __u16 twidth, theight; /* Width and height of the text field */ -+ compat_uptr_t theme; -+}; -+ -+#define vc_decor_from_compat(to, from) \ -+ (to).bg_color = (from).bg_color; \ -+ (to).state = (from).state; \ -+ (to).tx = (from).tx; \ -+ (to).ty = (from).ty; \ -+ (to).twidth = (from).twidth; \ -+ (to).theight = (from).theight; \ -+ (to).theme = compat_ptr((from).theme) -+ -+#define vc_decor_to_compat(to, from) \ -+ (to).bg_color = (from).bg_color; \ -+ (to).state = (from).state; \ -+ (to).tx = (from).tx; \ -+ (to).ty = (from).ty; \ -+ (to).twidth = (from).twidth; \ -+ (to).theight = (from).theight; \ -+ (to).theme = ptr_to_compat((from).theme) -+ -+#endif /* CONFIG_COMPAT */ -+#endif /* __KERNEL__ */ -+ -+#endif -diff --git a/include/linux/console_struct.h b/include/linux/console_struct.h -index 7f0c329..98f5d60 100644 ---- a/include/linux/console_struct.h -+++ b/include/linux/console_struct.h -@@ -19,6 +19,7 @@ - struct vt_struct; - - #define NPAR 16 -+#include - - struct vc_data { - struct tty_port port; /* Upper level data */ -@@ -107,6 +108,8 @@ struct vc_data { - unsigned long vc_uni_pagedir; - unsigned long *vc_uni_pagedir_loc; /* [!] Location of uni_pagedir variable for this console */ - bool vc_panic_force_write; /* when oops/panic this VC can accept forced output/blanking */ -+ -+ struct vc_decor vc_decor; - /* additional information is in vt_kern.h */ - }; - -diff --git a/include/linux/fb.h b/include/linux/fb.h -index fe6ac95..1e36b03 100644 ---- a/include/linux/fb.h -+++ b/include/linux/fb.h -@@ -219,6 +219,34 @@ struct fb_deferred_io { - }; - #endif - -+#ifdef __KERNEL__ -+#ifdef CONFIG_COMPAT -+struct fb_image32 { -+ __u32 dx; /* Where to place image */ -+ __u32 dy; -+ __u32 width; /* Size of image */ -+ __u32 height; -+ __u32 fg_color; /* Only used when a mono bitmap */ -+ __u32 bg_color; -+ __u8 depth; /* Depth of the image */ -+ const compat_uptr_t data; /* Pointer to image data */ -+ struct fb_cmap32 cmap; /* color map info */ -+}; -+ -+#define fb_image_from_compat(to, from) \ -+ (to).dx = (from).dx; \ -+ (to).dy = (from).dy; \ -+ (to).width = (from).width; \ -+ (to).height = (from).height; \ -+ (to).fg_color = (from).fg_color; \ -+ (to).bg_color = (from).bg_color; \ -+ (to).depth = (from).depth; \ -+ (to).data = compat_ptr((from).data); \ -+ fb_cmap_from_compat((to).cmap, (from).cmap) -+ -+#endif /* CONFIG_COMPAT */ -+#endif /* __KERNEL__ */ -+ - /* - * Frame buffer operations - * -@@ -489,6 +517,9 @@ struct fb_info { - #define FBINFO_STATE_SUSPENDED 1 - u32 state; /* Hardware state i.e suspend */ - void *fbcon_par; /* fbcon use-only private area */ -+ -+ struct fb_image bgdecor; -+ - /* From here on everything is device dependent */ - void *par; - /* we need the PCI or similar aperture base/size not -diff --git a/include/uapi/linux/fb.h b/include/uapi/linux/fb.h -index fb795c3..dc77a03 100644 ---- a/include/uapi/linux/fb.h -+++ b/include/uapi/linux/fb.h -@@ -8,6 +8,25 @@ - - #define FB_MAX 32 /* sufficient for now */ - -+struct fbcon_decor_iowrapper -+{ -+ unsigned short vc; /* Virtual console */ -+ unsigned char origin; /* Point of origin of the request */ -+ void *data; -+}; -+ -+#ifdef __KERNEL__ -+#ifdef CONFIG_COMPAT -+#include -+struct fbcon_decor_iowrapper32 -+{ -+ unsigned short vc; /* Virtual console */ -+ unsigned char origin; /* Point of origin of the request */ -+ compat_uptr_t data; -+}; -+#endif /* CONFIG_COMPAT */ -+#endif /* __KERNEL__ */ -+ - /* ioctls - 0x46 is 'F' */ - #define FBIOGET_VSCREENINFO 0x4600 -@@ -35,6 +54,25 @@ - #define FBIOGET_DISPINFO 0x4618 - #define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32) - -+#define FBIOCONDECOR_SETCFG _IOWR('F', 0x19, struct fbcon_decor_iowrapper) -+#define FBIOCONDECOR_GETCFG _IOR('F', 0x1A, struct fbcon_decor_iowrapper) -+#define FBIOCONDECOR_SETSTATE _IOWR('F', 0x1B, struct fbcon_decor_iowrapper) -+#define FBIOCONDECOR_GETSTATE _IOR('F', 0x1C, struct fbcon_decor_iowrapper) -+#define FBIOCONDECOR_SETPIC _IOWR('F', 0x1D, struct fbcon_decor_iowrapper) -+#ifdef __KERNEL__ -+#ifdef CONFIG_COMPAT -+#define FBIOCONDECOR_SETCFG32 _IOWR('F', 0x19, struct fbcon_decor_iowrapper32) -+#define FBIOCONDECOR_GETCFG32 _IOR('F', 0x1A, struct fbcon_decor_iowrapper32) -+#define FBIOCONDECOR_SETSTATE32 _IOWR('F', 0x1B, struct fbcon_decor_iowrapper32) -+#define FBIOCONDECOR_GETSTATE32 _IOR('F', 0x1C, struct fbcon_decor_iowrapper32) -+#define FBIOCONDECOR_SETPIC32 _IOWR('F', 0x1D, struct fbcon_decor_iowrapper32) -+#endif /* CONFIG_COMPAT */ -+#endif /* __KERNEL__ */ -+ -+#define FBCON_DECOR_THEME_LEN 128 /* Maximum lenght of a theme name */ -+#define FBCON_DECOR_IO_ORIG_KERNEL 0 /* Kernel ioctl origin */ -+#define FBCON_DECOR_IO_ORIG_USER 1 /* User ioctl origin */ -+ - #define FB_TYPE_PACKED_PIXELS 0 /* Packed Pixels */ - #define FB_TYPE_PLANES 1 /* Non interleaved planes */ - #define FB_TYPE_INTERLEAVED_PLANES 2 /* Interleaved planes */ -@@ -277,6 +315,29 @@ struct fb_var_screeninfo { - __u32 reserved[4]; /* Reserved for future compatibility */ - }; - -+#ifdef __KERNEL__ -+#ifdef CONFIG_COMPAT -+struct fb_cmap32 { -+ __u32 start; -+ __u32 len; /* Number of entries */ -+ compat_uptr_t red; /* Red values */ -+ compat_uptr_t green; -+ compat_uptr_t blue; -+ compat_uptr_t transp; /* transparency, can be NULL */ -+}; -+ -+#define fb_cmap_from_compat(to, from) \ -+ (to).start = (from).start; \ -+ (to).len = (from).len; \ -+ (to).red = compat_ptr((from).red); \ -+ (to).green = compat_ptr((from).green); \ -+ (to).blue = compat_ptr((from).blue); \ -+ (to).transp = compat_ptr((from).transp) -+ -+#endif /* CONFIG_COMPAT */ -+#endif /* __KERNEL__ */ -+ -+ - struct fb_cmap { - __u32 start; /* First entry */ - __u32 len; /* Number of entries */ -diff --git a/kernel/sysctl.c b/kernel/sysctl.c -index 74f5b58..6386ab0 100644 ---- a/kernel/sysctl.c -+++ b/kernel/sysctl.c -@@ -146,6 +146,10 @@ static const int cap_last_cap = CAP_LAST_CAP; - static unsigned long hung_task_timeout_max = (LONG_MAX/HZ); - #endif - -+#ifdef CONFIG_FB_CON_DECOR -+extern char fbcon_decor_path[]; -+#endif -+ - #ifdef CONFIG_INOTIFY_USER - #include - #endif -@@ -255,6 +259,15 @@ static struct ctl_table sysctl_base_table[] = { - .mode = 0555, - .child = dev_table, - }, -+#ifdef CONFIG_FB_CON_DECOR -+ { -+ .procname = "fbcondecor", -+ .data = &fbcon_decor_path, -+ .maxlen = KMOD_PATH_LEN, -+ .mode = 0644, -+ .proc_handler = &proc_dostring, -+ }, -+#endif - { } - }; - diff --git a/kernel/kernel/files/patches/gentoo/4567_distro-Gentoo-Kconfig.patch b/kernel/kernel/files/patches/gentoo/4567_distro-Gentoo-Kconfig.patch deleted file mode 100644 index c7af596c..00000000 --- a/kernel/kernel/files/patches/gentoo/4567_distro-Gentoo-Kconfig.patch +++ /dev/null @@ -1,143 +0,0 @@ ---- a/Kconfig -+++ b/Kconfig -@@ -8,4 +8,6 @@ config SRCARCH - string - option env="SRCARCH" - -+source "distro/Kconfig" -+ - source "arch/$SRCARCH/Kconfig" ---- /dev/null -+++ b/distro/Kconfig -@@ -0,0 +1,131 @@ -+menu "Gentoo Linux" -+ -+config GENTOO_LINUX -+ bool "Gentoo Linux support" -+ -+ default y -+ -+ help -+ In order to boot Gentoo Linux a minimal set of config settings needs to -+ be enabled in the kernel; to avoid the users from having to enable them -+ manually as part of a Gentoo Linux installation or a new clean config, -+ we enable these config settings by default for convenience. -+ -+ See the settings that become available for more details and fine-tuning. -+ -+config GENTOO_LINUX_UDEV -+ bool "Linux dynamic and persistent device naming (userspace devfs) support" -+ -+ depends on GENTOO_LINUX -+ default y if GENTOO_LINUX -+ -+ select DEVTMPFS -+ select TMPFS -+ -+ select MMU -+ select SHMEM -+ -+ help -+ In order to boot Gentoo Linux a minimal set of config settings needs to -+ be enabled in the kernel; to avoid the users from having to enable them -+ manually as part of a Gentoo Linux installation or a new clean config, -+ we enable these config settings by default for convenience. -+ -+ Currently this only selects TMPFS, DEVTMPFS and their dependencies. -+ TMPFS is enabled to maintain a tmpfs file system at /dev/shm, /run and -+ /sys/fs/cgroup; DEVTMPFS to maintain a devtmpfs file system at /dev. -+ -+ Some of these are critical files that need to be available early in the -+ boot process; if not available, it causes sysfs and udev to malfunction. -+ -+ To ensure Gentoo Linux boots, it is best to leave this setting enabled; -+ if you run a custom setup, you could consider whether to disable this. -+ -+config GENTOO_LINUX_PORTAGE -+ bool "Select options required by Portage features" -+ -+ depends on GENTOO_LINUX -+ default y if GENTOO_LINUX -+ -+ select CGROUPS -+ select NAMESPACES -+ select IPC_NS -+ select NET_NS -+ -+ help -+ This enables options required by various Portage FEATURES. -+ Currently this selects: -+ -+ CGROUPS (required for FEATURES=cgroup) -+ IPC_NS (required for FEATURES=ipc-sandbox) -+ NET_NS (required for FEATURES=network-sandbox) -+ -+ It is highly recommended that you leave this enabled as these FEATURES -+ are, or will soon be, enabled by default. -+ -+menu "Support for init systems, system and service managers" -+ visible if GENTOO_LINUX -+ -+config GENTOO_LINUX_INIT_SCRIPT -+ bool "OpenRC, runit and other script based systems and managers" -+ -+ default y if GENTOO_LINUX -+ -+ depends on GENTOO_LINUX -+ -+ select BINFMT_SCRIPT -+ -+ help -+ The init system is the first thing that loads after the kernel booted. -+ -+ These config settings allow you to select which init systems to support; -+ instead of having to select all the individual settings all over the -+ place, these settings allows you to select all the settings at once. -+ -+ This particular setting enables all the known requirements for OpenRC, -+ runit and similar script based systems and managers. -+ -+ If you are unsure about this, it is best to leave this setting enabled. -+ -+config GENTOO_LINUX_INIT_SYSTEMD -+ bool "systemd" -+ -+ default n -+ -+ depends on GENTOO_LINUX && GENTOO_LINUX_UDEV -+ -+ select AUTOFS4_FS -+ select BLK_DEV_BSG -+ select CGROUPS -+ select DEVPTS_MULTIPLE_INSTANCES -+ select EPOLL -+ select FANOTIFY -+ select FHANDLE -+ select INOTIFY_USER -+ select NET -+ select NET_NS -+ select PROC_FS -+ select SIGNALFD -+ select SYSFS -+ select TIMERFD -+ -+ select ANON_INODES -+ select BLOCK -+ select EVENTFD -+ select FSNOTIFY -+ select INET -+ select NLATTR -+ -+ help -+ The init system is the first thing that loads after the kernel booted. -+ -+ These config settings allow you to select which init systems to support; -+ instead of having to select all the individual settings all over the -+ place, these settings allows you to select all the settings at once. -+ -+ This particular setting enables all the known requirements for systemd; -+ it also enables suggested optional settings, as the package suggests to. -+ -+endmenu -+ -+endmenu diff --git a/kernel/kernel/files/patches/gentoo/5001_block-cgroups-kconfig-build-bits-for-BFQ-v7r7-3.19.patch b/kernel/kernel/files/patches/gentoo/5001_block-cgroups-kconfig-build-bits-for-BFQ-v7r7-3.19.patch deleted file mode 100644 index b36d572c..00000000 --- a/kernel/kernel/files/patches/gentoo/5001_block-cgroups-kconfig-build-bits-for-BFQ-v7r7-3.19.patch +++ /dev/null @@ -1,104 +0,0 @@ -From a828d56aebc0735676be23734cccf31e279c0d1b Mon Sep 17 00:00:00 2001 -From: Paolo Valente -Date: Mon, 8 Dec 2014 16:04:25 +0100 -Subject: [PATCH 1/3] block: cgroups, kconfig, build bits for BFQ-v7r7-3.19 - -Update Kconfig.iosched and do the related Makefile changes to include -kernel configuration options for BFQ. Also add the bfqio controller -to the cgroups subsystem. - -Signed-off-by: Paolo Valente -Signed-off-by: Arianna Avanzini ---- - block/Kconfig.iosched | 32 ++++++++++++++++++++++++++++++++ - block/Makefile | 1 + - include/linux/cgroup_subsys.h | 4 ++++ - 3 files changed, 37 insertions(+) - -diff --git a/block/Kconfig.iosched b/block/Kconfig.iosched -index 421bef9..0ee5f0f 100644 ---- a/block/Kconfig.iosched -+++ b/block/Kconfig.iosched -@@ -39,6 +39,27 @@ config CFQ_GROUP_IOSCHED - ---help--- - Enable group IO scheduling in CFQ. - -+config IOSCHED_BFQ -+ tristate "BFQ I/O scheduler" -+ default n -+ ---help--- -+ The BFQ I/O scheduler tries to distribute bandwidth among -+ all processes according to their weights. -+ It aims at distributing the bandwidth as desired, independently of -+ the disk parameters and with any workload. It also tries to -+ guarantee low latency to interactive and soft real-time -+ applications. If compiled built-in (saying Y here), BFQ can -+ be configured to support hierarchical scheduling. -+ -+config CGROUP_BFQIO -+ bool "BFQ hierarchical scheduling support" -+ depends on CGROUPS && IOSCHED_BFQ=y -+ default n -+ ---help--- -+ Enable hierarchical scheduling in BFQ, using the cgroups -+ filesystem interface. The name of the subsystem will be -+ bfqio. -+ - choice - prompt "Default I/O scheduler" - default DEFAULT_CFQ -@@ -52,6 +73,16 @@ choice - config DEFAULT_CFQ - bool "CFQ" if IOSCHED_CFQ=y - -+ config DEFAULT_BFQ -+ bool "BFQ" if IOSCHED_BFQ=y -+ help -+ Selects BFQ as the default I/O scheduler which will be -+ used by default for all block devices. -+ The BFQ I/O scheduler aims at distributing the bandwidth -+ as desired, independently of the disk parameters and with -+ any workload. It also tries to guarantee low latency to -+ interactive and soft real-time applications. -+ - config DEFAULT_NOOP - bool "No-op" - -@@ -61,6 +92,7 @@ config DEFAULT_IOSCHED - string - default "deadline" if DEFAULT_DEADLINE - default "cfq" if DEFAULT_CFQ -+ default "bfq" if DEFAULT_BFQ - default "noop" if DEFAULT_NOOP - - endmenu -diff --git a/block/Makefile b/block/Makefile -index 00ecc97..1ed86d5 100644 ---- a/block/Makefile -+++ b/block/Makefile -@@ -18,6 +18,7 @@ obj-$(CONFIG_BLK_DEV_THROTTLING) += blk-throttle.o - obj-$(CONFIG_IOSCHED_NOOP) += noop-iosched.o - obj-$(CONFIG_IOSCHED_DEADLINE) += deadline-iosched.o - obj-$(CONFIG_IOSCHED_CFQ) += cfq-iosched.o -+obj-$(CONFIG_IOSCHED_BFQ) += bfq-iosched.o - - obj-$(CONFIG_BLOCK_COMPAT) += compat_ioctl.o - obj-$(CONFIG_BLK_CMDLINE_PARSER) += cmdline-parser.o -diff --git a/include/linux/cgroup_subsys.h b/include/linux/cgroup_subsys.h -index 98c4f9b..13b010d 100644 ---- a/include/linux/cgroup_subsys.h -+++ b/include/linux/cgroup_subsys.h -@@ -35,6 +35,10 @@ SUBSYS(net_cls) - SUBSYS(blkio) - #endif - -+#if IS_ENABLED(CONFIG_CGROUP_BFQIO) -+SUBSYS(bfqio) -+#endif -+ - #if IS_ENABLED(CONFIG_CGROUP_PERF) - SUBSYS(perf_event) - #endif --- -2.3.0 - diff --git a/kernel/kernel/files/patches/gentoo/5002_block-introduce-the-BFQ-v7r7-I-O-sched-for-3.19.patch b/kernel/kernel/files/patches/gentoo/5002_block-introduce-the-BFQ-v7r7-I-O-sched-for-3.19.patch deleted file mode 100644 index fb96ff28..00000000 --- a/kernel/kernel/files/patches/gentoo/5002_block-introduce-the-BFQ-v7r7-I-O-sched-for-3.19.patch +++ /dev/null @@ -1,6966 +0,0 @@ -From 5bfaaa91a51940efaccb66bc5cd562ba3b9d4053 Mon Sep 17 00:00:00 2001 -From: Paolo Valente -Date: Thu, 9 May 2013 19:10:02 +0200 -Subject: [PATCH 2/3] block: introduce the BFQ-v7r7 I/O sched for 3.19 - -Add the BFQ-v7r7 I/O scheduler to 3.19. -The general structure is borrowed from CFQ, as much of the code for -handling I/O contexts. Over time, several useful features have been -ported from CFQ as well (details in the changelog in README.BFQ). A -(bfq_)queue is associated to each task doing I/O on a device, and each -time a scheduling decision has to be made a queue is selected and served -until it expires. - - - Slices are given in the service domain: tasks are assigned - budgets, measured in number of sectors. Once got the disk, a task - must however consume its assigned budget within a configurable - maximum time (by default, the maximum possible value of the - budgets is automatically computed to comply with this timeout). - This allows the desired latency vs "throughput boosting" tradeoff - to be set. - - - Budgets are scheduled according to a variant of WF2Q+, implemented - using an augmented rb-tree to take eligibility into account while - preserving an O(log N) overall complexity. - - - A low-latency tunable is provided; if enabled, both interactive - and soft real-time applications are guaranteed a very low latency. - - - Latency guarantees are preserved also in the presence of NCQ. - - - Also with flash-based devices, a high throughput is achieved - while still preserving latency guarantees. - - - BFQ features Early Queue Merge (EQM), a sort of fusion of the - cooperating-queue-merging and the preemption mechanisms present - in CFQ. EQM is in fact a unified mechanism that tries to get a - sequential read pattern, and hence a high throughput, with any - set of processes performing interleaved I/O over a contiguous - sequence of sectors. - - - BFQ supports full hierarchical scheduling, exporting a cgroups - interface. Since each node has a full scheduler, each group can - be assigned its own weight. - - - If the cgroups interface is not used, only I/O priorities can be - assigned to processes, with ioprio values mapped to weights - with the relation weight = IOPRIO_BE_NR - ioprio. - - - ioprio classes are served in strict priority order, i.e., lower - priority queues are not served as long as there are higher - priority queues. Among queues in the same class the bandwidth is - distributed in proportion to the weight of each queue. A very - thin extra bandwidth is however guaranteed to the Idle class, to - prevent it from starving. - -Signed-off-by: Paolo Valente -Signed-off-by: Arianna Avanzini ---- - block/bfq-cgroup.c | 936 ++++++++++++ - block/bfq-ioc.c | 36 + - block/bfq-iosched.c | 3902 +++++++++++++++++++++++++++++++++++++++++++++++++++ - block/bfq-sched.c | 1214 ++++++++++++++++ - block/bfq.h | 775 ++++++++++ - 5 files changed, 6863 insertions(+) - create mode 100644 block/bfq-cgroup.c - create mode 100644 block/bfq-ioc.c - create mode 100644 block/bfq-iosched.c - create mode 100644 block/bfq-sched.c - create mode 100644 block/bfq.h - -diff --git a/block/bfq-cgroup.c b/block/bfq-cgroup.c -new file mode 100644 -index 0000000..11e2f1d ---- /dev/null -+++ b/block/bfq-cgroup.c -@@ -0,0 +1,936 @@ -+/* -+ * BFQ: CGROUPS support. -+ * -+ * Based on ideas and code from CFQ: -+ * Copyright (C) 2003 Jens Axboe -+ * -+ * Copyright (C) 2008 Fabio Checconi -+ * Paolo Valente -+ * -+ * Copyright (C) 2010 Paolo Valente -+ * -+ * Licensed under the GPL-2 as detailed in the accompanying COPYING.BFQ -+ * file. -+ */ -+ -+#ifdef CONFIG_CGROUP_BFQIO -+ -+static DEFINE_MUTEX(bfqio_mutex); -+ -+static bool bfqio_is_removed(struct bfqio_cgroup *bgrp) -+{ -+ return bgrp ? !bgrp->online : false; -+} -+ -+static struct bfqio_cgroup bfqio_root_cgroup = { -+ .weight = BFQ_DEFAULT_GRP_WEIGHT, -+ .ioprio = BFQ_DEFAULT_GRP_IOPRIO, -+ .ioprio_class = BFQ_DEFAULT_GRP_CLASS, -+}; -+ -+static inline void bfq_init_entity(struct bfq_entity *entity, -+ struct bfq_group *bfqg) -+{ -+ entity->weight = entity->new_weight; -+ entity->orig_weight = entity->new_weight; -+ entity->ioprio = entity->new_ioprio; -+ entity->ioprio_class = entity->new_ioprio_class; -+ entity->parent = bfqg->my_entity; -+ entity->sched_data = &bfqg->sched_data; -+} -+ -+static struct bfqio_cgroup *css_to_bfqio(struct cgroup_subsys_state *css) -+{ -+ return css ? container_of(css, struct bfqio_cgroup, css) : NULL; -+} -+ -+/* -+ * Search the bfq_group for bfqd into the hash table (by now only a list) -+ * of bgrp. Must be called under rcu_read_lock(). -+ */ -+static struct bfq_group *bfqio_lookup_group(struct bfqio_cgroup *bgrp, -+ struct bfq_data *bfqd) -+{ -+ struct bfq_group *bfqg; -+ void *key; -+ -+ hlist_for_each_entry_rcu(bfqg, &bgrp->group_data, group_node) { -+ key = rcu_dereference(bfqg->bfqd); -+ if (key == bfqd) -+ return bfqg; -+ } -+ -+ return NULL; -+} -+ -+static inline void bfq_group_init_entity(struct bfqio_cgroup *bgrp, -+ struct bfq_group *bfqg) -+{ -+ struct bfq_entity *entity = &bfqg->entity; -+ -+ /* -+ * If the weight of the entity has never been set via the sysfs -+ * interface, then bgrp->weight == 0. In this case we initialize -+ * the weight from the current ioprio value. Otherwise, the group -+ * weight, if set, has priority over the ioprio value. -+ */ -+ if (bgrp->weight == 0) { -+ entity->new_weight = bfq_ioprio_to_weight(bgrp->ioprio); -+ entity->new_ioprio = bgrp->ioprio; -+ } else { -+ if (bgrp->weight < BFQ_MIN_WEIGHT || -+ bgrp->weight > BFQ_MAX_WEIGHT) { -+ printk(KERN_CRIT "bfq_group_init_entity: " -+ "bgrp->weight %d\n", bgrp->weight); -+ BUG(); -+ } -+ entity->new_weight = bgrp->weight; -+ entity->new_ioprio = bfq_weight_to_ioprio(bgrp->weight); -+ } -+ entity->orig_weight = entity->weight = entity->new_weight; -+ entity->ioprio = entity->new_ioprio; -+ entity->ioprio_class = entity->new_ioprio_class = bgrp->ioprio_class; -+ entity->my_sched_data = &bfqg->sched_data; -+ bfqg->active_entities = 0; -+} -+ -+static inline void bfq_group_set_parent(struct bfq_group *bfqg, -+ struct bfq_group *parent) -+{ -+ struct bfq_entity *entity; -+ -+ BUG_ON(parent == NULL); -+ BUG_ON(bfqg == NULL); -+ -+ entity = &bfqg->entity; -+ entity->parent = parent->my_entity; -+ entity->sched_data = &parent->sched_data; -+} -+ -+/** -+ * bfq_group_chain_alloc - allocate a chain of groups. -+ * @bfqd: queue descriptor. -+ * @css: the leaf cgroup_subsys_state this chain starts from. -+ * -+ * Allocate a chain of groups starting from the one belonging to -+ * @cgroup up to the root cgroup. Stop if a cgroup on the chain -+ * to the root has already an allocated group on @bfqd. -+ */ -+static struct bfq_group *bfq_group_chain_alloc(struct bfq_data *bfqd, -+ struct cgroup_subsys_state *css) -+{ -+ struct bfqio_cgroup *bgrp; -+ struct bfq_group *bfqg, *prev = NULL, *leaf = NULL; -+ -+ for (; css != NULL; css = css->parent) { -+ bgrp = css_to_bfqio(css); -+ -+ bfqg = bfqio_lookup_group(bgrp, bfqd); -+ if (bfqg != NULL) { -+ /* -+ * All the cgroups in the path from there to the -+ * root must have a bfq_group for bfqd, so we don't -+ * need any more allocations. -+ */ -+ break; -+ } -+ -+ bfqg = kzalloc(sizeof(*bfqg), GFP_ATOMIC); -+ if (bfqg == NULL) -+ goto cleanup; -+ -+ bfq_group_init_entity(bgrp, bfqg); -+ bfqg->my_entity = &bfqg->entity; -+ -+ if (leaf == NULL) { -+ leaf = bfqg; -+ prev = leaf; -+ } else { -+ bfq_group_set_parent(prev, bfqg); -+ /* -+ * Build a list of allocated nodes using the bfqd -+ * filed, that is still unused and will be -+ * initialized only after the node will be -+ * connected. -+ */ -+ prev->bfqd = bfqg; -+ prev = bfqg; -+ } -+ } -+ -+ return leaf; -+ -+cleanup: -+ while (leaf != NULL) { -+ prev = leaf; -+ leaf = leaf->bfqd; -+ kfree(prev); -+ } -+ -+ return NULL; -+} -+ -+/** -+ * bfq_group_chain_link - link an allocated group chain to a cgroup -+ * hierarchy. -+ * @bfqd: the queue descriptor. -+ * @css: the leaf cgroup_subsys_state to start from. -+ * @leaf: the leaf group (to be associated to @cgroup). -+ * -+ * Try to link a chain of groups to a cgroup hierarchy, connecting the -+ * nodes bottom-up, so we can be sure that when we find a cgroup in the -+ * hierarchy that already as a group associated to @bfqd all the nodes -+ * in the path to the root cgroup have one too. -+ * -+ * On locking: the queue lock protects the hierarchy (there is a hierarchy -+ * per device) while the bfqio_cgroup lock protects the list of groups -+ * belonging to the same cgroup. -+ */ -+static void bfq_group_chain_link(struct bfq_data *bfqd, -+ struct cgroup_subsys_state *css, -+ struct bfq_group *leaf) -+{ -+ struct bfqio_cgroup *bgrp; -+ struct bfq_group *bfqg, *next, *prev = NULL; -+ unsigned long flags; -+ -+ assert_spin_locked(bfqd->queue->queue_lock); -+ -+ for (; css != NULL && leaf != NULL; css = css->parent) { -+ bgrp = css_to_bfqio(css); -+ next = leaf->bfqd; -+ -+ bfqg = bfqio_lookup_group(bgrp, bfqd); -+ BUG_ON(bfqg != NULL); -+ -+ spin_lock_irqsave(&bgrp->lock, flags); -+ -+ rcu_assign_pointer(leaf->bfqd, bfqd); -+ hlist_add_head_rcu(&leaf->group_node, &bgrp->group_data); -+ hlist_add_head(&leaf->bfqd_node, &bfqd->group_list); -+ -+ spin_unlock_irqrestore(&bgrp->lock, flags); -+ -+ prev = leaf; -+ leaf = next; -+ } -+ -+ BUG_ON(css == NULL && leaf != NULL); -+ if (css != NULL && prev != NULL) { -+ bgrp = css_to_bfqio(css); -+ bfqg = bfqio_lookup_group(bgrp, bfqd); -+ bfq_group_set_parent(prev, bfqg); -+ } -+} -+ -+/** -+ * bfq_find_alloc_group - return the group associated to @bfqd in @cgroup. -+ * @bfqd: queue descriptor. -+ * @cgroup: cgroup being searched for. -+ * -+ * Return a group associated to @bfqd in @cgroup, allocating one if -+ * necessary. When a group is returned all the cgroups in the path -+ * to the root have a group associated to @bfqd. -+ * -+ * If the allocation fails, return the root group: this breaks guarantees -+ * but is a safe fallback. If this loss becomes a problem it can be -+ * mitigated using the equivalent weight (given by the product of the -+ * weights of the groups in the path from @group to the root) in the -+ * root scheduler. -+ * -+ * We allocate all the missing nodes in the path from the leaf cgroup -+ * to the root and we connect the nodes only after all the allocations -+ * have been successful. -+ */ -+static struct bfq_group *bfq_find_alloc_group(struct bfq_data *bfqd, -+ struct cgroup_subsys_state *css) -+{ -+ struct bfqio_cgroup *bgrp = css_to_bfqio(css); -+ struct bfq_group *bfqg; -+ -+ bfqg = bfqio_lookup_group(bgrp, bfqd); -+ if (bfqg != NULL) -+ return bfqg; -+ -+ bfqg = bfq_group_chain_alloc(bfqd, css); -+ if (bfqg != NULL) -+ bfq_group_chain_link(bfqd, css, bfqg); -+ else -+ bfqg = bfqd->root_group; -+ -+ return bfqg; -+} -+ -+/** -+ * bfq_bfqq_move - migrate @bfqq to @bfqg. -+ * @bfqd: queue descriptor. -+ * @bfqq: the queue to move. -+ * @entity: @bfqq's entity. -+ * @bfqg: the group to move to. -+ * -+ * Move @bfqq to @bfqg, deactivating it from its old group and reactivating -+ * it on the new one. Avoid putting the entity on the old group idle tree. -+ * -+ * Must be called under the queue lock; the cgroup owning @bfqg must -+ * not disappear (by now this just means that we are called under -+ * rcu_read_lock()). -+ */ -+static void bfq_bfqq_move(struct bfq_data *bfqd, struct bfq_queue *bfqq, -+ struct bfq_entity *entity, struct bfq_group *bfqg) -+{ -+ int busy, resume; -+ -+ busy = bfq_bfqq_busy(bfqq); -+ resume = !RB_EMPTY_ROOT(&bfqq->sort_list); -+ -+ BUG_ON(resume && !entity->on_st); -+ BUG_ON(busy && !resume && entity->on_st && -+ bfqq != bfqd->in_service_queue); -+ -+ if (busy) { -+ BUG_ON(atomic_read(&bfqq->ref) < 2); -+ -+ if (!resume) -+ bfq_del_bfqq_busy(bfqd, bfqq, 0); -+ else -+ bfq_deactivate_bfqq(bfqd, bfqq, 0); -+ } else if (entity->on_st) -+ bfq_put_idle_entity(bfq_entity_service_tree(entity), entity); -+ -+ /* -+ * Here we use a reference to bfqg. We don't need a refcounter -+ * as the cgroup reference will not be dropped, so that its -+ * destroy() callback will not be invoked. -+ */ -+ entity->parent = bfqg->my_entity; -+ entity->sched_data = &bfqg->sched_data; -+ -+ if (busy && resume) -+ bfq_activate_bfqq(bfqd, bfqq); -+ -+ if (bfqd->in_service_queue == NULL && !bfqd->rq_in_driver) -+ bfq_schedule_dispatch(bfqd); -+} -+ -+/** -+ * __bfq_bic_change_cgroup - move @bic to @cgroup. -+ * @bfqd: the queue descriptor. -+ * @bic: the bic to move. -+ * @cgroup: the cgroup to move to. -+ * -+ * Move bic to cgroup, assuming that bfqd->queue is locked; the caller -+ * has to make sure that the reference to cgroup is valid across the call. -+ * -+ * NOTE: an alternative approach might have been to store the current -+ * cgroup in bfqq and getting a reference to it, reducing the lookup -+ * time here, at the price of slightly more complex code. -+ */ -+static struct bfq_group *__bfq_bic_change_cgroup(struct bfq_data *bfqd, -+ struct bfq_io_cq *bic, -+ struct cgroup_subsys_state *css) -+{ -+ struct bfq_queue *async_bfqq = bic_to_bfqq(bic, 0); -+ struct bfq_queue *sync_bfqq = bic_to_bfqq(bic, 1); -+ struct bfq_entity *entity; -+ struct bfq_group *bfqg; -+ struct bfqio_cgroup *bgrp; -+ -+ bgrp = css_to_bfqio(css); -+ -+ bfqg = bfq_find_alloc_group(bfqd, css); -+ if (async_bfqq != NULL) { -+ entity = &async_bfqq->entity; -+ -+ if (entity->sched_data != &bfqg->sched_data) { -+ bic_set_bfqq(bic, NULL, 0); -+ bfq_log_bfqq(bfqd, async_bfqq, -+ "bic_change_group: %p %d", -+ async_bfqq, atomic_read(&async_bfqq->ref)); -+ bfq_put_queue(async_bfqq); -+ } -+ } -+ -+ if (sync_bfqq != NULL) { -+ entity = &sync_bfqq->entity; -+ if (entity->sched_data != &bfqg->sched_data) -+ bfq_bfqq_move(bfqd, sync_bfqq, entity, bfqg); -+ } -+ -+ return bfqg; -+} -+ -+/** -+ * bfq_bic_change_cgroup - move @bic to @cgroup. -+ * @bic: the bic being migrated. -+ * @cgroup: the destination cgroup. -+ * -+ * When the task owning @bic is moved to @cgroup, @bic is immediately -+ * moved into its new parent group. -+ */ -+static void bfq_bic_change_cgroup(struct bfq_io_cq *bic, -+ struct cgroup_subsys_state *css) -+{ -+ struct bfq_data *bfqd; -+ unsigned long uninitialized_var(flags); -+ -+ bfqd = bfq_get_bfqd_locked(&(bic->icq.q->elevator->elevator_data), -+ &flags); -+ if (bfqd != NULL) { -+ __bfq_bic_change_cgroup(bfqd, bic, css); -+ bfq_put_bfqd_unlock(bfqd, &flags); -+ } -+} -+ -+/** -+ * bfq_bic_update_cgroup - update the cgroup of @bic. -+ * @bic: the @bic to update. -+ * -+ * Make sure that @bic is enqueued in the cgroup of the current task. -+ * We need this in addition to moving bics during the cgroup attach -+ * phase because the task owning @bic could be at its first disk -+ * access or we may end up in the root cgroup as the result of a -+ * memory allocation failure and here we try to move to the right -+ * group. -+ * -+ * Must be called under the queue lock. It is safe to use the returned -+ * value even after the rcu_read_unlock() as the migration/destruction -+ * paths act under the queue lock too. IOW it is impossible to race with -+ * group migration/destruction and end up with an invalid group as: -+ * a) here cgroup has not yet been destroyed, nor its destroy callback -+ * has started execution, as current holds a reference to it, -+ * b) if it is destroyed after rcu_read_unlock() [after current is -+ * migrated to a different cgroup] its attach() callback will have -+ * taken care of remove all the references to the old cgroup data. -+ */ -+static struct bfq_group *bfq_bic_update_cgroup(struct bfq_io_cq *bic) -+{ -+ struct bfq_data *bfqd = bic_to_bfqd(bic); -+ struct bfq_group *bfqg; -+ struct cgroup_subsys_state *css; -+ -+ BUG_ON(bfqd == NULL); -+ -+ rcu_read_lock(); -+ css = task_css(current, bfqio_cgrp_id); -+ bfqg = __bfq_bic_change_cgroup(bfqd, bic, css); -+ rcu_read_unlock(); -+ -+ return bfqg; -+} -+ -+/** -+ * bfq_flush_idle_tree - deactivate any entity on the idle tree of @st. -+ * @st: the service tree being flushed. -+ */ -+static inline void bfq_flush_idle_tree(struct bfq_service_tree *st) -+{ -+ struct bfq_entity *entity = st->first_idle; -+ -+ for (; entity != NULL; entity = st->first_idle) -+ __bfq_deactivate_entity(entity, 0); -+} -+ -+/** -+ * bfq_reparent_leaf_entity - move leaf entity to the root_group. -+ * @bfqd: the device data structure with the root group. -+ * @entity: the entity to move. -+ */ -+static inline void bfq_reparent_leaf_entity(struct bfq_data *bfqd, -+ struct bfq_entity *entity) -+{ -+ struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); -+ -+ BUG_ON(bfqq == NULL); -+ bfq_bfqq_move(bfqd, bfqq, entity, bfqd->root_group); -+ return; -+} -+ -+/** -+ * bfq_reparent_active_entities - move to the root group all active -+ * entities. -+ * @bfqd: the device data structure with the root group. -+ * @bfqg: the group to move from. -+ * @st: the service tree with the entities. -+ * -+ * Needs queue_lock to be taken and reference to be valid over the call. -+ */ -+static inline void bfq_reparent_active_entities(struct bfq_data *bfqd, -+ struct bfq_group *bfqg, -+ struct bfq_service_tree *st) -+{ -+ struct rb_root *active = &st->active; -+ struct bfq_entity *entity = NULL; -+ -+ if (!RB_EMPTY_ROOT(&st->active)) -+ entity = bfq_entity_of(rb_first(active)); -+ -+ for (; entity != NULL; entity = bfq_entity_of(rb_first(active))) -+ bfq_reparent_leaf_entity(bfqd, entity); -+ -+ if (bfqg->sched_data.in_service_entity != NULL) -+ bfq_reparent_leaf_entity(bfqd, -+ bfqg->sched_data.in_service_entity); -+ -+ return; -+} -+ -+/** -+ * bfq_destroy_group - destroy @bfqg. -+ * @bgrp: the bfqio_cgroup containing @bfqg. -+ * @bfqg: the group being destroyed. -+ * -+ * Destroy @bfqg, making sure that it is not referenced from its parent. -+ */ -+static void bfq_destroy_group(struct bfqio_cgroup *bgrp, struct bfq_group *bfqg) -+{ -+ struct bfq_data *bfqd; -+ struct bfq_service_tree *st; -+ struct bfq_entity *entity = bfqg->my_entity; -+ unsigned long uninitialized_var(flags); -+ int i; -+ -+ hlist_del(&bfqg->group_node); -+ -+ /* -+ * Empty all service_trees belonging to this group before -+ * deactivating the group itself. -+ */ -+ for (i = 0; i < BFQ_IOPRIO_CLASSES; i++) { -+ st = bfqg->sched_data.service_tree + i; -+ -+ /* -+ * The idle tree may still contain bfq_queues belonging -+ * to exited task because they never migrated to a different -+ * cgroup from the one being destroyed now. No one else -+ * can access them so it's safe to act without any lock. -+ */ -+ bfq_flush_idle_tree(st); -+ -+ /* -+ * It may happen that some queues are still active -+ * (busy) upon group destruction (if the corresponding -+ * processes have been forced to terminate). We move -+ * all the leaf entities corresponding to these queues -+ * to the root_group. -+ * Also, it may happen that the group has an entity -+ * in service, which is disconnected from the active -+ * tree: it must be moved, too. -+ * There is no need to put the sync queues, as the -+ * scheduler has taken no reference. -+ */ -+ bfqd = bfq_get_bfqd_locked(&bfqg->bfqd, &flags); -+ if (bfqd != NULL) { -+ bfq_reparent_active_entities(bfqd, bfqg, st); -+ bfq_put_bfqd_unlock(bfqd, &flags); -+ } -+ BUG_ON(!RB_EMPTY_ROOT(&st->active)); -+ BUG_ON(!RB_EMPTY_ROOT(&st->idle)); -+ } -+ BUG_ON(bfqg->sched_data.next_in_service != NULL); -+ BUG_ON(bfqg->sched_data.in_service_entity != NULL); -+ -+ /* -+ * We may race with device destruction, take extra care when -+ * dereferencing bfqg->bfqd. -+ */ -+ bfqd = bfq_get_bfqd_locked(&bfqg->bfqd, &flags); -+ if (bfqd != NULL) { -+ hlist_del(&bfqg->bfqd_node); -+ __bfq_deactivate_entity(entity, 0); -+ bfq_put_async_queues(bfqd, bfqg); -+ bfq_put_bfqd_unlock(bfqd, &flags); -+ } -+ BUG_ON(entity->tree != NULL); -+ -+ /* -+ * No need to defer the kfree() to the end of the RCU grace -+ * period: we are called from the destroy() callback of our -+ * cgroup, so we can be sure that no one is a) still using -+ * this cgroup or b) doing lookups in it. -+ */ -+ kfree(bfqg); -+} -+ -+static void bfq_end_wr_async(struct bfq_data *bfqd) -+{ -+ struct hlist_node *tmp; -+ struct bfq_group *bfqg; -+ -+ hlist_for_each_entry_safe(bfqg, tmp, &bfqd->group_list, bfqd_node) -+ bfq_end_wr_async_queues(bfqd, bfqg); -+ bfq_end_wr_async_queues(bfqd, bfqd->root_group); -+} -+ -+/** -+ * bfq_disconnect_groups - disconnect @bfqd from all its groups. -+ * @bfqd: the device descriptor being exited. -+ * -+ * When the device exits we just make sure that no lookup can return -+ * the now unused group structures. They will be deallocated on cgroup -+ * destruction. -+ */ -+static void bfq_disconnect_groups(struct bfq_data *bfqd) -+{ -+ struct hlist_node *tmp; -+ struct bfq_group *bfqg; -+ -+ bfq_log(bfqd, "disconnect_groups beginning"); -+ hlist_for_each_entry_safe(bfqg, tmp, &bfqd->group_list, bfqd_node) { -+ hlist_del(&bfqg->bfqd_node); -+ -+ __bfq_deactivate_entity(bfqg->my_entity, 0); -+ -+ /* -+ * Don't remove from the group hash, just set an -+ * invalid key. No lookups can race with the -+ * assignment as bfqd is being destroyed; this -+ * implies also that new elements cannot be added -+ * to the list. -+ */ -+ rcu_assign_pointer(bfqg->bfqd, NULL); -+ -+ bfq_log(bfqd, "disconnect_groups: put async for group %p", -+ bfqg); -+ bfq_put_async_queues(bfqd, bfqg); -+ } -+} -+ -+static inline void bfq_free_root_group(struct bfq_data *bfqd) -+{ -+ struct bfqio_cgroup *bgrp = &bfqio_root_cgroup; -+ struct bfq_group *bfqg = bfqd->root_group; -+ -+ bfq_put_async_queues(bfqd, bfqg); -+ -+ spin_lock_irq(&bgrp->lock); -+ hlist_del_rcu(&bfqg->group_node); -+ spin_unlock_irq(&bgrp->lock); -+ -+ /* -+ * No need to synchronize_rcu() here: since the device is gone -+ * there cannot be any read-side access to its root_group. -+ */ -+ kfree(bfqg); -+} -+ -+static struct bfq_group *bfq_alloc_root_group(struct bfq_data *bfqd, int node) -+{ -+ struct bfq_group *bfqg; -+ struct bfqio_cgroup *bgrp; -+ int i; -+ -+ bfqg = kzalloc_node(sizeof(*bfqg), GFP_KERNEL, node); -+ if (bfqg == NULL) -+ return NULL; -+ -+ bfqg->entity.parent = NULL; -+ for (i = 0; i < BFQ_IOPRIO_CLASSES; i++) -+ bfqg->sched_data.service_tree[i] = BFQ_SERVICE_TREE_INIT; -+ -+ bgrp = &bfqio_root_cgroup; -+ spin_lock_irq(&bgrp->lock); -+ rcu_assign_pointer(bfqg->bfqd, bfqd); -+ hlist_add_head_rcu(&bfqg->group_node, &bgrp->group_data); -+ spin_unlock_irq(&bgrp->lock); -+ -+ return bfqg; -+} -+ -+#define SHOW_FUNCTION(__VAR) \ -+static u64 bfqio_cgroup_##__VAR##_read(struct cgroup_subsys_state *css, \ -+ struct cftype *cftype) \ -+{ \ -+ struct bfqio_cgroup *bgrp = css_to_bfqio(css); \ -+ u64 ret = -ENODEV; \ -+ \ -+ mutex_lock(&bfqio_mutex); \ -+ if (bfqio_is_removed(bgrp)) \ -+ goto out_unlock; \ -+ \ -+ spin_lock_irq(&bgrp->lock); \ -+ ret = bgrp->__VAR; \ -+ spin_unlock_irq(&bgrp->lock); \ -+ \ -+out_unlock: \ -+ mutex_unlock(&bfqio_mutex); \ -+ return ret; \ -+} -+ -+SHOW_FUNCTION(weight); -+SHOW_FUNCTION(ioprio); -+SHOW_FUNCTION(ioprio_class); -+#undef SHOW_FUNCTION -+ -+#define STORE_FUNCTION(__VAR, __MIN, __MAX) \ -+static int bfqio_cgroup_##__VAR##_write(struct cgroup_subsys_state *css,\ -+ struct cftype *cftype, \ -+ u64 val) \ -+{ \ -+ struct bfqio_cgroup *bgrp = css_to_bfqio(css); \ -+ struct bfq_group *bfqg; \ -+ int ret = -EINVAL; \ -+ \ -+ if (val < (__MIN) || val > (__MAX)) \ -+ return ret; \ -+ \ -+ ret = -ENODEV; \ -+ mutex_lock(&bfqio_mutex); \ -+ if (bfqio_is_removed(bgrp)) \ -+ goto out_unlock; \ -+ ret = 0; \ -+ \ -+ spin_lock_irq(&bgrp->lock); \ -+ bgrp->__VAR = (unsigned short)val; \ -+ hlist_for_each_entry(bfqg, &bgrp->group_data, group_node) { \ -+ /* \ -+ * Setting the ioprio_changed flag of the entity \ -+ * to 1 with new_##__VAR == ##__VAR would re-set \ -+ * the value of the weight to its ioprio mapping. \ -+ * Set the flag only if necessary. \ -+ */ \ -+ if ((unsigned short)val != bfqg->entity.new_##__VAR) { \ -+ bfqg->entity.new_##__VAR = (unsigned short)val; \ -+ /* \ -+ * Make sure that the above new value has been \ -+ * stored in bfqg->entity.new_##__VAR before \ -+ * setting the ioprio_changed flag. In fact, \ -+ * this flag may be read asynchronously (in \ -+ * critical sections protected by a different \ -+ * lock than that held here), and finding this \ -+ * flag set may cause the execution of the code \ -+ * for updating parameters whose value may \ -+ * depend also on bfqg->entity.new_##__VAR (in \ -+ * __bfq_entity_update_weight_prio). \ -+ * This barrier makes sure that the new value \ -+ * of bfqg->entity.new_##__VAR is correctly \ -+ * seen in that code. \ -+ */ \ -+ smp_wmb(); \ -+ bfqg->entity.ioprio_changed = 1; \ -+ } \ -+ } \ -+ spin_unlock_irq(&bgrp->lock); \ -+ \ -+out_unlock: \ -+ mutex_unlock(&bfqio_mutex); \ -+ return ret; \ -+} -+ -+STORE_FUNCTION(weight, BFQ_MIN_WEIGHT, BFQ_MAX_WEIGHT); -+STORE_FUNCTION(ioprio, 0, IOPRIO_BE_NR - 1); -+STORE_FUNCTION(ioprio_class, IOPRIO_CLASS_RT, IOPRIO_CLASS_IDLE); -+#undef STORE_FUNCTION -+ -+static struct cftype bfqio_files[] = { -+ { -+ .name = "weight", -+ .read_u64 = bfqio_cgroup_weight_read, -+ .write_u64 = bfqio_cgroup_weight_write, -+ }, -+ { -+ .name = "ioprio", -+ .read_u64 = bfqio_cgroup_ioprio_read, -+ .write_u64 = bfqio_cgroup_ioprio_write, -+ }, -+ { -+ .name = "ioprio_class", -+ .read_u64 = bfqio_cgroup_ioprio_class_read, -+ .write_u64 = bfqio_cgroup_ioprio_class_write, -+ }, -+ { }, /* terminate */ -+}; -+ -+static struct cgroup_subsys_state *bfqio_create(struct cgroup_subsys_state -+ *parent_css) -+{ -+ struct bfqio_cgroup *bgrp; -+ -+ if (parent_css != NULL) { -+ bgrp = kzalloc(sizeof(*bgrp), GFP_KERNEL); -+ if (bgrp == NULL) -+ return ERR_PTR(-ENOMEM); -+ } else -+ bgrp = &bfqio_root_cgroup; -+ -+ spin_lock_init(&bgrp->lock); -+ INIT_HLIST_HEAD(&bgrp->group_data); -+ bgrp->ioprio = BFQ_DEFAULT_GRP_IOPRIO; -+ bgrp->ioprio_class = BFQ_DEFAULT_GRP_CLASS; -+ -+ return &bgrp->css; -+} -+ -+/* -+ * We cannot support shared io contexts, as we have no means to support -+ * two tasks with the same ioc in two different groups without major rework -+ * of the main bic/bfqq data structures. By now we allow a task to change -+ * its cgroup only if it's the only owner of its ioc; the drawback of this -+ * behavior is that a group containing a task that forked using CLONE_IO -+ * will not be destroyed until the tasks sharing the ioc die. -+ */ -+static int bfqio_can_attach(struct cgroup_subsys_state *css, -+ struct cgroup_taskset *tset) -+{ -+ struct task_struct *task; -+ struct io_context *ioc; -+ int ret = 0; -+ -+ cgroup_taskset_for_each(task, tset) { -+ /* -+ * task_lock() is needed to avoid races with -+ * exit_io_context() -+ */ -+ task_lock(task); -+ ioc = task->io_context; -+ if (ioc != NULL && atomic_read(&ioc->nr_tasks) > 1) -+ /* -+ * ioc == NULL means that the task is either too -+ * young or exiting: if it has still no ioc the -+ * ioc can't be shared, if the task is exiting the -+ * attach will fail anyway, no matter what we -+ * return here. -+ */ -+ ret = -EINVAL; -+ task_unlock(task); -+ if (ret) -+ break; -+ } -+ -+ return ret; -+} -+ -+static void bfqio_attach(struct cgroup_subsys_state *css, -+ struct cgroup_taskset *tset) -+{ -+ struct task_struct *task; -+ struct io_context *ioc; -+ struct io_cq *icq; -+ -+ /* -+ * IMPORTANT NOTE: The move of more than one process at a time to a -+ * new group has not yet been tested. -+ */ -+ cgroup_taskset_for_each(task, tset) { -+ ioc = get_task_io_context(task, GFP_ATOMIC, NUMA_NO_NODE); -+ if (ioc) { -+ /* -+ * Handle cgroup change here. -+ */ -+ rcu_read_lock(); -+ hlist_for_each_entry_rcu(icq, &ioc->icq_list, ioc_node) -+ if (!strncmp( -+ icq->q->elevator->type->elevator_name, -+ "bfq", ELV_NAME_MAX)) -+ bfq_bic_change_cgroup(icq_to_bic(icq), -+ css); -+ rcu_read_unlock(); -+ put_io_context(ioc); -+ } -+ } -+} -+ -+static void bfqio_destroy(struct cgroup_subsys_state *css) -+{ -+ struct bfqio_cgroup *bgrp = css_to_bfqio(css); -+ struct hlist_node *tmp; -+ struct bfq_group *bfqg; -+ -+ /* -+ * Since we are destroying the cgroup, there are no more tasks -+ * referencing it, and all the RCU grace periods that may have -+ * referenced it are ended (as the destruction of the parent -+ * cgroup is RCU-safe); bgrp->group_data will not be accessed by -+ * anything else and we don't need any synchronization. -+ */ -+ hlist_for_each_entry_safe(bfqg, tmp, &bgrp->group_data, group_node) -+ bfq_destroy_group(bgrp, bfqg); -+ -+ BUG_ON(!hlist_empty(&bgrp->group_data)); -+ -+ kfree(bgrp); -+} -+ -+static int bfqio_css_online(struct cgroup_subsys_state *css) -+{ -+ struct bfqio_cgroup *bgrp = css_to_bfqio(css); -+ -+ mutex_lock(&bfqio_mutex); -+ bgrp->online = true; -+ mutex_unlock(&bfqio_mutex); -+ -+ return 0; -+} -+ -+static void bfqio_css_offline(struct cgroup_subsys_state *css) -+{ -+ struct bfqio_cgroup *bgrp = css_to_bfqio(css); -+ -+ mutex_lock(&bfqio_mutex); -+ bgrp->online = false; -+ mutex_unlock(&bfqio_mutex); -+} -+ -+struct cgroup_subsys bfqio_cgrp_subsys = { -+ .css_alloc = bfqio_create, -+ .css_online = bfqio_css_online, -+ .css_offline = bfqio_css_offline, -+ .can_attach = bfqio_can_attach, -+ .attach = bfqio_attach, -+ .css_free = bfqio_destroy, -+ .legacy_cftypes = bfqio_files, -+}; -+#else -+static inline void bfq_init_entity(struct bfq_entity *entity, -+ struct bfq_group *bfqg) -+{ -+ entity->weight = entity->new_weight; -+ entity->orig_weight = entity->new_weight; -+ entity->ioprio = entity->new_ioprio; -+ entity->ioprio_class = entity->new_ioprio_class; -+ entity->sched_data = &bfqg->sched_data; -+} -+ -+static inline struct bfq_group * -+bfq_bic_update_cgroup(struct bfq_io_cq *bic) -+{ -+ struct bfq_data *bfqd = bic_to_bfqd(bic); -+ return bfqd->root_group; -+} -+ -+static inline void bfq_bfqq_move(struct bfq_data *bfqd, -+ struct bfq_queue *bfqq, -+ struct bfq_entity *entity, -+ struct bfq_group *bfqg) -+{ -+} -+ -+static void bfq_end_wr_async(struct bfq_data *bfqd) -+{ -+ bfq_end_wr_async_queues(bfqd, bfqd->root_group); -+} -+ -+static inline void bfq_disconnect_groups(struct bfq_data *bfqd) -+{ -+ bfq_put_async_queues(bfqd, bfqd->root_group); -+} -+ -+static inline void bfq_free_root_group(struct bfq_data *bfqd) -+{ -+ kfree(bfqd->root_group); -+} -+ -+static struct bfq_group *bfq_alloc_root_group(struct bfq_data *bfqd, int node) -+{ -+ struct bfq_group *bfqg; -+ int i; -+ -+ bfqg = kmalloc_node(sizeof(*bfqg), GFP_KERNEL | __GFP_ZERO, node); -+ if (bfqg == NULL) -+ return NULL; -+ -+ for (i = 0; i < BFQ_IOPRIO_CLASSES; i++) -+ bfqg->sched_data.service_tree[i] = BFQ_SERVICE_TREE_INIT; -+ -+ return bfqg; -+} -+#endif -diff --git a/block/bfq-ioc.c b/block/bfq-ioc.c -new file mode 100644 -index 0000000..7f6b000 ---- /dev/null -+++ b/block/bfq-ioc.c -@@ -0,0 +1,36 @@ -+/* -+ * BFQ: I/O context handling. -+ * -+ * Based on ideas and code from CFQ: -+ * Copyright (C) 2003 Jens Axboe -+ * -+ * Copyright (C) 2008 Fabio Checconi -+ * Paolo Valente -+ * -+ * Copyright (C) 2010 Paolo Valente -+ */ -+ -+/** -+ * icq_to_bic - convert iocontext queue structure to bfq_io_cq. -+ * @icq: the iocontext queue. -+ */ -+static inline struct bfq_io_cq *icq_to_bic(struct io_cq *icq) -+{ -+ /* bic->icq is the first member, %NULL will convert to %NULL */ -+ return container_of(icq, struct bfq_io_cq, icq); -+} -+ -+/** -+ * bfq_bic_lookup - search into @ioc a bic associated to @bfqd. -+ * @bfqd: the lookup key. -+ * @ioc: the io_context of the process doing I/O. -+ * -+ * Queue lock must be held. -+ */ -+static inline struct bfq_io_cq *bfq_bic_lookup(struct bfq_data *bfqd, -+ struct io_context *ioc) -+{ -+ if (ioc) -+ return icq_to_bic(ioc_lookup_icq(ioc, bfqd->queue)); -+ return NULL; -+} -diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c -new file mode 100644 -index 0000000..97ee934 ---- /dev/null -+++ b/block/bfq-iosched.c -@@ -0,0 +1,3902 @@ -+/* -+ * Budget Fair Queueing (BFQ) disk scheduler. -+ * -+ * Based on ideas and code from CFQ: -+ * Copyright (C) 2003 Jens Axboe -+ * -+ * Copyright (C) 2008 Fabio Checconi -+ * Paolo Valente -+ * -+ * Copyright (C) 2010 Paolo Valente -+ * -+ * Licensed under the GPL-2 as detailed in the accompanying COPYING.BFQ -+ * file. -+ * -+ * BFQ is a proportional-share storage-I/O scheduling algorithm based on -+ * the slice-by-slice service scheme of CFQ. But BFQ assigns budgets, -+ * measured in number of sectors, to processes instead of time slices. The -+ * device is not granted to the in-service process for a given time slice, -+ * but until it has exhausted its assigned budget. This change from the time -+ * to the service domain allows BFQ to distribute the device throughput -+ * among processes as desired, without any distortion due to ZBR, workload -+ * fluctuations or other factors. BFQ uses an ad hoc internal scheduler, -+ * called B-WF2Q+, to schedule processes according to their budgets. More -+ * precisely, BFQ schedules queues associated to processes. Thanks to the -+ * accurate policy of B-WF2Q+, BFQ can afford to assign high budgets to -+ * I/O-bound processes issuing sequential requests (to boost the -+ * throughput), and yet guarantee a low latency to interactive and soft -+ * real-time applications. -+ * -+ * BFQ is described in [1], where also a reference to the initial, more -+ * theoretical paper on BFQ can be found. The interested reader can find -+ * in the latter paper full details on the main algorithm, as well as -+ * formulas of the guarantees and formal proofs of all the properties. -+ * With respect to the version of BFQ presented in these papers, this -+ * implementation adds a few more heuristics, such as the one that -+ * guarantees a low latency to soft real-time applications, and a -+ * hierarchical extension based on H-WF2Q+. -+ * -+ * B-WF2Q+ is based on WF2Q+, that is described in [2], together with -+ * H-WF2Q+, while the augmented tree used to implement B-WF2Q+ with O(log N) -+ * complexity derives from the one introduced with EEVDF in [3]. -+ * -+ * [1] P. Valente and M. Andreolini, ``Improving Application Responsiveness -+ * with the BFQ Disk I/O Scheduler'', -+ * Proceedings of the 5th Annual International Systems and Storage -+ * Conference (SYSTOR '12), June 2012. -+ * -+ * http://algogroup.unimo.it/people/paolo/disk_sched/bf1-v1-suite-results.pdf -+ * -+ * [2] Jon C.R. Bennett and H. Zhang, ``Hierarchical Packet Fair Queueing -+ * Algorithms,'' IEEE/ACM Transactions on Networking, 5(5):675-689, -+ * Oct 1997. -+ * -+ * http://www.cs.cmu.edu/~hzhang/papers/TON-97-Oct.ps.gz -+ * -+ * [3] I. Stoica and H. Abdel-Wahab, ``Earliest Eligible Virtual Deadline -+ * First: A Flexible and Accurate Mechanism for Proportional Share -+ * Resource Allocation,'' technical report. -+ * -+ * http://www.cs.berkeley.edu/~istoica/papers/eevdf-tr-95.pdf -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "bfq.h" -+#include "blk.h" -+ -+/* Max number of dispatches in one round of service. */ -+static const int bfq_quantum = 4; -+ -+/* Expiration time of sync (0) and async (1) requests, in jiffies. */ -+static const int bfq_fifo_expire[2] = { HZ / 4, HZ / 8 }; -+ -+/* Maximum backwards seek, in KiB. */ -+static const int bfq_back_max = 16 * 1024; -+ -+/* Penalty of a backwards seek, in number of sectors. */ -+static const int bfq_back_penalty = 2; -+ -+/* Idling period duration, in jiffies. */ -+static int bfq_slice_idle = HZ / 125; -+ -+/* Default maximum budget values, in sectors and number of requests. */ -+static const int bfq_default_max_budget = 16 * 1024; -+static const int bfq_max_budget_async_rq = 4; -+ -+/* -+ * Async to sync throughput distribution is controlled as follows: -+ * when an async request is served, the entity is charged the number -+ * of sectors of the request, multiplied by the factor below -+ */ -+static const int bfq_async_charge_factor = 10; -+ -+/* Default timeout values, in jiffies, approximating CFQ defaults. */ -+static const int bfq_timeout_sync = HZ / 8; -+static int bfq_timeout_async = HZ / 25; -+ -+struct kmem_cache *bfq_pool; -+ -+/* Below this threshold (in ms), we consider thinktime immediate. */ -+#define BFQ_MIN_TT 2 -+ -+/* hw_tag detection: parallel requests threshold and min samples needed. */ -+#define BFQ_HW_QUEUE_THRESHOLD 4 -+#define BFQ_HW_QUEUE_SAMPLES 32 -+ -+#define BFQQ_SEEK_THR (sector_t)(8 * 1024) -+#define BFQQ_SEEKY(bfqq) ((bfqq)->seek_mean > BFQQ_SEEK_THR) -+ -+/* Min samples used for peak rate estimation (for autotuning). */ -+#define BFQ_PEAK_RATE_SAMPLES 32 -+ -+/* Shift used for peak rate fixed precision calculations. */ -+#define BFQ_RATE_SHIFT 16 -+ -+/* -+ * By default, BFQ computes the duration of the weight raising for -+ * interactive applications automatically, using the following formula: -+ * duration = (R / r) * T, where r is the peak rate of the device, and -+ * R and T are two reference parameters. -+ * In particular, R is the peak rate of the reference device (see below), -+ * and T is a reference time: given the systems that are likely to be -+ * installed on the reference device according to its speed class, T is -+ * about the maximum time needed, under BFQ and while reading two files in -+ * parallel, to load typical large applications on these systems. -+ * In practice, the slower/faster the device at hand is, the more/less it -+ * takes to load applications with respect to the reference device. -+ * Accordingly, the longer/shorter BFQ grants weight raising to interactive -+ * applications. -+ * -+ * BFQ uses four different reference pairs (R, T), depending on: -+ * . whether the device is rotational or non-rotational; -+ * . whether the device is slow, such as old or portable HDDs, as well as -+ * SD cards, or fast, such as newer HDDs and SSDs. -+ * -+ * The device's speed class is dynamically (re)detected in -+ * bfq_update_peak_rate() every time the estimated peak rate is updated. -+ * -+ * In the following definitions, R_slow[0]/R_fast[0] and T_slow[0]/T_fast[0] -+ * are the reference values for a slow/fast rotational device, whereas -+ * R_slow[1]/R_fast[1] and T_slow[1]/T_fast[1] are the reference values for -+ * a slow/fast non-rotational device. Finally, device_speed_thresh are the -+ * thresholds used to switch between speed classes. -+ * Both the reference peak rates and the thresholds are measured in -+ * sectors/usec, left-shifted by BFQ_RATE_SHIFT. -+ */ -+static int R_slow[2] = {1536, 10752}; -+static int R_fast[2] = {17415, 34791}; -+/* -+ * To improve readability, a conversion function is used to initialize the -+ * following arrays, which entails that they can be initialized only in a -+ * function. -+ */ -+static int T_slow[2]; -+static int T_fast[2]; -+static int device_speed_thresh[2]; -+ -+#define BFQ_SERVICE_TREE_INIT ((struct bfq_service_tree) \ -+ { RB_ROOT, RB_ROOT, NULL, NULL, 0, 0 }) -+ -+#define RQ_BIC(rq) ((struct bfq_io_cq *) (rq)->elv.priv[0]) -+#define RQ_BFQQ(rq) ((rq)->elv.priv[1]) -+ -+static inline void bfq_schedule_dispatch(struct bfq_data *bfqd); -+ -+#include "bfq-ioc.c" -+#include "bfq-sched.c" -+#include "bfq-cgroup.c" -+ -+#define bfq_class_idle(bfqq) ((bfqq)->entity.ioprio_class ==\ -+ IOPRIO_CLASS_IDLE) -+#define bfq_class_rt(bfqq) ((bfqq)->entity.ioprio_class ==\ -+ IOPRIO_CLASS_RT) -+ -+#define bfq_sample_valid(samples) ((samples) > 80) -+ -+/* -+ * We regard a request as SYNC, if either it's a read or has the SYNC bit -+ * set (in which case it could also be a direct WRITE). -+ */ -+static inline int bfq_bio_sync(struct bio *bio) -+{ -+ if (bio_data_dir(bio) == READ || (bio->bi_rw & REQ_SYNC)) -+ return 1; -+ -+ return 0; -+} -+ -+/* -+ * Scheduler run of queue, if there are requests pending and no one in the -+ * driver that will restart queueing. -+ */ -+static inline void bfq_schedule_dispatch(struct bfq_data *bfqd) -+{ -+ if (bfqd->queued != 0) { -+ bfq_log(bfqd, "schedule dispatch"); -+ kblockd_schedule_work(&bfqd->unplug_work); -+ } -+} -+ -+/* -+ * Lifted from AS - choose which of rq1 and rq2 that is best served now. -+ * We choose the request that is closesr to the head right now. Distance -+ * behind the head is penalized and only allowed to a certain extent. -+ */ -+static struct request *bfq_choose_req(struct bfq_data *bfqd, -+ struct request *rq1, -+ struct request *rq2, -+ sector_t last) -+{ -+ sector_t s1, s2, d1 = 0, d2 = 0; -+ unsigned long back_max; -+#define BFQ_RQ1_WRAP 0x01 /* request 1 wraps */ -+#define BFQ_RQ2_WRAP 0x02 /* request 2 wraps */ -+ unsigned wrap = 0; /* bit mask: requests behind the disk head? */ -+ -+ if (rq1 == NULL || rq1 == rq2) -+ return rq2; -+ if (rq2 == NULL) -+ return rq1; -+ -+ if (rq_is_sync(rq1) && !rq_is_sync(rq2)) -+ return rq1; -+ else if (rq_is_sync(rq2) && !rq_is_sync(rq1)) -+ return rq2; -+ if ((rq1->cmd_flags & REQ_META) && !(rq2->cmd_flags & REQ_META)) -+ return rq1; -+ else if ((rq2->cmd_flags & REQ_META) && !(rq1->cmd_flags & REQ_META)) -+ return rq2; -+ -+ s1 = blk_rq_pos(rq1); -+ s2 = blk_rq_pos(rq2); -+ -+ /* -+ * By definition, 1KiB is 2 sectors. -+ */ -+ back_max = bfqd->bfq_back_max * 2; -+ -+ /* -+ * Strict one way elevator _except_ in the case where we allow -+ * short backward seeks which are biased as twice the cost of a -+ * similar forward seek. -+ */ -+ if (s1 >= last) -+ d1 = s1 - last; -+ else if (s1 + back_max >= last) -+ d1 = (last - s1) * bfqd->bfq_back_penalty; -+ else -+ wrap |= BFQ_RQ1_WRAP; -+ -+ if (s2 >= last) -+ d2 = s2 - last; -+ else if (s2 + back_max >= last) -+ d2 = (last - s2) * bfqd->bfq_back_penalty; -+ else -+ wrap |= BFQ_RQ2_WRAP; -+ -+ /* Found required data */ -+ -+ /* -+ * By doing switch() on the bit mask "wrap" we avoid having to -+ * check two variables for all permutations: --> faster! -+ */ -+ switch (wrap) { -+ case 0: /* common case for CFQ: rq1 and rq2 not wrapped */ -+ if (d1 < d2) -+ return rq1; -+ else if (d2 < d1) -+ return rq2; -+ else { -+ if (s1 >= s2) -+ return rq1; -+ else -+ return rq2; -+ } -+ -+ case BFQ_RQ2_WRAP: -+ return rq1; -+ case BFQ_RQ1_WRAP: -+ return rq2; -+ case (BFQ_RQ1_WRAP|BFQ_RQ2_WRAP): /* both rqs wrapped */ -+ default: -+ /* -+ * Since both rqs are wrapped, -+ * start with the one that's further behind head -+ * (--> only *one* back seek required), -+ * since back seek takes more time than forward. -+ */ -+ if (s1 <= s2) -+ return rq1; -+ else -+ return rq2; -+ } -+} -+ -+static struct bfq_queue * -+bfq_rq_pos_tree_lookup(struct bfq_data *bfqd, struct rb_root *root, -+ sector_t sector, struct rb_node **ret_parent, -+ struct rb_node ***rb_link) -+{ -+ struct rb_node **p, *parent; -+ struct bfq_queue *bfqq = NULL; -+ -+ parent = NULL; -+ p = &root->rb_node; -+ while (*p) { -+ struct rb_node **n; -+ -+ parent = *p; -+ bfqq = rb_entry(parent, struct bfq_queue, pos_node); -+ -+ /* -+ * Sort strictly based on sector. Smallest to the left, -+ * largest to the right. -+ */ -+ if (sector > blk_rq_pos(bfqq->next_rq)) -+ n = &(*p)->rb_right; -+ else if (sector < blk_rq_pos(bfqq->next_rq)) -+ n = &(*p)->rb_left; -+ else -+ break; -+ p = n; -+ bfqq = NULL; -+ } -+ -+ *ret_parent = parent; -+ if (rb_link) -+ *rb_link = p; -+ -+ bfq_log(bfqd, "rq_pos_tree_lookup %llu: returning %d", -+ (long long unsigned)sector, -+ bfqq != NULL ? bfqq->pid : 0); -+ -+ return bfqq; -+} -+ -+static void bfq_rq_pos_tree_add(struct bfq_data *bfqd, struct bfq_queue *bfqq) -+{ -+ struct rb_node **p, *parent; -+ struct bfq_queue *__bfqq; -+ -+ if (bfqq->pos_root != NULL) { -+ rb_erase(&bfqq->pos_node, bfqq->pos_root); -+ bfqq->pos_root = NULL; -+ } -+ -+ if (bfq_class_idle(bfqq)) -+ return; -+ if (!bfqq->next_rq) -+ return; -+ -+ bfqq->pos_root = &bfqd->rq_pos_tree; -+ __bfqq = bfq_rq_pos_tree_lookup(bfqd, bfqq->pos_root, -+ blk_rq_pos(bfqq->next_rq), &parent, &p); -+ if (__bfqq == NULL) { -+ rb_link_node(&bfqq->pos_node, parent, p); -+ rb_insert_color(&bfqq->pos_node, bfqq->pos_root); -+ } else -+ bfqq->pos_root = NULL; -+} -+ -+/* -+ * Tell whether there are active queues or groups with differentiated weights. -+ */ -+static inline bool bfq_differentiated_weights(struct bfq_data *bfqd) -+{ -+ BUG_ON(!bfqd->hw_tag); -+ /* -+ * For weights to differ, at least one of the trees must contain -+ * at least two nodes. -+ */ -+ return (!RB_EMPTY_ROOT(&bfqd->queue_weights_tree) && -+ (bfqd->queue_weights_tree.rb_node->rb_left || -+ bfqd->queue_weights_tree.rb_node->rb_right) -+#ifdef CONFIG_CGROUP_BFQIO -+ ) || -+ (!RB_EMPTY_ROOT(&bfqd->group_weights_tree) && -+ (bfqd->group_weights_tree.rb_node->rb_left || -+ bfqd->group_weights_tree.rb_node->rb_right) -+#endif -+ ); -+} -+ -+/* -+ * If the weight-counter tree passed as input contains no counter for -+ * the weight of the input entity, then add that counter; otherwise just -+ * increment the existing counter. -+ * -+ * Note that weight-counter trees contain few nodes in mostly symmetric -+ * scenarios. For example, if all queues have the same weight, then the -+ * weight-counter tree for the queues may contain at most one node. -+ * This holds even if low_latency is on, because weight-raised queues -+ * are not inserted in the tree. -+ * In most scenarios, the rate at which nodes are created/destroyed -+ * should be low too. -+ */ -+static void bfq_weights_tree_add(struct bfq_data *bfqd, -+ struct bfq_entity *entity, -+ struct rb_root *root) -+{ -+ struct rb_node **new = &(root->rb_node), *parent = NULL; -+ -+ /* -+ * Do not insert if: -+ * - the device does not support queueing; -+ * - the entity is already associated with a counter, which happens if: -+ * 1) the entity is associated with a queue, 2) a request arrival -+ * has caused the queue to become both non-weight-raised, and hence -+ * change its weight, and backlogged; in this respect, each -+ * of the two events causes an invocation of this function, -+ * 3) this is the invocation of this function caused by the second -+ * event. This second invocation is actually useless, and we handle -+ * this fact by exiting immediately. More efficient or clearer -+ * solutions might possibly be adopted. -+ */ -+ if (!bfqd->hw_tag || entity->weight_counter) -+ return; -+ -+ while (*new) { -+ struct bfq_weight_counter *__counter = container_of(*new, -+ struct bfq_weight_counter, -+ weights_node); -+ parent = *new; -+ -+ if (entity->weight == __counter->weight) { -+ entity->weight_counter = __counter; -+ goto inc_counter; -+ } -+ if (entity->weight < __counter->weight) -+ new = &((*new)->rb_left); -+ else -+ new = &((*new)->rb_right); -+ } -+ -+ entity->weight_counter = kzalloc(sizeof(struct bfq_weight_counter), -+ GFP_ATOMIC); -+ entity->weight_counter->weight = entity->weight; -+ rb_link_node(&entity->weight_counter->weights_node, parent, new); -+ rb_insert_color(&entity->weight_counter->weights_node, root); -+ -+inc_counter: -+ entity->weight_counter->num_active++; -+} -+ -+/* -+ * Decrement the weight counter associated with the entity, and, if the -+ * counter reaches 0, remove the counter from the tree. -+ * See the comments to the function bfq_weights_tree_add() for considerations -+ * about overhead. -+ */ -+static void bfq_weights_tree_remove(struct bfq_data *bfqd, -+ struct bfq_entity *entity, -+ struct rb_root *root) -+{ -+ /* -+ * Check whether the entity is actually associated with a counter. -+ * In fact, the device may not be considered NCQ-capable for a while, -+ * which implies that no insertion in the weight trees is performed, -+ * after which the device may start to be deemed NCQ-capable, and hence -+ * this function may start to be invoked. This may cause the function -+ * to be invoked for entities that are not associated with any counter. -+ */ -+ if (!entity->weight_counter) -+ return; -+ -+ BUG_ON(RB_EMPTY_ROOT(root)); -+ BUG_ON(entity->weight_counter->weight != entity->weight); -+ -+ BUG_ON(!entity->weight_counter->num_active); -+ entity->weight_counter->num_active--; -+ if (entity->weight_counter->num_active > 0) -+ goto reset_entity_pointer; -+ -+ rb_erase(&entity->weight_counter->weights_node, root); -+ kfree(entity->weight_counter); -+ -+reset_entity_pointer: -+ entity->weight_counter = NULL; -+} -+ -+static struct request *bfq_find_next_rq(struct bfq_data *bfqd, -+ struct bfq_queue *bfqq, -+ struct request *last) -+{ -+ struct rb_node *rbnext = rb_next(&last->rb_node); -+ struct rb_node *rbprev = rb_prev(&last->rb_node); -+ struct request *next = NULL, *prev = NULL; -+ -+ BUG_ON(RB_EMPTY_NODE(&last->rb_node)); -+ -+ if (rbprev != NULL) -+ prev = rb_entry_rq(rbprev); -+ -+ if (rbnext != NULL) -+ next = rb_entry_rq(rbnext); -+ else { -+ rbnext = rb_first(&bfqq->sort_list); -+ if (rbnext && rbnext != &last->rb_node) -+ next = rb_entry_rq(rbnext); -+ } -+ -+ return bfq_choose_req(bfqd, next, prev, blk_rq_pos(last)); -+} -+ -+/* see the definition of bfq_async_charge_factor for details */ -+static inline unsigned long bfq_serv_to_charge(struct request *rq, -+ struct bfq_queue *bfqq) -+{ -+ return blk_rq_sectors(rq) * -+ (1 + ((!bfq_bfqq_sync(bfqq)) * (bfqq->wr_coeff == 1) * -+ bfq_async_charge_factor)); -+} -+ -+/** -+ * bfq_updated_next_req - update the queue after a new next_rq selection. -+ * @bfqd: the device data the queue belongs to. -+ * @bfqq: the queue to update. -+ * -+ * If the first request of a queue changes we make sure that the queue -+ * has enough budget to serve at least its first request (if the -+ * request has grown). We do this because if the queue has not enough -+ * budget for its first request, it has to go through two dispatch -+ * rounds to actually get it dispatched. -+ */ -+static void bfq_updated_next_req(struct bfq_data *bfqd, -+ struct bfq_queue *bfqq) -+{ -+ struct bfq_entity *entity = &bfqq->entity; -+ struct bfq_service_tree *st = bfq_entity_service_tree(entity); -+ struct request *next_rq = bfqq->next_rq; -+ unsigned long new_budget; -+ -+ if (next_rq == NULL) -+ return; -+ -+ if (bfqq == bfqd->in_service_queue) -+ /* -+ * In order not to break guarantees, budgets cannot be -+ * changed after an entity has been selected. -+ */ -+ return; -+ -+ BUG_ON(entity->tree != &st->active); -+ BUG_ON(entity == entity->sched_data->in_service_entity); -+ -+ new_budget = max_t(unsigned long, bfqq->max_budget, -+ bfq_serv_to_charge(next_rq, bfqq)); -+ if (entity->budget != new_budget) { -+ entity->budget = new_budget; -+ bfq_log_bfqq(bfqd, bfqq, "updated next rq: new budget %lu", -+ new_budget); -+ bfq_activate_bfqq(bfqd, bfqq); -+ } -+} -+ -+static inline unsigned int bfq_wr_duration(struct bfq_data *bfqd) -+{ -+ u64 dur; -+ -+ if (bfqd->bfq_wr_max_time > 0) -+ return bfqd->bfq_wr_max_time; -+ -+ dur = bfqd->RT_prod; -+ do_div(dur, bfqd->peak_rate); -+ -+ return dur; -+} -+ -+/* Empty burst list and add just bfqq (see comments to bfq_handle_burst) */ -+static inline void bfq_reset_burst_list(struct bfq_data *bfqd, -+ struct bfq_queue *bfqq) -+{ -+ struct bfq_queue *item; -+ struct hlist_node *n; -+ -+ hlist_for_each_entry_safe(item, n, &bfqd->burst_list, burst_list_node) -+ hlist_del_init(&item->burst_list_node); -+ hlist_add_head(&bfqq->burst_list_node, &bfqd->burst_list); -+ bfqd->burst_size = 1; -+} -+ -+/* Add bfqq to the list of queues in current burst (see bfq_handle_burst) */ -+static void bfq_add_to_burst(struct bfq_data *bfqd, struct bfq_queue *bfqq) -+{ -+ /* Increment burst size to take into account also bfqq */ -+ bfqd->burst_size++; -+ -+ if (bfqd->burst_size == bfqd->bfq_large_burst_thresh) { -+ struct bfq_queue *pos, *bfqq_item; -+ struct hlist_node *n; -+ -+ /* -+ * Enough queues have been activated shortly after each -+ * other to consider this burst as large. -+ */ -+ bfqd->large_burst = true; -+ -+ /* -+ * We can now mark all queues in the burst list as -+ * belonging to a large burst. -+ */ -+ hlist_for_each_entry(bfqq_item, &bfqd->burst_list, -+ burst_list_node) -+ bfq_mark_bfqq_in_large_burst(bfqq_item); -+ bfq_mark_bfqq_in_large_burst(bfqq); -+ -+ /* -+ * From now on, and until the current burst finishes, any -+ * new queue being activated shortly after the last queue -+ * was inserted in the burst can be immediately marked as -+ * belonging to a large burst. So the burst list is not -+ * needed any more. Remove it. -+ */ -+ hlist_for_each_entry_safe(pos, n, &bfqd->burst_list, -+ burst_list_node) -+ hlist_del_init(&pos->burst_list_node); -+ } else /* burst not yet large: add bfqq to the burst list */ -+ hlist_add_head(&bfqq->burst_list_node, &bfqd->burst_list); -+} -+ -+/* -+ * If many queues happen to become active shortly after each other, then, -+ * to help the processes associated to these queues get their job done as -+ * soon as possible, it is usually better to not grant either weight-raising -+ * or device idling to these queues. In this comment we describe, firstly, -+ * the reasons why this fact holds, and, secondly, the next function, which -+ * implements the main steps needed to properly mark these queues so that -+ * they can then be treated in a different way. -+ * -+ * As for the terminology, we say that a queue becomes active, i.e., -+ * switches from idle to backlogged, either when it is created (as a -+ * consequence of the arrival of an I/O request), or, if already existing, -+ * when a new request for the queue arrives while the queue is idle. -+ * Bursts of activations, i.e., activations of different queues occurring -+ * shortly after each other, are typically caused by services or applications -+ * that spawn or reactivate many parallel threads/processes. Examples are -+ * systemd during boot or git grep. -+ * -+ * These services or applications benefit mostly from a high throughput: -+ * the quicker the requests of the activated queues are cumulatively served, -+ * the sooner the target job of these queues gets completed. As a consequence, -+ * weight-raising any of these queues, which also implies idling the device -+ * for it, is almost always counterproductive: in most cases it just lowers -+ * throughput. -+ * -+ * On the other hand, a burst of activations may be also caused by the start -+ * of an application that does not consist in a lot of parallel I/O-bound -+ * threads. In fact, with a complex application, the burst may be just a -+ * consequence of the fact that several processes need to be executed to -+ * start-up the application. To start an application as quickly as possible, -+ * the best thing to do is to privilege the I/O related to the application -+ * with respect to all other I/O. Therefore, the best strategy to start as -+ * quickly as possible an application that causes a burst of activations is -+ * to weight-raise all the queues activated during the burst. This is the -+ * exact opposite of the best strategy for the other type of bursts. -+ * -+ * In the end, to take the best action for each of the two cases, the two -+ * types of bursts need to be distinguished. Fortunately, this seems -+ * relatively easy to do, by looking at the sizes of the bursts. In -+ * particular, we found a threshold such that bursts with a larger size -+ * than that threshold are apparently caused only by services or commands -+ * such as systemd or git grep. For brevity, hereafter we call just 'large' -+ * these bursts. BFQ *does not* weight-raise queues whose activations occur -+ * in a large burst. In addition, for each of these queues BFQ performs or -+ * does not perform idling depending on which choice boosts the throughput -+ * most. The exact choice depends on the device and request pattern at -+ * hand. -+ * -+ * Turning back to the next function, it implements all the steps needed -+ * to detect the occurrence of a large burst and to properly mark all the -+ * queues belonging to it (so that they can then be treated in a different -+ * way). This goal is achieved by maintaining a special "burst list" that -+ * holds, temporarily, the queues that belong to the burst in progress. The -+ * list is then used to mark these queues as belonging to a large burst if -+ * the burst does become large. The main steps are the following. -+ * -+ * . when the very first queue is activated, the queue is inserted into the -+ * list (as it could be the first queue in a possible burst) -+ * -+ * . if the current burst has not yet become large, and a queue Q that does -+ * not yet belong to the burst is activated shortly after the last time -+ * at which a new queue entered the burst list, then the function appends -+ * Q to the burst list -+ * -+ * . if, as a consequence of the previous step, the burst size reaches -+ * the large-burst threshold, then -+ * -+ * . all the queues in the burst list are marked as belonging to a -+ * large burst -+ * -+ * . the burst list is deleted; in fact, the burst list already served -+ * its purpose (keeping temporarily track of the queues in a burst, -+ * so as to be able to mark them as belonging to a large burst in the -+ * previous sub-step), and now is not needed any more -+ * -+ * . the device enters a large-burst mode -+ * -+ * . if a queue Q that does not belong to the burst is activated while -+ * the device is in large-burst mode and shortly after the last time -+ * at which a queue either entered the burst list or was marked as -+ * belonging to the current large burst, then Q is immediately marked -+ * as belonging to a large burst. -+ * -+ * . if a queue Q that does not belong to the burst is activated a while -+ * later, i.e., not shortly after, than the last time at which a queue -+ * either entered the burst list or was marked as belonging to the -+ * current large burst, then the current burst is deemed as finished and: -+ * -+ * . the large-burst mode is reset if set -+ * -+ * . the burst list is emptied -+ * -+ * . Q is inserted in the burst list, as Q may be the first queue -+ * in a possible new burst (then the burst list contains just Q -+ * after this step). -+ */ -+static void bfq_handle_burst(struct bfq_data *bfqd, struct bfq_queue *bfqq, -+ bool idle_for_long_time) -+{ -+ /* -+ * If bfqq happened to be activated in a burst, but has been idle -+ * for at least as long as an interactive queue, then we assume -+ * that, in the overall I/O initiated in the burst, the I/O -+ * associated to bfqq is finished. So bfqq does not need to be -+ * treated as a queue belonging to a burst anymore. Accordingly, -+ * we reset bfqq's in_large_burst flag if set, and remove bfqq -+ * from the burst list if it's there. We do not decrement instead -+ * burst_size, because the fact that bfqq does not need to belong -+ * to the burst list any more does not invalidate the fact that -+ * bfqq may have been activated during the current burst. -+ */ -+ if (idle_for_long_time) { -+ hlist_del_init(&bfqq->burst_list_node); -+ bfq_clear_bfqq_in_large_burst(bfqq); -+ } -+ -+ /* -+ * If bfqq is already in the burst list or is part of a large -+ * burst, then there is nothing else to do. -+ */ -+ if (!hlist_unhashed(&bfqq->burst_list_node) || -+ bfq_bfqq_in_large_burst(bfqq)) -+ return; -+ -+ /* -+ * If bfqq's activation happens late enough, then the current -+ * burst is finished, and related data structures must be reset. -+ * -+ * In this respect, consider the special case where bfqq is the very -+ * first queue being activated. In this case, last_ins_in_burst is -+ * not yet significant when we get here. But it is easy to verify -+ * that, whether or not the following condition is true, bfqq will -+ * end up being inserted into the burst list. In particular the -+ * list will happen to contain only bfqq. And this is exactly what -+ * has to happen, as bfqq may be the first queue in a possible -+ * burst. -+ */ -+ if (time_is_before_jiffies(bfqd->last_ins_in_burst + -+ bfqd->bfq_burst_interval)) { -+ bfqd->large_burst = false; -+ bfq_reset_burst_list(bfqd, bfqq); -+ return; -+ } -+ -+ /* -+ * If we get here, then bfqq is being activated shortly after the -+ * last queue. So, if the current burst is also large, we can mark -+ * bfqq as belonging to this large burst immediately. -+ */ -+ if (bfqd->large_burst) { -+ bfq_mark_bfqq_in_large_burst(bfqq); -+ return; -+ } -+ -+ /* -+ * If we get here, then a large-burst state has not yet been -+ * reached, but bfqq is being activated shortly after the last -+ * queue. Then we add bfqq to the burst. -+ */ -+ bfq_add_to_burst(bfqd, bfqq); -+} -+ -+static void bfq_add_request(struct request *rq) -+{ -+ struct bfq_queue *bfqq = RQ_BFQQ(rq); -+ struct bfq_entity *entity = &bfqq->entity; -+ struct bfq_data *bfqd = bfqq->bfqd; -+ struct request *next_rq, *prev; -+ unsigned long old_wr_coeff = bfqq->wr_coeff; -+ bool interactive = false; -+ -+ bfq_log_bfqq(bfqd, bfqq, "add_request %d", rq_is_sync(rq)); -+ bfqq->queued[rq_is_sync(rq)]++; -+ bfqd->queued++; -+ -+ elv_rb_add(&bfqq->sort_list, rq); -+ -+ /* -+ * Check if this request is a better next-serve candidate. -+ */ -+ prev = bfqq->next_rq; -+ next_rq = bfq_choose_req(bfqd, bfqq->next_rq, rq, bfqd->last_position); -+ BUG_ON(next_rq == NULL); -+ bfqq->next_rq = next_rq; -+ -+ /* -+ * Adjust priority tree position, if next_rq changes. -+ */ -+ if (prev != bfqq->next_rq) -+ bfq_rq_pos_tree_add(bfqd, bfqq); -+ -+ if (!bfq_bfqq_busy(bfqq)) { -+ bool soft_rt, -+ idle_for_long_time = time_is_before_jiffies( -+ bfqq->budget_timeout + -+ bfqd->bfq_wr_min_idle_time); -+ -+ if (bfq_bfqq_sync(bfqq)) { -+ bool already_in_burst = -+ !hlist_unhashed(&bfqq->burst_list_node) || -+ bfq_bfqq_in_large_burst(bfqq); -+ bfq_handle_burst(bfqd, bfqq, idle_for_long_time); -+ /* -+ * If bfqq was not already in the current burst, -+ * then, at this point, bfqq either has been -+ * added to the current burst or has caused the -+ * current burst to terminate. In particular, in -+ * the second case, bfqq has become the first -+ * queue in a possible new burst. -+ * In both cases last_ins_in_burst needs to be -+ * moved forward. -+ */ -+ if (!already_in_burst) -+ bfqd->last_ins_in_burst = jiffies; -+ } -+ -+ soft_rt = bfqd->bfq_wr_max_softrt_rate > 0 && -+ !bfq_bfqq_in_large_burst(bfqq) && -+ time_is_before_jiffies(bfqq->soft_rt_next_start); -+ interactive = !bfq_bfqq_in_large_burst(bfqq) && -+ idle_for_long_time; -+ entity->budget = max_t(unsigned long, bfqq->max_budget, -+ bfq_serv_to_charge(next_rq, bfqq)); -+ -+ if (!bfq_bfqq_IO_bound(bfqq)) { -+ if (time_before(jiffies, -+ RQ_BIC(rq)->ttime.last_end_request + -+ bfqd->bfq_slice_idle)) { -+ bfqq->requests_within_timer++; -+ if (bfqq->requests_within_timer >= -+ bfqd->bfq_requests_within_timer) -+ bfq_mark_bfqq_IO_bound(bfqq); -+ } else -+ bfqq->requests_within_timer = 0; -+ } -+ -+ if (!bfqd->low_latency) -+ goto add_bfqq_busy; -+ -+ /* -+ * If the queue is not being boosted and has been idle -+ * for enough time, start a weight-raising period -+ */ -+ if (old_wr_coeff == 1 && (interactive || soft_rt)) { -+ bfqq->wr_coeff = bfqd->bfq_wr_coeff; -+ if (interactive) -+ bfqq->wr_cur_max_time = bfq_wr_duration(bfqd); -+ else -+ bfqq->wr_cur_max_time = -+ bfqd->bfq_wr_rt_max_time; -+ bfq_log_bfqq(bfqd, bfqq, -+ "wrais starting at %lu, rais_max_time %u", -+ jiffies, -+ jiffies_to_msecs(bfqq->wr_cur_max_time)); -+ } else if (old_wr_coeff > 1) { -+ if (interactive) -+ bfqq->wr_cur_max_time = bfq_wr_duration(bfqd); -+ else if (bfq_bfqq_in_large_burst(bfqq) || -+ (bfqq->wr_cur_max_time == -+ bfqd->bfq_wr_rt_max_time && -+ !soft_rt)) { -+ bfqq->wr_coeff = 1; -+ bfq_log_bfqq(bfqd, bfqq, -+ "wrais ending at %lu, rais_max_time %u", -+ jiffies, -+ jiffies_to_msecs(bfqq-> -+ wr_cur_max_time)); -+ } else if (time_before( -+ bfqq->last_wr_start_finish + -+ bfqq->wr_cur_max_time, -+ jiffies + -+ bfqd->bfq_wr_rt_max_time) && -+ soft_rt) { -+ /* -+ * -+ * The remaining weight-raising time is lower -+ * than bfqd->bfq_wr_rt_max_time, which -+ * means that the application is enjoying -+ * weight raising either because deemed soft- -+ * rt in the near past, or because deemed -+ * interactive a long ago. In both cases, -+ * resetting now the current remaining weight- -+ * raising time for the application to the -+ * weight-raising duration for soft rt -+ * applications would not cause any latency -+ * increase for the application (as the new -+ * duration would be higher than the remaining -+ * time). -+ * -+ * In addition, the application is now meeting -+ * the requirements for being deemed soft rt. -+ * In the end we can correctly and safely -+ * (re)charge the weight-raising duration for -+ * the application with the weight-raising -+ * duration for soft rt applications. -+ * -+ * In particular, doing this recharge now, i.e., -+ * before the weight-raising period for the -+ * application finishes, reduces the probability -+ * of the following negative scenario: -+ * 1) the weight of a soft rt application is -+ * raised at startup (as for any newly -+ * created application), -+ * 2) since the application is not interactive, -+ * at a certain time weight-raising is -+ * stopped for the application, -+ * 3) at that time the application happens to -+ * still have pending requests, and hence -+ * is destined to not have a chance to be -+ * deemed soft rt before these requests are -+ * completed (see the comments to the -+ * function bfq_bfqq_softrt_next_start() -+ * for details on soft rt detection), -+ * 4) these pending requests experience a high -+ * latency because the application is not -+ * weight-raised while they are pending. -+ */ -+ bfqq->last_wr_start_finish = jiffies; -+ bfqq->wr_cur_max_time = -+ bfqd->bfq_wr_rt_max_time; -+ } -+ } -+ if (old_wr_coeff != bfqq->wr_coeff) -+ entity->ioprio_changed = 1; -+add_bfqq_busy: -+ bfqq->last_idle_bklogged = jiffies; -+ bfqq->service_from_backlogged = 0; -+ bfq_clear_bfqq_softrt_update(bfqq); -+ bfq_add_bfqq_busy(bfqd, bfqq); -+ } else { -+ if (bfqd->low_latency && old_wr_coeff == 1 && !rq_is_sync(rq) && -+ time_is_before_jiffies( -+ bfqq->last_wr_start_finish + -+ bfqd->bfq_wr_min_inter_arr_async)) { -+ bfqq->wr_coeff = bfqd->bfq_wr_coeff; -+ bfqq->wr_cur_max_time = bfq_wr_duration(bfqd); -+ -+ bfqd->wr_busy_queues++; -+ entity->ioprio_changed = 1; -+ bfq_log_bfqq(bfqd, bfqq, -+ "non-idle wrais starting at %lu, rais_max_time %u", -+ jiffies, -+ jiffies_to_msecs(bfqq->wr_cur_max_time)); -+ } -+ if (prev != bfqq->next_rq) -+ bfq_updated_next_req(bfqd, bfqq); -+ } -+ -+ if (bfqd->low_latency && -+ (old_wr_coeff == 1 || bfqq->wr_coeff == 1 || interactive)) -+ bfqq->last_wr_start_finish = jiffies; -+} -+ -+static struct request *bfq_find_rq_fmerge(struct bfq_data *bfqd, -+ struct bio *bio) -+{ -+ struct task_struct *tsk = current; -+ struct bfq_io_cq *bic; -+ struct bfq_queue *bfqq; -+ -+ bic = bfq_bic_lookup(bfqd, tsk->io_context); -+ if (bic == NULL) -+ return NULL; -+ -+ bfqq = bic_to_bfqq(bic, bfq_bio_sync(bio)); -+ if (bfqq != NULL) -+ return elv_rb_find(&bfqq->sort_list, bio_end_sector(bio)); -+ -+ return NULL; -+} -+ -+static void bfq_activate_request(struct request_queue *q, struct request *rq) -+{ -+ struct bfq_data *bfqd = q->elevator->elevator_data; -+ -+ bfqd->rq_in_driver++; -+ bfqd->last_position = blk_rq_pos(rq) + blk_rq_sectors(rq); -+ bfq_log(bfqd, "activate_request: new bfqd->last_position %llu", -+ (long long unsigned)bfqd->last_position); -+} -+ -+static inline void bfq_deactivate_request(struct request_queue *q, -+ struct request *rq) -+{ -+ struct bfq_data *bfqd = q->elevator->elevator_data; -+ -+ BUG_ON(bfqd->rq_in_driver == 0); -+ bfqd->rq_in_driver--; -+} -+ -+static void bfq_remove_request(struct request *rq) -+{ -+ struct bfq_queue *bfqq = RQ_BFQQ(rq); -+ struct bfq_data *bfqd = bfqq->bfqd; -+ const int sync = rq_is_sync(rq); -+ -+ if (bfqq->next_rq == rq) { -+ bfqq->next_rq = bfq_find_next_rq(bfqd, bfqq, rq); -+ bfq_updated_next_req(bfqd, bfqq); -+ } -+ -+ list_del_init(&rq->queuelist); -+ BUG_ON(bfqq->queued[sync] == 0); -+ bfqq->queued[sync]--; -+ bfqd->queued--; -+ elv_rb_del(&bfqq->sort_list, rq); -+ -+ if (RB_EMPTY_ROOT(&bfqq->sort_list)) { -+ if (bfq_bfqq_busy(bfqq) && bfqq != bfqd->in_service_queue) -+ bfq_del_bfqq_busy(bfqd, bfqq, 1); -+ /* -+ * Remove queue from request-position tree as it is empty. -+ */ -+ if (bfqq->pos_root != NULL) { -+ rb_erase(&bfqq->pos_node, bfqq->pos_root); -+ bfqq->pos_root = NULL; -+ } -+ } -+ -+ if (rq->cmd_flags & REQ_META) { -+ BUG_ON(bfqq->meta_pending == 0); -+ bfqq->meta_pending--; -+ } -+} -+ -+static int bfq_merge(struct request_queue *q, struct request **req, -+ struct bio *bio) -+{ -+ struct bfq_data *bfqd = q->elevator->elevator_data; -+ struct request *__rq; -+ -+ __rq = bfq_find_rq_fmerge(bfqd, bio); -+ if (__rq != NULL && elv_rq_merge_ok(__rq, bio)) { -+ *req = __rq; -+ return ELEVATOR_FRONT_MERGE; -+ } -+ -+ return ELEVATOR_NO_MERGE; -+} -+ -+static void bfq_merged_request(struct request_queue *q, struct request *req, -+ int type) -+{ -+ if (type == ELEVATOR_FRONT_MERGE && -+ rb_prev(&req->rb_node) && -+ blk_rq_pos(req) < -+ blk_rq_pos(container_of(rb_prev(&req->rb_node), -+ struct request, rb_node))) { -+ struct bfq_queue *bfqq = RQ_BFQQ(req); -+ struct bfq_data *bfqd = bfqq->bfqd; -+ struct request *prev, *next_rq; -+ -+ /* Reposition request in its sort_list */ -+ elv_rb_del(&bfqq->sort_list, req); -+ elv_rb_add(&bfqq->sort_list, req); -+ /* Choose next request to be served for bfqq */ -+ prev = bfqq->next_rq; -+ next_rq = bfq_choose_req(bfqd, bfqq->next_rq, req, -+ bfqd->last_position); -+ BUG_ON(next_rq == NULL); -+ bfqq->next_rq = next_rq; -+ /* -+ * If next_rq changes, update both the queue's budget to -+ * fit the new request and the queue's position in its -+ * rq_pos_tree. -+ */ -+ if (prev != bfqq->next_rq) { -+ bfq_updated_next_req(bfqd, bfqq); -+ bfq_rq_pos_tree_add(bfqd, bfqq); -+ } -+ } -+} -+ -+static void bfq_merged_requests(struct request_queue *q, struct request *rq, -+ struct request *next) -+{ -+ struct bfq_queue *bfqq = RQ_BFQQ(rq); -+ -+ /* -+ * Reposition in fifo if next is older than rq. -+ */ -+ if (!list_empty(&rq->queuelist) && !list_empty(&next->queuelist) && -+ time_before(next->fifo_time, rq->fifo_time)) { -+ list_move(&rq->queuelist, &next->queuelist); -+ rq->fifo_time = next->fifo_time; -+ } -+ -+ if (bfqq->next_rq == next) -+ bfqq->next_rq = rq; -+ -+ bfq_remove_request(next); -+} -+ -+/* Must be called with bfqq != NULL */ -+static inline void bfq_bfqq_end_wr(struct bfq_queue *bfqq) -+{ -+ BUG_ON(bfqq == NULL); -+ if (bfq_bfqq_busy(bfqq)) -+ bfqq->bfqd->wr_busy_queues--; -+ bfqq->wr_coeff = 1; -+ bfqq->wr_cur_max_time = 0; -+ /* Trigger a weight change on the next activation of the queue */ -+ bfqq->entity.ioprio_changed = 1; -+} -+ -+static void bfq_end_wr_async_queues(struct bfq_data *bfqd, -+ struct bfq_group *bfqg) -+{ -+ int i, j; -+ -+ for (i = 0; i < 2; i++) -+ for (j = 0; j < IOPRIO_BE_NR; j++) -+ if (bfqg->async_bfqq[i][j] != NULL) -+ bfq_bfqq_end_wr(bfqg->async_bfqq[i][j]); -+ if (bfqg->async_idle_bfqq != NULL) -+ bfq_bfqq_end_wr(bfqg->async_idle_bfqq); -+} -+ -+static void bfq_end_wr(struct bfq_data *bfqd) -+{ -+ struct bfq_queue *bfqq; -+ -+ spin_lock_irq(bfqd->queue->queue_lock); -+ -+ list_for_each_entry(bfqq, &bfqd->active_list, bfqq_list) -+ bfq_bfqq_end_wr(bfqq); -+ list_for_each_entry(bfqq, &bfqd->idle_list, bfqq_list) -+ bfq_bfqq_end_wr(bfqq); -+ bfq_end_wr_async(bfqd); -+ -+ spin_unlock_irq(bfqd->queue->queue_lock); -+} -+ -+static int bfq_allow_merge(struct request_queue *q, struct request *rq, -+ struct bio *bio) -+{ -+ struct bfq_data *bfqd = q->elevator->elevator_data; -+ struct bfq_io_cq *bic; -+ struct bfq_queue *bfqq; -+ -+ /* -+ * Disallow merge of a sync bio into an async request. -+ */ -+ if (bfq_bio_sync(bio) && !rq_is_sync(rq)) -+ return 0; -+ -+ /* -+ * Lookup the bfqq that this bio will be queued with. Allow -+ * merge only if rq is queued there. -+ * Queue lock is held here. -+ */ -+ bic = bfq_bic_lookup(bfqd, current->io_context); -+ if (bic == NULL) -+ return 0; -+ -+ bfqq = bic_to_bfqq(bic, bfq_bio_sync(bio)); -+ return bfqq == RQ_BFQQ(rq); -+} -+ -+static void __bfq_set_in_service_queue(struct bfq_data *bfqd, -+ struct bfq_queue *bfqq) -+{ -+ if (bfqq != NULL) { -+ bfq_mark_bfqq_must_alloc(bfqq); -+ bfq_mark_bfqq_budget_new(bfqq); -+ bfq_clear_bfqq_fifo_expire(bfqq); -+ -+ bfqd->budgets_assigned = (bfqd->budgets_assigned*7 + 256) / 8; -+ -+ bfq_log_bfqq(bfqd, bfqq, -+ "set_in_service_queue, cur-budget = %lu", -+ bfqq->entity.budget); -+ } -+ -+ bfqd->in_service_queue = bfqq; -+} -+ -+/* -+ * Get and set a new queue for service. -+ */ -+static struct bfq_queue *bfq_set_in_service_queue(struct bfq_data *bfqd, -+ struct bfq_queue *bfqq) -+{ -+ if (!bfqq) -+ bfqq = bfq_get_next_queue(bfqd); -+ else -+ bfq_get_next_queue_forced(bfqd, bfqq); -+ -+ __bfq_set_in_service_queue(bfqd, bfqq); -+ return bfqq; -+} -+ -+static inline sector_t bfq_dist_from_last(struct bfq_data *bfqd, -+ struct request *rq) -+{ -+ if (blk_rq_pos(rq) >= bfqd->last_position) -+ return blk_rq_pos(rq) - bfqd->last_position; -+ else -+ return bfqd->last_position - blk_rq_pos(rq); -+} -+ -+/* -+ * Return true if bfqq has no request pending and rq is close enough to -+ * bfqd->last_position, or if rq is closer to bfqd->last_position than -+ * bfqq->next_rq -+ */ -+static inline int bfq_rq_close(struct bfq_data *bfqd, struct request *rq) -+{ -+ return bfq_dist_from_last(bfqd, rq) <= BFQQ_SEEK_THR; -+} -+ -+static struct bfq_queue *bfqq_close(struct bfq_data *bfqd) -+{ -+ struct rb_root *root = &bfqd->rq_pos_tree; -+ struct rb_node *parent, *node; -+ struct bfq_queue *__bfqq; -+ sector_t sector = bfqd->last_position; -+ -+ if (RB_EMPTY_ROOT(root)) -+ return NULL; -+ -+ /* -+ * First, if we find a request starting at the end of the last -+ * request, choose it. -+ */ -+ __bfqq = bfq_rq_pos_tree_lookup(bfqd, root, sector, &parent, NULL); -+ if (__bfqq != NULL) -+ return __bfqq; -+ -+ /* -+ * If the exact sector wasn't found, the parent of the NULL leaf -+ * will contain the closest sector (rq_pos_tree sorted by -+ * next_request position). -+ */ -+ __bfqq = rb_entry(parent, struct bfq_queue, pos_node); -+ if (bfq_rq_close(bfqd, __bfqq->next_rq)) -+ return __bfqq; -+ -+ if (blk_rq_pos(__bfqq->next_rq) < sector) -+ node = rb_next(&__bfqq->pos_node); -+ else -+ node = rb_prev(&__bfqq->pos_node); -+ if (node == NULL) -+ return NULL; -+ -+ __bfqq = rb_entry(node, struct bfq_queue, pos_node); -+ if (bfq_rq_close(bfqd, __bfqq->next_rq)) -+ return __bfqq; -+ -+ return NULL; -+} -+ -+/* -+ * bfqd - obvious -+ * cur_bfqq - passed in so that we don't decide that the current queue -+ * is closely cooperating with itself. -+ * -+ * We are assuming that cur_bfqq has dispatched at least one request, -+ * and that bfqd->last_position reflects a position on the disk associated -+ * with the I/O issued by cur_bfqq. -+ */ -+static struct bfq_queue *bfq_close_cooperator(struct bfq_data *bfqd, -+ struct bfq_queue *cur_bfqq) -+{ -+ struct bfq_queue *bfqq; -+ -+ if (bfq_class_idle(cur_bfqq)) -+ return NULL; -+ if (!bfq_bfqq_sync(cur_bfqq)) -+ return NULL; -+ if (BFQQ_SEEKY(cur_bfqq)) -+ return NULL; -+ -+ /* If device has only one backlogged bfq_queue, don't search. */ -+ if (bfqd->busy_queues == 1) -+ return NULL; -+ -+ /* -+ * We should notice if some of the queues are cooperating, e.g. -+ * working closely on the same area of the disk. In that case, -+ * we can group them together and don't waste time idling. -+ */ -+ bfqq = bfqq_close(bfqd); -+ if (bfqq == NULL || bfqq == cur_bfqq) -+ return NULL; -+ -+ /* -+ * Do not merge queues from different bfq_groups. -+ */ -+ if (bfqq->entity.parent != cur_bfqq->entity.parent) -+ return NULL; -+ -+ /* -+ * It only makes sense to merge sync queues. -+ */ -+ if (!bfq_bfqq_sync(bfqq)) -+ return NULL; -+ if (BFQQ_SEEKY(bfqq)) -+ return NULL; -+ -+ /* -+ * Do not merge queues of different priority classes. -+ */ -+ if (bfq_class_rt(bfqq) != bfq_class_rt(cur_bfqq)) -+ return NULL; -+ -+ return bfqq; -+} -+ -+/* -+ * If enough samples have been computed, return the current max budget -+ * stored in bfqd, which is dynamically updated according to the -+ * estimated disk peak rate; otherwise return the default max budget -+ */ -+static inline unsigned long bfq_max_budget(struct bfq_data *bfqd) -+{ -+ if (bfqd->budgets_assigned < 194) -+ return bfq_default_max_budget; -+ else -+ return bfqd->bfq_max_budget; -+} -+ -+/* -+ * Return min budget, which is a fraction of the current or default -+ * max budget (trying with 1/32) -+ */ -+static inline unsigned long bfq_min_budget(struct bfq_data *bfqd) -+{ -+ if (bfqd->budgets_assigned < 194) -+ return bfq_default_max_budget / 32; -+ else -+ return bfqd->bfq_max_budget / 32; -+} -+ -+static void bfq_arm_slice_timer(struct bfq_data *bfqd) -+{ -+ struct bfq_queue *bfqq = bfqd->in_service_queue; -+ struct bfq_io_cq *bic; -+ unsigned long sl; -+ -+ BUG_ON(!RB_EMPTY_ROOT(&bfqq->sort_list)); -+ -+ /* Processes have exited, don't wait. */ -+ bic = bfqd->in_service_bic; -+ if (bic == NULL || atomic_read(&bic->icq.ioc->active_ref) == 0) -+ return; -+ -+ bfq_mark_bfqq_wait_request(bfqq); -+ -+ /* -+ * We don't want to idle for seeks, but we do want to allow -+ * fair distribution of slice time for a process doing back-to-back -+ * seeks. So allow a little bit of time for him to submit a new rq. -+ * -+ * To prevent processes with (partly) seeky workloads from -+ * being too ill-treated, grant them a small fraction of the -+ * assigned budget before reducing the waiting time to -+ * BFQ_MIN_TT. This happened to help reduce latency. -+ */ -+ sl = bfqd->bfq_slice_idle; -+ /* -+ * Unless the queue is being weight-raised, grant only minimum idle -+ * time if the queue either has been seeky for long enough or has -+ * already proved to be constantly seeky. -+ */ -+ if (bfq_sample_valid(bfqq->seek_samples) && -+ ((BFQQ_SEEKY(bfqq) && bfqq->entity.service > -+ bfq_max_budget(bfqq->bfqd) / 8) || -+ bfq_bfqq_constantly_seeky(bfqq)) && bfqq->wr_coeff == 1) -+ sl = min(sl, msecs_to_jiffies(BFQ_MIN_TT)); -+ else if (bfqq->wr_coeff > 1) -+ sl = sl * 3; -+ bfqd->last_idling_start = ktime_get(); -+ mod_timer(&bfqd->idle_slice_timer, jiffies + sl); -+ bfq_log(bfqd, "arm idle: %u/%u ms", -+ jiffies_to_msecs(sl), jiffies_to_msecs(bfqd->bfq_slice_idle)); -+} -+ -+/* -+ * Set the maximum time for the in-service queue to consume its -+ * budget. This prevents seeky processes from lowering the disk -+ * throughput (always guaranteed with a time slice scheme as in CFQ). -+ */ -+static void bfq_set_budget_timeout(struct bfq_data *bfqd) -+{ -+ struct bfq_queue *bfqq = bfqd->in_service_queue; -+ unsigned int timeout_coeff; -+ if (bfqq->wr_cur_max_time == bfqd->bfq_wr_rt_max_time) -+ timeout_coeff = 1; -+ else -+ timeout_coeff = bfqq->entity.weight / bfqq->entity.orig_weight; -+ -+ bfqd->last_budget_start = ktime_get(); -+ -+ bfq_clear_bfqq_budget_new(bfqq); -+ bfqq->budget_timeout = jiffies + -+ bfqd->bfq_timeout[bfq_bfqq_sync(bfqq)] * timeout_coeff; -+ -+ bfq_log_bfqq(bfqd, bfqq, "set budget_timeout %u", -+ jiffies_to_msecs(bfqd->bfq_timeout[bfq_bfqq_sync(bfqq)] * -+ timeout_coeff)); -+} -+ -+/* -+ * Move request from internal lists to the request queue dispatch list. -+ */ -+static void bfq_dispatch_insert(struct request_queue *q, struct request *rq) -+{ -+ struct bfq_data *bfqd = q->elevator->elevator_data; -+ struct bfq_queue *bfqq = RQ_BFQQ(rq); -+ -+ /* -+ * For consistency, the next instruction should have been executed -+ * after removing the request from the queue and dispatching it. -+ * We execute instead this instruction before bfq_remove_request() -+ * (and hence introduce a temporary inconsistency), for efficiency. -+ * In fact, in a forced_dispatch, this prevents two counters related -+ * to bfqq->dispatched to risk to be uselessly decremented if bfqq -+ * is not in service, and then to be incremented again after -+ * incrementing bfqq->dispatched. -+ */ -+ bfqq->dispatched++; -+ bfq_remove_request(rq); -+ elv_dispatch_sort(q, rq); -+ -+ if (bfq_bfqq_sync(bfqq)) -+ bfqd->sync_flight++; -+} -+ -+/* -+ * Return expired entry, or NULL to just start from scratch in rbtree. -+ */ -+static struct request *bfq_check_fifo(struct bfq_queue *bfqq) -+{ -+ struct request *rq = NULL; -+ -+ if (bfq_bfqq_fifo_expire(bfqq)) -+ return NULL; -+ -+ bfq_mark_bfqq_fifo_expire(bfqq); -+ -+ if (list_empty(&bfqq->fifo)) -+ return NULL; -+ -+ rq = rq_entry_fifo(bfqq->fifo.next); -+ -+ if (time_before(jiffies, rq->fifo_time)) -+ return NULL; -+ -+ return rq; -+} -+ -+/* Must be called with the queue_lock held. */ -+static int bfqq_process_refs(struct bfq_queue *bfqq) -+{ -+ int process_refs, io_refs; -+ -+ io_refs = bfqq->allocated[READ] + bfqq->allocated[WRITE]; -+ process_refs = atomic_read(&bfqq->ref) - io_refs - bfqq->entity.on_st; -+ BUG_ON(process_refs < 0); -+ return process_refs; -+} -+ -+static void bfq_setup_merge(struct bfq_queue *bfqq, struct bfq_queue *new_bfqq) -+{ -+ int process_refs, new_process_refs; -+ struct bfq_queue *__bfqq; -+ -+ /* -+ * If there are no process references on the new_bfqq, then it is -+ * unsafe to follow the ->new_bfqq chain as other bfqq's in the chain -+ * may have dropped their last reference (not just their last process -+ * reference). -+ */ -+ if (!bfqq_process_refs(new_bfqq)) -+ return; -+ -+ /* Avoid a circular list and skip interim queue merges. */ -+ while ((__bfqq = new_bfqq->new_bfqq)) { -+ if (__bfqq == bfqq) -+ return; -+ new_bfqq = __bfqq; -+ } -+ -+ process_refs = bfqq_process_refs(bfqq); -+ new_process_refs = bfqq_process_refs(new_bfqq); -+ /* -+ * If the process for the bfqq has gone away, there is no -+ * sense in merging the queues. -+ */ -+ if (process_refs == 0 || new_process_refs == 0) -+ return; -+ -+ /* -+ * Merge in the direction of the lesser amount of work. -+ */ -+ if (new_process_refs >= process_refs) { -+ bfqq->new_bfqq = new_bfqq; -+ atomic_add(process_refs, &new_bfqq->ref); -+ } else { -+ new_bfqq->new_bfqq = bfqq; -+ atomic_add(new_process_refs, &bfqq->ref); -+ } -+ bfq_log_bfqq(bfqq->bfqd, bfqq, "scheduling merge with queue %d", -+ new_bfqq->pid); -+} -+ -+static inline unsigned long bfq_bfqq_budget_left(struct bfq_queue *bfqq) -+{ -+ struct bfq_entity *entity = &bfqq->entity; -+ return entity->budget - entity->service; -+} -+ -+static void __bfq_bfqq_expire(struct bfq_data *bfqd, struct bfq_queue *bfqq) -+{ -+ BUG_ON(bfqq != bfqd->in_service_queue); -+ -+ __bfq_bfqd_reset_in_service(bfqd); -+ -+ /* -+ * If this bfqq is shared between multiple processes, check -+ * to make sure that those processes are still issuing I/Os -+ * within the mean seek distance. If not, it may be time to -+ * break the queues apart again. -+ */ -+ if (bfq_bfqq_coop(bfqq) && BFQQ_SEEKY(bfqq)) -+ bfq_mark_bfqq_split_coop(bfqq); -+ -+ if (RB_EMPTY_ROOT(&bfqq->sort_list)) { -+ /* -+ * Overloading budget_timeout field to store the time -+ * at which the queue remains with no backlog; used by -+ * the weight-raising mechanism. -+ */ -+ bfqq->budget_timeout = jiffies; -+ bfq_del_bfqq_busy(bfqd, bfqq, 1); -+ } else { -+ bfq_activate_bfqq(bfqd, bfqq); -+ /* -+ * Resort priority tree of potential close cooperators. -+ */ -+ bfq_rq_pos_tree_add(bfqd, bfqq); -+ } -+} -+ -+/** -+ * __bfq_bfqq_recalc_budget - try to adapt the budget to the @bfqq behavior. -+ * @bfqd: device data. -+ * @bfqq: queue to update. -+ * @reason: reason for expiration. -+ * -+ * Handle the feedback on @bfqq budget. See the body for detailed -+ * comments. -+ */ -+static void __bfq_bfqq_recalc_budget(struct bfq_data *bfqd, -+ struct bfq_queue *bfqq, -+ enum bfqq_expiration reason) -+{ -+ struct request *next_rq; -+ unsigned long budget, min_budget; -+ -+ budget = bfqq->max_budget; -+ min_budget = bfq_min_budget(bfqd); -+ -+ BUG_ON(bfqq != bfqd->in_service_queue); -+ -+ bfq_log_bfqq(bfqd, bfqq, "recalc_budg: last budg %lu, budg left %lu", -+ bfqq->entity.budget, bfq_bfqq_budget_left(bfqq)); -+ bfq_log_bfqq(bfqd, bfqq, "recalc_budg: last max_budg %lu, min budg %lu", -+ budget, bfq_min_budget(bfqd)); -+ bfq_log_bfqq(bfqd, bfqq, "recalc_budg: sync %d, seeky %d", -+ bfq_bfqq_sync(bfqq), BFQQ_SEEKY(bfqd->in_service_queue)); -+ -+ if (bfq_bfqq_sync(bfqq)) { -+ switch (reason) { -+ /* -+ * Caveat: in all the following cases we trade latency -+ * for throughput. -+ */ -+ case BFQ_BFQQ_TOO_IDLE: -+ /* -+ * This is the only case where we may reduce -+ * the budget: if there is no request of the -+ * process still waiting for completion, then -+ * we assume (tentatively) that the timer has -+ * expired because the batch of requests of -+ * the process could have been served with a -+ * smaller budget. Hence, betting that -+ * process will behave in the same way when it -+ * becomes backlogged again, we reduce its -+ * next budget. As long as we guess right, -+ * this budget cut reduces the latency -+ * experienced by the process. -+ * -+ * However, if there are still outstanding -+ * requests, then the process may have not yet -+ * issued its next request just because it is -+ * still waiting for the completion of some of -+ * the still outstanding ones. So in this -+ * subcase we do not reduce its budget, on the -+ * contrary we increase it to possibly boost -+ * the throughput, as discussed in the -+ * comments to the BUDGET_TIMEOUT case. -+ */ -+ if (bfqq->dispatched > 0) /* still outstanding reqs */ -+ budget = min(budget * 2, bfqd->bfq_max_budget); -+ else { -+ if (budget > 5 * min_budget) -+ budget -= 4 * min_budget; -+ else -+ budget = min_budget; -+ } -+ break; -+ case BFQ_BFQQ_BUDGET_TIMEOUT: -+ /* -+ * We double the budget here because: 1) it -+ * gives the chance to boost the throughput if -+ * this is not a seeky process (which may have -+ * bumped into this timeout because of, e.g., -+ * ZBR), 2) together with charge_full_budget -+ * it helps give seeky processes higher -+ * timestamps, and hence be served less -+ * frequently. -+ */ -+ budget = min(budget * 2, bfqd->bfq_max_budget); -+ break; -+ case BFQ_BFQQ_BUDGET_EXHAUSTED: -+ /* -+ * The process still has backlog, and did not -+ * let either the budget timeout or the disk -+ * idling timeout expire. Hence it is not -+ * seeky, has a short thinktime and may be -+ * happy with a higher budget too. So -+ * definitely increase the budget of this good -+ * candidate to boost the disk throughput. -+ */ -+ budget = min(budget * 4, bfqd->bfq_max_budget); -+ break; -+ case BFQ_BFQQ_NO_MORE_REQUESTS: -+ /* -+ * Leave the budget unchanged. -+ */ -+ default: -+ return; -+ } -+ } else /* async queue */ -+ /* async queues get always the maximum possible budget -+ * (their ability to dispatch is limited by -+ * @bfqd->bfq_max_budget_async_rq). -+ */ -+ budget = bfqd->bfq_max_budget; -+ -+ bfqq->max_budget = budget; -+ -+ if (bfqd->budgets_assigned >= 194 && bfqd->bfq_user_max_budget == 0 && -+ bfqq->max_budget > bfqd->bfq_max_budget) -+ bfqq->max_budget = bfqd->bfq_max_budget; -+ -+ /* -+ * Make sure that we have enough budget for the next request. -+ * Since the finish time of the bfqq must be kept in sync with -+ * the budget, be sure to call __bfq_bfqq_expire() after the -+ * update. -+ */ -+ next_rq = bfqq->next_rq; -+ if (next_rq != NULL) -+ bfqq->entity.budget = max_t(unsigned long, bfqq->max_budget, -+ bfq_serv_to_charge(next_rq, bfqq)); -+ else -+ bfqq->entity.budget = bfqq->max_budget; -+ -+ bfq_log_bfqq(bfqd, bfqq, "head sect: %u, new budget %lu", -+ next_rq != NULL ? blk_rq_sectors(next_rq) : 0, -+ bfqq->entity.budget); -+} -+ -+static unsigned long bfq_calc_max_budget(u64 peak_rate, u64 timeout) -+{ -+ unsigned long max_budget; -+ -+ /* -+ * The max_budget calculated when autotuning is equal to the -+ * amount of sectors transfered in timeout_sync at the -+ * estimated peak rate. -+ */ -+ max_budget = (unsigned long)(peak_rate * 1000 * -+ timeout >> BFQ_RATE_SHIFT); -+ -+ return max_budget; -+} -+ -+/* -+ * In addition to updating the peak rate, checks whether the process -+ * is "slow", and returns 1 if so. This slow flag is used, in addition -+ * to the budget timeout, to reduce the amount of service provided to -+ * seeky processes, and hence reduce their chances to lower the -+ * throughput. See the code for more details. -+ */ -+static int bfq_update_peak_rate(struct bfq_data *bfqd, struct bfq_queue *bfqq, -+ int compensate, enum bfqq_expiration reason) -+{ -+ u64 bw, usecs, expected, timeout; -+ ktime_t delta; -+ int update = 0; -+ -+ if (!bfq_bfqq_sync(bfqq) || bfq_bfqq_budget_new(bfqq)) -+ return 0; -+ -+ if (compensate) -+ delta = bfqd->last_idling_start; -+ else -+ delta = ktime_get(); -+ delta = ktime_sub(delta, bfqd->last_budget_start); -+ usecs = ktime_to_us(delta); -+ -+ /* Don't trust short/unrealistic values. */ -+ if (usecs < 100 || usecs >= LONG_MAX) -+ return 0; -+ -+ /* -+ * Calculate the bandwidth for the last slice. We use a 64 bit -+ * value to store the peak rate, in sectors per usec in fixed -+ * point math. We do so to have enough precision in the estimate -+ * and to avoid overflows. -+ */ -+ bw = (u64)bfqq->entity.service << BFQ_RATE_SHIFT; -+ do_div(bw, (unsigned long)usecs); -+ -+ timeout = jiffies_to_msecs(bfqd->bfq_timeout[BLK_RW_SYNC]); -+ -+ /* -+ * Use only long (> 20ms) intervals to filter out spikes for -+ * the peak rate estimation. -+ */ -+ if (usecs > 20000) { -+ if (bw > bfqd->peak_rate || -+ (!BFQQ_SEEKY(bfqq) && -+ reason == BFQ_BFQQ_BUDGET_TIMEOUT)) { -+ bfq_log(bfqd, "measured bw =%llu", bw); -+ /* -+ * To smooth oscillations use a low-pass filter with -+ * alpha=7/8, i.e., -+ * new_rate = (7/8) * old_rate + (1/8) * bw -+ */ -+ do_div(bw, 8); -+ if (bw == 0) -+ return 0; -+ bfqd->peak_rate *= 7; -+ do_div(bfqd->peak_rate, 8); -+ bfqd->peak_rate += bw; -+ update = 1; -+ bfq_log(bfqd, "new peak_rate=%llu", bfqd->peak_rate); -+ } -+ -+ update |= bfqd->peak_rate_samples == BFQ_PEAK_RATE_SAMPLES - 1; -+ -+ if (bfqd->peak_rate_samples < BFQ_PEAK_RATE_SAMPLES) -+ bfqd->peak_rate_samples++; -+ -+ if (bfqd->peak_rate_samples == BFQ_PEAK_RATE_SAMPLES && -+ update) { -+ int dev_type = blk_queue_nonrot(bfqd->queue); -+ if (bfqd->bfq_user_max_budget == 0) { -+ bfqd->bfq_max_budget = -+ bfq_calc_max_budget(bfqd->peak_rate, -+ timeout); -+ bfq_log(bfqd, "new max_budget=%lu", -+ bfqd->bfq_max_budget); -+ } -+ if (bfqd->device_speed == BFQ_BFQD_FAST && -+ bfqd->peak_rate < device_speed_thresh[dev_type]) { -+ bfqd->device_speed = BFQ_BFQD_SLOW; -+ bfqd->RT_prod = R_slow[dev_type] * -+ T_slow[dev_type]; -+ } else if (bfqd->device_speed == BFQ_BFQD_SLOW && -+ bfqd->peak_rate > device_speed_thresh[dev_type]) { -+ bfqd->device_speed = BFQ_BFQD_FAST; -+ bfqd->RT_prod = R_fast[dev_type] * -+ T_fast[dev_type]; -+ } -+ } -+ } -+ -+ /* -+ * If the process has been served for a too short time -+ * interval to let its possible sequential accesses prevail on -+ * the initial seek time needed to move the disk head on the -+ * first sector it requested, then give the process a chance -+ * and for the moment return false. -+ */ -+ if (bfqq->entity.budget <= bfq_max_budget(bfqd) / 8) -+ return 0; -+ -+ /* -+ * A process is considered ``slow'' (i.e., seeky, so that we -+ * cannot treat it fairly in the service domain, as it would -+ * slow down too much the other processes) if, when a slice -+ * ends for whatever reason, it has received service at a -+ * rate that would not be high enough to complete the budget -+ * before the budget timeout expiration. -+ */ -+ expected = bw * 1000 * timeout >> BFQ_RATE_SHIFT; -+ -+ /* -+ * Caveat: processes doing IO in the slower disk zones will -+ * tend to be slow(er) even if not seeky. And the estimated -+ * peak rate will actually be an average over the disk -+ * surface. Hence, to not be too harsh with unlucky processes, -+ * we keep a budget/3 margin of safety before declaring a -+ * process slow. -+ */ -+ return expected > (4 * bfqq->entity.budget) / 3; -+} -+ -+/* -+ * To be deemed as soft real-time, an application must meet two -+ * requirements. First, the application must not require an average -+ * bandwidth higher than the approximate bandwidth required to playback or -+ * record a compressed high-definition video. -+ * The next function is invoked on the completion of the last request of a -+ * batch, to compute the next-start time instant, soft_rt_next_start, such -+ * that, if the next request of the application does not arrive before -+ * soft_rt_next_start, then the above requirement on the bandwidth is met. -+ * -+ * The second requirement is that the request pattern of the application is -+ * isochronous, i.e., that, after issuing a request or a batch of requests, -+ * the application stops issuing new requests until all its pending requests -+ * have been completed. After that, the application may issue a new batch, -+ * and so on. -+ * For this reason the next function is invoked to compute -+ * soft_rt_next_start only for applications that meet this requirement, -+ * whereas soft_rt_next_start is set to infinity for applications that do -+ * not. -+ * -+ * Unfortunately, even a greedy application may happen to behave in an -+ * isochronous way if the CPU load is high. In fact, the application may -+ * stop issuing requests while the CPUs are busy serving other processes, -+ * then restart, then stop again for a while, and so on. In addition, if -+ * the disk achieves a low enough throughput with the request pattern -+ * issued by the application (e.g., because the request pattern is random -+ * and/or the device is slow), then the application may meet the above -+ * bandwidth requirement too. To prevent such a greedy application to be -+ * deemed as soft real-time, a further rule is used in the computation of -+ * soft_rt_next_start: soft_rt_next_start must be higher than the current -+ * time plus the maximum time for which the arrival of a request is waited -+ * for when a sync queue becomes idle, namely bfqd->bfq_slice_idle. -+ * This filters out greedy applications, as the latter issue instead their -+ * next request as soon as possible after the last one has been completed -+ * (in contrast, when a batch of requests is completed, a soft real-time -+ * application spends some time processing data). -+ * -+ * Unfortunately, the last filter may easily generate false positives if -+ * only bfqd->bfq_slice_idle is used as a reference time interval and one -+ * or both the following cases occur: -+ * 1) HZ is so low that the duration of a jiffy is comparable to or higher -+ * than bfqd->bfq_slice_idle. This happens, e.g., on slow devices with -+ * HZ=100. -+ * 2) jiffies, instead of increasing at a constant rate, may stop increasing -+ * for a while, then suddenly 'jump' by several units to recover the lost -+ * increments. This seems to happen, e.g., inside virtual machines. -+ * To address this issue, we do not use as a reference time interval just -+ * bfqd->bfq_slice_idle, but bfqd->bfq_slice_idle plus a few jiffies. In -+ * particular we add the minimum number of jiffies for which the filter -+ * seems to be quite precise also in embedded systems and KVM/QEMU virtual -+ * machines. -+ */ -+static inline unsigned long bfq_bfqq_softrt_next_start(struct bfq_data *bfqd, -+ struct bfq_queue *bfqq) -+{ -+ return max(bfqq->last_idle_bklogged + -+ HZ * bfqq->service_from_backlogged / -+ bfqd->bfq_wr_max_softrt_rate, -+ jiffies + bfqq->bfqd->bfq_slice_idle + 4); -+} -+ -+/* -+ * Return the largest-possible time instant such that, for as long as possible, -+ * the current time will be lower than this time instant according to the macro -+ * time_is_before_jiffies(). -+ */ -+static inline unsigned long bfq_infinity_from_now(unsigned long now) -+{ -+ return now + ULONG_MAX / 2; -+} -+ -+/** -+ * bfq_bfqq_expire - expire a queue. -+ * @bfqd: device owning the queue. -+ * @bfqq: the queue to expire. -+ * @compensate: if true, compensate for the time spent idling. -+ * @reason: the reason causing the expiration. -+ * -+ * -+ * If the process associated to the queue is slow (i.e., seeky), or in -+ * case of budget timeout, or, finally, if it is async, we -+ * artificially charge it an entire budget (independently of the -+ * actual service it received). As a consequence, the queue will get -+ * higher timestamps than the correct ones upon reactivation, and -+ * hence it will be rescheduled as if it had received more service -+ * than what it actually received. In the end, this class of processes -+ * will receive less service in proportion to how slowly they consume -+ * their budgets (and hence how seriously they tend to lower the -+ * throughput). -+ * -+ * In contrast, when a queue expires because it has been idling for -+ * too much or because it exhausted its budget, we do not touch the -+ * amount of service it has received. Hence when the queue will be -+ * reactivated and its timestamps updated, the latter will be in sync -+ * with the actual service received by the queue until expiration. -+ * -+ * Charging a full budget to the first type of queues and the exact -+ * service to the others has the effect of using the WF2Q+ policy to -+ * schedule the former on a timeslice basis, without violating the -+ * service domain guarantees of the latter. -+ */ -+static void bfq_bfqq_expire(struct bfq_data *bfqd, -+ struct bfq_queue *bfqq, -+ int compensate, -+ enum bfqq_expiration reason) -+{ -+ int slow; -+ BUG_ON(bfqq != bfqd->in_service_queue); -+ -+ /* Update disk peak rate for autotuning and check whether the -+ * process is slow (see bfq_update_peak_rate). -+ */ -+ slow = bfq_update_peak_rate(bfqd, bfqq, compensate, reason); -+ -+ /* -+ * As above explained, 'punish' slow (i.e., seeky), timed-out -+ * and async queues, to favor sequential sync workloads. -+ * -+ * Processes doing I/O in the slower disk zones will tend to be -+ * slow(er) even if not seeky. Hence, since the estimated peak -+ * rate is actually an average over the disk surface, these -+ * processes may timeout just for bad luck. To avoid punishing -+ * them we do not charge a full budget to a process that -+ * succeeded in consuming at least 2/3 of its budget. -+ */ -+ if (slow || (reason == BFQ_BFQQ_BUDGET_TIMEOUT && -+ bfq_bfqq_budget_left(bfqq) >= bfqq->entity.budget / 3)) -+ bfq_bfqq_charge_full_budget(bfqq); -+ -+ bfqq->service_from_backlogged += bfqq->entity.service; -+ -+ if (BFQQ_SEEKY(bfqq) && reason == BFQ_BFQQ_BUDGET_TIMEOUT && -+ !bfq_bfqq_constantly_seeky(bfqq)) { -+ bfq_mark_bfqq_constantly_seeky(bfqq); -+ if (!blk_queue_nonrot(bfqd->queue)) -+ bfqd->const_seeky_busy_in_flight_queues++; -+ } -+ -+ if (reason == BFQ_BFQQ_TOO_IDLE && -+ bfqq->entity.service <= 2 * bfqq->entity.budget / 10 ) -+ bfq_clear_bfqq_IO_bound(bfqq); -+ -+ if (bfqd->low_latency && bfqq->wr_coeff == 1) -+ bfqq->last_wr_start_finish = jiffies; -+ -+ if (bfqd->low_latency && bfqd->bfq_wr_max_softrt_rate > 0 && -+ RB_EMPTY_ROOT(&bfqq->sort_list)) { -+ /* -+ * If we get here, and there are no outstanding requests, -+ * then the request pattern is isochronous (see the comments -+ * to the function bfq_bfqq_softrt_next_start()). Hence we -+ * can compute soft_rt_next_start. If, instead, the queue -+ * still has outstanding requests, then we have to wait -+ * for the completion of all the outstanding requests to -+ * discover whether the request pattern is actually -+ * isochronous. -+ */ -+ if (bfqq->dispatched == 0) -+ bfqq->soft_rt_next_start = -+ bfq_bfqq_softrt_next_start(bfqd, bfqq); -+ else { -+ /* -+ * The application is still waiting for the -+ * completion of one or more requests: -+ * prevent it from possibly being incorrectly -+ * deemed as soft real-time by setting its -+ * soft_rt_next_start to infinity. In fact, -+ * without this assignment, the application -+ * would be incorrectly deemed as soft -+ * real-time if: -+ * 1) it issued a new request before the -+ * completion of all its in-flight -+ * requests, and -+ * 2) at that time, its soft_rt_next_start -+ * happened to be in the past. -+ */ -+ bfqq->soft_rt_next_start = -+ bfq_infinity_from_now(jiffies); -+ /* -+ * Schedule an update of soft_rt_next_start to when -+ * the task may be discovered to be isochronous. -+ */ -+ bfq_mark_bfqq_softrt_update(bfqq); -+ } -+ } -+ -+ bfq_log_bfqq(bfqd, bfqq, -+ "expire (%d, slow %d, num_disp %d, idle_win %d)", reason, -+ slow, bfqq->dispatched, bfq_bfqq_idle_window(bfqq)); -+ -+ /* -+ * Increase, decrease or leave budget unchanged according to -+ * reason. -+ */ -+ __bfq_bfqq_recalc_budget(bfqd, bfqq, reason); -+ __bfq_bfqq_expire(bfqd, bfqq); -+} -+ -+/* -+ * Budget timeout is not implemented through a dedicated timer, but -+ * just checked on request arrivals and completions, as well as on -+ * idle timer expirations. -+ */ -+static int bfq_bfqq_budget_timeout(struct bfq_queue *bfqq) -+{ -+ if (bfq_bfqq_budget_new(bfqq) || -+ time_before(jiffies, bfqq->budget_timeout)) -+ return 0; -+ return 1; -+} -+ -+/* -+ * If we expire a queue that is waiting for the arrival of a new -+ * request, we may prevent the fictitious timestamp back-shifting that -+ * allows the guarantees of the queue to be preserved (see [1] for -+ * this tricky aspect). Hence we return true only if this condition -+ * does not hold, or if the queue is slow enough to deserve only to be -+ * kicked off for preserving a high throughput. -+*/ -+static inline int bfq_may_expire_for_budg_timeout(struct bfq_queue *bfqq) -+{ -+ bfq_log_bfqq(bfqq->bfqd, bfqq, -+ "may_budget_timeout: wait_request %d left %d timeout %d", -+ bfq_bfqq_wait_request(bfqq), -+ bfq_bfqq_budget_left(bfqq) >= bfqq->entity.budget / 3, -+ bfq_bfqq_budget_timeout(bfqq)); -+ -+ return (!bfq_bfqq_wait_request(bfqq) || -+ bfq_bfqq_budget_left(bfqq) >= bfqq->entity.budget / 3) -+ && -+ bfq_bfqq_budget_timeout(bfqq); -+} -+ -+/* -+ * Device idling is allowed only for the queues for which this function -+ * returns true. For this reason, the return value of this function plays a -+ * critical role for both throughput boosting and service guarantees. The -+ * return value is computed through a logical expression. In this rather -+ * long comment, we try to briefly describe all the details and motivations -+ * behind the components of this logical expression. -+ * -+ * First, the expression is false if bfqq is not sync, or if: bfqq happened -+ * to become active during a large burst of queue activations, and the -+ * pattern of requests bfqq contains boosts the throughput if bfqq is -+ * expired. In fact, queues that became active during a large burst benefit -+ * only from throughput, as discussed in the comments to bfq_handle_burst. -+ * In this respect, expiring bfqq certainly boosts the throughput on NCQ- -+ * capable flash-based devices, whereas, on rotational devices, it boosts -+ * the throughput only if bfqq contains random requests. -+ * -+ * On the opposite end, if (a) bfqq is sync, (b) the above burst-related -+ * condition does not hold, and (c) bfqq is being weight-raised, then the -+ * expression always evaluates to true, as device idling is instrumental -+ * for preserving low-latency guarantees (see [1]). If, instead, conditions -+ * (a) and (b) do hold, but (c) does not, then the expression evaluates to -+ * true only if: (1) bfqq is I/O-bound and has a non-null idle window, and -+ * (2) at least one of the following two conditions holds. -+ * The first condition is that the device is not performing NCQ, because -+ * idling the device most certainly boosts the throughput if this condition -+ * holds and bfqq is I/O-bound and has been granted a non-null idle window. -+ * The second compound condition is made of the logical AND of two components. -+ * -+ * The first component is true only if there is no weight-raised busy -+ * queue. This guarantees that the device is not idled for a sync non- -+ * weight-raised queue when there are busy weight-raised queues. The former -+ * is then expired immediately if empty. Combined with the timestamping -+ * rules of BFQ (see [1] for details), this causes sync non-weight-raised -+ * queues to get a lower number of requests served, and hence to ask for a -+ * lower number of requests from the request pool, before the busy weight- -+ * raised queues get served again. -+ * -+ * This is beneficial for the processes associated with weight-raised -+ * queues, when the request pool is saturated (e.g., in the presence of -+ * write hogs). In fact, if the processes associated with the other queues -+ * ask for requests at a lower rate, then weight-raised processes have a -+ * higher probability to get a request from the pool immediately (or at -+ * least soon) when they need one. Hence they have a higher probability to -+ * actually get a fraction of the disk throughput proportional to their -+ * high weight. This is especially true with NCQ-capable drives, which -+ * enqueue several requests in advance and further reorder internally- -+ * queued requests. -+ * -+ * In the end, mistreating non-weight-raised queues when there are busy -+ * weight-raised queues seems to mitigate starvation problems in the -+ * presence of heavy write workloads and NCQ, and hence to guarantee a -+ * higher application and system responsiveness in these hostile scenarios. -+ * -+ * If the first component of the compound condition is instead true, i.e., -+ * there is no weight-raised busy queue, then the second component of the -+ * compound condition takes into account service-guarantee and throughput -+ * issues related to NCQ (recall that the compound condition is evaluated -+ * only if the device is detected as supporting NCQ). -+ * -+ * As for service guarantees, allowing the drive to enqueue more than one -+ * request at a time, and hence delegating de facto final scheduling -+ * decisions to the drive's internal scheduler, causes loss of control on -+ * the actual request service order. In this respect, when the drive is -+ * allowed to enqueue more than one request at a time, the service -+ * distribution enforced by the drive's internal scheduler is likely to -+ * coincide with the desired device-throughput distribution only in the -+ * following, perfectly symmetric, scenario: -+ * 1) all active queues have the same weight, -+ * 2) all active groups at the same level in the groups tree have the same -+ * weight, -+ * 3) all active groups at the same level in the groups tree have the same -+ * number of children. -+ * -+ * Even in such a scenario, sequential I/O may still receive a preferential -+ * treatment, but this is not likely to be a big issue with flash-based -+ * devices, because of their non-dramatic loss of throughput with random -+ * I/O. Things do differ with HDDs, for which additional care is taken, as -+ * explained after completing the discussion for flash-based devices. -+ * -+ * Unfortunately, keeping the necessary state for evaluating exactly the -+ * above symmetry conditions would be quite complex and time-consuming. -+ * Therefore BFQ evaluates instead the following stronger sub-conditions, -+ * for which it is much easier to maintain the needed state: -+ * 1) all active queues have the same weight, -+ * 2) all active groups have the same weight, -+ * 3) all active groups have at most one active child each. -+ * In particular, the last two conditions are always true if hierarchical -+ * support and the cgroups interface are not enabled, hence no state needs -+ * to be maintained in this case. -+ * -+ * According to the above considerations, the second component of the -+ * compound condition evaluates to true if any of the above symmetry -+ * sub-condition does not hold, or the device is not flash-based. Therefore, -+ * if also the first component is true, then idling is allowed for a sync -+ * queue. These are the only sub-conditions considered if the device is -+ * flash-based, as, for such a device, it is sensible to force idling only -+ * for service-guarantee issues. In fact, as for throughput, idling -+ * NCQ-capable flash-based devices would not boost the throughput even -+ * with sequential I/O; rather it would lower the throughput in proportion -+ * to how fast the device is. In the end, (only) if all the three -+ * sub-conditions hold and the device is flash-based, the compound -+ * condition evaluates to false and therefore no idling is performed. -+ * -+ * As already said, things change with a rotational device, where idling -+ * boosts the throughput with sequential I/O (even with NCQ). Hence, for -+ * such a device the second component of the compound condition evaluates -+ * to true also if the following additional sub-condition does not hold: -+ * the queue is constantly seeky. Unfortunately, this different behavior -+ * with respect to flash-based devices causes an additional asymmetry: if -+ * some sync queues enjoy idling and some other sync queues do not, then -+ * the latter get a low share of the device throughput, simply because the -+ * former get many requests served after being set as in service, whereas -+ * the latter do not. As a consequence, to guarantee the desired throughput -+ * distribution, on HDDs the compound expression evaluates to true (and -+ * hence device idling is performed) also if the following last symmetry -+ * condition does not hold: no other queue is benefiting from idling. Also -+ * this last condition is actually replaced with a simpler-to-maintain and -+ * stronger condition: there is no busy queue which is not constantly seeky -+ * (and hence may also benefit from idling). -+ * -+ * To sum up, when all the required symmetry and throughput-boosting -+ * sub-conditions hold, the second component of the compound condition -+ * evaluates to false, and hence no idling is performed. This helps to -+ * keep the drives' internal queues full on NCQ-capable devices, and hence -+ * to boost the throughput, without causing 'almost' any loss of service -+ * guarantees. The 'almost' follows from the fact that, if the internal -+ * queue of one such device is filled while all the sub-conditions hold, -+ * but at some point in time some sub-condition stops to hold, then it may -+ * become impossible to let requests be served in the new desired order -+ * until all the requests already queued in the device have been served. -+ */ -+static inline bool bfq_bfqq_must_not_expire(struct bfq_queue *bfqq) -+{ -+ struct bfq_data *bfqd = bfqq->bfqd; -+#ifdef CONFIG_CGROUP_BFQIO -+#define symmetric_scenario (!bfqd->active_numerous_groups && \ -+ !bfq_differentiated_weights(bfqd)) -+#else -+#define symmetric_scenario (!bfq_differentiated_weights(bfqd)) -+#endif -+#define cond_for_seeky_on_ncq_hdd (bfq_bfqq_constantly_seeky(bfqq) && \ -+ bfqd->busy_in_flight_queues == \ -+ bfqd->const_seeky_busy_in_flight_queues) -+ -+#define cond_for_expiring_in_burst (bfq_bfqq_in_large_burst(bfqq) && \ -+ bfqd->hw_tag && \ -+ (blk_queue_nonrot(bfqd->queue) || \ -+ bfq_bfqq_constantly_seeky(bfqq))) -+ -+/* -+ * Condition for expiring a non-weight-raised queue (and hence not idling -+ * the device). -+ */ -+#define cond_for_expiring_non_wr (bfqd->hw_tag && \ -+ (bfqd->wr_busy_queues > 0 || \ -+ (symmetric_scenario && \ -+ (blk_queue_nonrot(bfqd->queue) || \ -+ cond_for_seeky_on_ncq_hdd)))) -+ -+ return bfq_bfqq_sync(bfqq) && -+ !cond_for_expiring_in_burst && -+ (bfqq->wr_coeff > 1 || -+ (bfq_bfqq_IO_bound(bfqq) && bfq_bfqq_idle_window(bfqq) && -+ !cond_for_expiring_non_wr) -+ ); -+} -+ -+/* -+ * If the in-service queue is empty but sync, and the function -+ * bfq_bfqq_must_not_expire returns true, then: -+ * 1) the queue must remain in service and cannot be expired, and -+ * 2) the disk must be idled to wait for the possible arrival of a new -+ * request for the queue. -+ * See the comments to the function bfq_bfqq_must_not_expire for the reasons -+ * why performing device idling is the best choice to boost the throughput -+ * and preserve service guarantees when bfq_bfqq_must_not_expire itself -+ * returns true. -+ */ -+static inline bool bfq_bfqq_must_idle(struct bfq_queue *bfqq) -+{ -+ struct bfq_data *bfqd = bfqq->bfqd; -+ -+ return RB_EMPTY_ROOT(&bfqq->sort_list) && bfqd->bfq_slice_idle != 0 && -+ bfq_bfqq_must_not_expire(bfqq); -+} -+ -+/* -+ * Select a queue for service. If we have a current queue in service, -+ * check whether to continue servicing it, or retrieve and set a new one. -+ */ -+static struct bfq_queue *bfq_select_queue(struct bfq_data *bfqd) -+{ -+ struct bfq_queue *bfqq, *new_bfqq = NULL; -+ struct request *next_rq; -+ enum bfqq_expiration reason = BFQ_BFQQ_BUDGET_TIMEOUT; -+ -+ bfqq = bfqd->in_service_queue; -+ if (bfqq == NULL) -+ goto new_queue; -+ -+ bfq_log_bfqq(bfqd, bfqq, "select_queue: already in-service queue"); -+ -+ /* -+ * If another queue has a request waiting within our mean seek -+ * distance, let it run. The expire code will check for close -+ * cooperators and put the close queue at the front of the -+ * service tree. If possible, merge the expiring queue with the -+ * new bfqq. -+ */ -+ new_bfqq = bfq_close_cooperator(bfqd, bfqq); -+ if (new_bfqq != NULL && bfqq->new_bfqq == NULL) -+ bfq_setup_merge(bfqq, new_bfqq); -+ -+ if (bfq_may_expire_for_budg_timeout(bfqq) && -+ !timer_pending(&bfqd->idle_slice_timer) && -+ !bfq_bfqq_must_idle(bfqq)) -+ goto expire; -+ -+ next_rq = bfqq->next_rq; -+ /* -+ * If bfqq has requests queued and it has enough budget left to -+ * serve them, keep the queue, otherwise expire it. -+ */ -+ if (next_rq != NULL) { -+ if (bfq_serv_to_charge(next_rq, bfqq) > -+ bfq_bfqq_budget_left(bfqq)) { -+ reason = BFQ_BFQQ_BUDGET_EXHAUSTED; -+ goto expire; -+ } else { -+ /* -+ * The idle timer may be pending because we may -+ * not disable disk idling even when a new request -+ * arrives. -+ */ -+ if (timer_pending(&bfqd->idle_slice_timer)) { -+ /* -+ * If we get here: 1) at least a new request -+ * has arrived but we have not disabled the -+ * timer because the request was too small, -+ * 2) then the block layer has unplugged -+ * the device, causing the dispatch to be -+ * invoked. -+ * -+ * Since the device is unplugged, now the -+ * requests are probably large enough to -+ * provide a reasonable throughput. -+ * So we disable idling. -+ */ -+ bfq_clear_bfqq_wait_request(bfqq); -+ del_timer(&bfqd->idle_slice_timer); -+ } -+ if (new_bfqq == NULL) -+ goto keep_queue; -+ else -+ goto expire; -+ } -+ } -+ -+ /* -+ * No requests pending. If the in-service queue still has requests -+ * in flight (possibly waiting for a completion) or is idling for a -+ * new request, then keep it. -+ */ -+ if (new_bfqq == NULL && (timer_pending(&bfqd->idle_slice_timer) || -+ (bfqq->dispatched != 0 && bfq_bfqq_must_not_expire(bfqq)))) { -+ bfqq = NULL; -+ goto keep_queue; -+ } else if (new_bfqq != NULL && timer_pending(&bfqd->idle_slice_timer)) { -+ /* -+ * Expiring the queue because there is a close cooperator, -+ * cancel timer. -+ */ -+ bfq_clear_bfqq_wait_request(bfqq); -+ del_timer(&bfqd->idle_slice_timer); -+ } -+ -+ reason = BFQ_BFQQ_NO_MORE_REQUESTS; -+expire: -+ bfq_bfqq_expire(bfqd, bfqq, 0, reason); -+new_queue: -+ bfqq = bfq_set_in_service_queue(bfqd, new_bfqq); -+ bfq_log(bfqd, "select_queue: new queue %d returned", -+ bfqq != NULL ? bfqq->pid : 0); -+keep_queue: -+ return bfqq; -+} -+ -+static void bfq_update_wr_data(struct bfq_data *bfqd, -+ struct bfq_queue *bfqq) -+{ -+ if (bfqq->wr_coeff > 1) { /* queue is being boosted */ -+ struct bfq_entity *entity = &bfqq->entity; -+ -+ bfq_log_bfqq(bfqd, bfqq, -+ "raising period dur %u/%u msec, old coeff %u, w %d(%d)", -+ jiffies_to_msecs(jiffies - -+ bfqq->last_wr_start_finish), -+ jiffies_to_msecs(bfqq->wr_cur_max_time), -+ bfqq->wr_coeff, -+ bfqq->entity.weight, bfqq->entity.orig_weight); -+ -+ BUG_ON(bfqq != bfqd->in_service_queue && entity->weight != -+ entity->orig_weight * bfqq->wr_coeff); -+ if (entity->ioprio_changed) -+ bfq_log_bfqq(bfqd, bfqq, "WARN: pending prio change"); -+ /* -+ * If the queue was activated in a burst, or -+ * too much time has elapsed from the beginning -+ * of this weight-raising, then end weight raising. -+ */ -+ if (bfq_bfqq_in_large_burst(bfqq) || -+ time_is_before_jiffies(bfqq->last_wr_start_finish + -+ bfqq->wr_cur_max_time)) { -+ bfqq->last_wr_start_finish = jiffies; -+ bfq_log_bfqq(bfqd, bfqq, -+ "wrais ending at %lu, rais_max_time %u", -+ bfqq->last_wr_start_finish, -+ jiffies_to_msecs(bfqq->wr_cur_max_time)); -+ bfq_bfqq_end_wr(bfqq); -+ __bfq_entity_update_weight_prio( -+ bfq_entity_service_tree(entity), -+ entity); -+ } -+ } -+} -+ -+/* -+ * Dispatch one request from bfqq, moving it to the request queue -+ * dispatch list. -+ */ -+static int bfq_dispatch_request(struct bfq_data *bfqd, -+ struct bfq_queue *bfqq) -+{ -+ int dispatched = 0; -+ struct request *rq; -+ unsigned long service_to_charge; -+ -+ BUG_ON(RB_EMPTY_ROOT(&bfqq->sort_list)); -+ -+ /* Follow expired path, else get first next available. */ -+ rq = bfq_check_fifo(bfqq); -+ if (rq == NULL) -+ rq = bfqq->next_rq; -+ service_to_charge = bfq_serv_to_charge(rq, bfqq); -+ -+ if (service_to_charge > bfq_bfqq_budget_left(bfqq)) { -+ /* -+ * This may happen if the next rq is chosen in fifo order -+ * instead of sector order. The budget is properly -+ * dimensioned to be always sufficient to serve the next -+ * request only if it is chosen in sector order. The reason -+ * is that it would be quite inefficient and little useful -+ * to always make sure that the budget is large enough to -+ * serve even the possible next rq in fifo order. -+ * In fact, requests are seldom served in fifo order. -+ * -+ * Expire the queue for budget exhaustion, and make sure -+ * that the next act_budget is enough to serve the next -+ * request, even if it comes from the fifo expired path. -+ */ -+ bfqq->next_rq = rq; -+ /* -+ * Since this dispatch is failed, make sure that -+ * a new one will be performed -+ */ -+ if (!bfqd->rq_in_driver) -+ bfq_schedule_dispatch(bfqd); -+ goto expire; -+ } -+ -+ /* Finally, insert request into driver dispatch list. */ -+ bfq_bfqq_served(bfqq, service_to_charge); -+ bfq_dispatch_insert(bfqd->queue, rq); -+ -+ bfq_update_wr_data(bfqd, bfqq); -+ -+ bfq_log_bfqq(bfqd, bfqq, -+ "dispatched %u sec req (%llu), budg left %lu", -+ blk_rq_sectors(rq), -+ (long long unsigned)blk_rq_pos(rq), -+ bfq_bfqq_budget_left(bfqq)); -+ -+ dispatched++; -+ -+ if (bfqd->in_service_bic == NULL) { -+ atomic_long_inc(&RQ_BIC(rq)->icq.ioc->refcount); -+ bfqd->in_service_bic = RQ_BIC(rq); -+ } -+ -+ if (bfqd->busy_queues > 1 && ((!bfq_bfqq_sync(bfqq) && -+ dispatched >= bfqd->bfq_max_budget_async_rq) || -+ bfq_class_idle(bfqq))) -+ goto expire; -+ -+ return dispatched; -+ -+expire: -+ bfq_bfqq_expire(bfqd, bfqq, 0, BFQ_BFQQ_BUDGET_EXHAUSTED); -+ return dispatched; -+} -+ -+static int __bfq_forced_dispatch_bfqq(struct bfq_queue *bfqq) -+{ -+ int dispatched = 0; -+ -+ while (bfqq->next_rq != NULL) { -+ bfq_dispatch_insert(bfqq->bfqd->queue, bfqq->next_rq); -+ dispatched++; -+ } -+ -+ BUG_ON(!list_empty(&bfqq->fifo)); -+ return dispatched; -+} -+ -+/* -+ * Drain our current requests. -+ * Used for barriers and when switching io schedulers on-the-fly. -+ */ -+static int bfq_forced_dispatch(struct bfq_data *bfqd) -+{ -+ struct bfq_queue *bfqq, *n; -+ struct bfq_service_tree *st; -+ int dispatched = 0; -+ -+ bfqq = bfqd->in_service_queue; -+ if (bfqq != NULL) -+ __bfq_bfqq_expire(bfqd, bfqq); -+ -+ /* -+ * Loop through classes, and be careful to leave the scheduler -+ * in a consistent state, as feedback mechanisms and vtime -+ * updates cannot be disabled during the process. -+ */ -+ list_for_each_entry_safe(bfqq, n, &bfqd->active_list, bfqq_list) { -+ st = bfq_entity_service_tree(&bfqq->entity); -+ -+ dispatched += __bfq_forced_dispatch_bfqq(bfqq); -+ bfqq->max_budget = bfq_max_budget(bfqd); -+ -+ bfq_forget_idle(st); -+ } -+ -+ BUG_ON(bfqd->busy_queues != 0); -+ -+ return dispatched; -+} -+ -+static int bfq_dispatch_requests(struct request_queue *q, int force) -+{ -+ struct bfq_data *bfqd = q->elevator->elevator_data; -+ struct bfq_queue *bfqq; -+ int max_dispatch; -+ -+ bfq_log(bfqd, "dispatch requests: %d busy queues", bfqd->busy_queues); -+ if (bfqd->busy_queues == 0) -+ return 0; -+ -+ if (unlikely(force)) -+ return bfq_forced_dispatch(bfqd); -+ -+ bfqq = bfq_select_queue(bfqd); -+ if (bfqq == NULL) -+ return 0; -+ -+ max_dispatch = bfqd->bfq_quantum; -+ if (bfq_class_idle(bfqq)) -+ max_dispatch = 1; -+ -+ if (!bfq_bfqq_sync(bfqq)) -+ max_dispatch = bfqd->bfq_max_budget_async_rq; -+ -+ if (bfqq->dispatched >= max_dispatch) { -+ if (bfqd->busy_queues > 1) -+ return 0; -+ if (bfqq->dispatched >= 4 * max_dispatch) -+ return 0; -+ } -+ -+ if (bfqd->sync_flight != 0 && !bfq_bfqq_sync(bfqq)) -+ return 0; -+ -+ bfq_clear_bfqq_wait_request(bfqq); -+ BUG_ON(timer_pending(&bfqd->idle_slice_timer)); -+ -+ if (!bfq_dispatch_request(bfqd, bfqq)) -+ return 0; -+ -+ bfq_log_bfqq(bfqd, bfqq, "dispatched one request of %d (max_disp %d)", -+ bfqq->pid, max_dispatch); -+ -+ return 1; -+} -+ -+/* -+ * Task holds one reference to the queue, dropped when task exits. Each rq -+ * in-flight on this queue also holds a reference, dropped when rq is freed. -+ * -+ * Queue lock must be held here. -+ */ -+static void bfq_put_queue(struct bfq_queue *bfqq) -+{ -+ struct bfq_data *bfqd = bfqq->bfqd; -+ -+ BUG_ON(atomic_read(&bfqq->ref) <= 0); -+ -+ bfq_log_bfqq(bfqd, bfqq, "put_queue: %p %d", bfqq, -+ atomic_read(&bfqq->ref)); -+ if (!atomic_dec_and_test(&bfqq->ref)) -+ return; -+ -+ BUG_ON(rb_first(&bfqq->sort_list) != NULL); -+ BUG_ON(bfqq->allocated[READ] + bfqq->allocated[WRITE] != 0); -+ BUG_ON(bfqq->entity.tree != NULL); -+ BUG_ON(bfq_bfqq_busy(bfqq)); -+ BUG_ON(bfqd->in_service_queue == bfqq); -+ -+ if (bfq_bfqq_sync(bfqq)) -+ /* -+ * The fact that this queue is being destroyed does not -+ * invalidate the fact that this queue may have been -+ * activated during the current burst. As a consequence, -+ * although the queue does not exist anymore, and hence -+ * needs to be removed from the burst list if there, -+ * the burst size has not to be decremented. -+ */ -+ hlist_del_init(&bfqq->burst_list_node); -+ -+ bfq_log_bfqq(bfqd, bfqq, "put_queue: %p freed", bfqq); -+ -+ kmem_cache_free(bfq_pool, bfqq); -+} -+ -+static void bfq_put_cooperator(struct bfq_queue *bfqq) -+{ -+ struct bfq_queue *__bfqq, *next; -+ -+ /* -+ * If this queue was scheduled to merge with another queue, be -+ * sure to drop the reference taken on that queue (and others in -+ * the merge chain). See bfq_setup_merge and bfq_merge_bfqqs. -+ */ -+ __bfqq = bfqq->new_bfqq; -+ while (__bfqq) { -+ if (__bfqq == bfqq) -+ break; -+ next = __bfqq->new_bfqq; -+ bfq_put_queue(__bfqq); -+ __bfqq = next; -+ } -+} -+ -+static void bfq_exit_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq) -+{ -+ if (bfqq == bfqd->in_service_queue) { -+ __bfq_bfqq_expire(bfqd, bfqq); -+ bfq_schedule_dispatch(bfqd); -+ } -+ -+ bfq_log_bfqq(bfqd, bfqq, "exit_bfqq: %p, %d", bfqq, -+ atomic_read(&bfqq->ref)); -+ -+ bfq_put_cooperator(bfqq); -+ -+ bfq_put_queue(bfqq); -+} -+ -+static inline void bfq_init_icq(struct io_cq *icq) -+{ -+ struct bfq_io_cq *bic = icq_to_bic(icq); -+ -+ bic->ttime.last_end_request = jiffies; -+} -+ -+static void bfq_exit_icq(struct io_cq *icq) -+{ -+ struct bfq_io_cq *bic = icq_to_bic(icq); -+ struct bfq_data *bfqd = bic_to_bfqd(bic); -+ -+ if (bic->bfqq[BLK_RW_ASYNC]) { -+ bfq_exit_bfqq(bfqd, bic->bfqq[BLK_RW_ASYNC]); -+ bic->bfqq[BLK_RW_ASYNC] = NULL; -+ } -+ -+ if (bic->bfqq[BLK_RW_SYNC]) { -+ bfq_exit_bfqq(bfqd, bic->bfqq[BLK_RW_SYNC]); -+ bic->bfqq[BLK_RW_SYNC] = NULL; -+ } -+} -+ -+/* -+ * Update the entity prio values; note that the new values will not -+ * be used until the next (re)activation. -+ */ -+static void bfq_init_prio_data(struct bfq_queue *bfqq, struct bfq_io_cq *bic) -+{ -+ struct task_struct *tsk = current; -+ int ioprio_class; -+ -+ if (!bfq_bfqq_prio_changed(bfqq)) -+ return; -+ -+ ioprio_class = IOPRIO_PRIO_CLASS(bic->ioprio); -+ switch (ioprio_class) { -+ default: -+ dev_err(bfqq->bfqd->queue->backing_dev_info.dev, -+ "bfq: bad prio class %d\n", ioprio_class); -+ case IOPRIO_CLASS_NONE: -+ /* -+ * No prio set, inherit CPU scheduling settings. -+ */ -+ bfqq->entity.new_ioprio = task_nice_ioprio(tsk); -+ bfqq->entity.new_ioprio_class = task_nice_ioclass(tsk); -+ break; -+ case IOPRIO_CLASS_RT: -+ bfqq->entity.new_ioprio = IOPRIO_PRIO_DATA(bic->ioprio); -+ bfqq->entity.new_ioprio_class = IOPRIO_CLASS_RT; -+ break; -+ case IOPRIO_CLASS_BE: -+ bfqq->entity.new_ioprio = IOPRIO_PRIO_DATA(bic->ioprio); -+ bfqq->entity.new_ioprio_class = IOPRIO_CLASS_BE; -+ break; -+ case IOPRIO_CLASS_IDLE: -+ bfqq->entity.new_ioprio_class = IOPRIO_CLASS_IDLE; -+ bfqq->entity.new_ioprio = 7; -+ bfq_clear_bfqq_idle_window(bfqq); -+ break; -+ } -+ -+ if (bfqq->entity.new_ioprio < 0 || -+ bfqq->entity.new_ioprio >= IOPRIO_BE_NR) { -+ printk(KERN_CRIT "bfq_init_prio_data: new_ioprio %d\n", -+ bfqq->entity.new_ioprio); -+ BUG(); -+ } -+ -+ bfqq->entity.ioprio_changed = 1; -+ -+ bfq_clear_bfqq_prio_changed(bfqq); -+} -+ -+static void bfq_changed_ioprio(struct bfq_io_cq *bic) -+{ -+ struct bfq_data *bfqd; -+ struct bfq_queue *bfqq, *new_bfqq; -+ struct bfq_group *bfqg; -+ unsigned long uninitialized_var(flags); -+ int ioprio = bic->icq.ioc->ioprio; -+ -+ bfqd = bfq_get_bfqd_locked(&(bic->icq.q->elevator->elevator_data), -+ &flags); -+ /* -+ * This condition may trigger on a newly created bic, be sure to -+ * drop the lock before returning. -+ */ -+ if (unlikely(bfqd == NULL) || likely(bic->ioprio == ioprio)) -+ goto out; -+ -+ bfqq = bic->bfqq[BLK_RW_ASYNC]; -+ if (bfqq != NULL) { -+ bfqg = container_of(bfqq->entity.sched_data, struct bfq_group, -+ sched_data); -+ new_bfqq = bfq_get_queue(bfqd, bfqg, BLK_RW_ASYNC, bic, -+ GFP_ATOMIC); -+ if (new_bfqq != NULL) { -+ bic->bfqq[BLK_RW_ASYNC] = new_bfqq; -+ bfq_log_bfqq(bfqd, bfqq, -+ "changed_ioprio: bfqq %p %d", -+ bfqq, atomic_read(&bfqq->ref)); -+ bfq_put_queue(bfqq); -+ } -+ } -+ -+ bfqq = bic->bfqq[BLK_RW_SYNC]; -+ if (bfqq != NULL) -+ bfq_mark_bfqq_prio_changed(bfqq); -+ -+ bic->ioprio = ioprio; -+ -+out: -+ bfq_put_bfqd_unlock(bfqd, &flags); -+} -+ -+static void bfq_init_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq, -+ pid_t pid, int is_sync) -+{ -+ RB_CLEAR_NODE(&bfqq->entity.rb_node); -+ INIT_LIST_HEAD(&bfqq->fifo); -+ INIT_HLIST_NODE(&bfqq->burst_list_node); -+ -+ atomic_set(&bfqq->ref, 0); -+ bfqq->bfqd = bfqd; -+ -+ bfq_mark_bfqq_prio_changed(bfqq); -+ -+ if (is_sync) { -+ if (!bfq_class_idle(bfqq)) -+ bfq_mark_bfqq_idle_window(bfqq); -+ bfq_mark_bfqq_sync(bfqq); -+ } -+ bfq_mark_bfqq_IO_bound(bfqq); -+ -+ /* Tentative initial value to trade off between thr and lat */ -+ bfqq->max_budget = (2 * bfq_max_budget(bfqd)) / 3; -+ bfqq->pid = pid; -+ -+ bfqq->wr_coeff = 1; -+ bfqq->last_wr_start_finish = 0; -+ /* -+ * Set to the value for which bfqq will not be deemed as -+ * soft rt when it becomes backlogged. -+ */ -+ bfqq->soft_rt_next_start = bfq_infinity_from_now(jiffies); -+} -+ -+static struct bfq_queue *bfq_find_alloc_queue(struct bfq_data *bfqd, -+ struct bfq_group *bfqg, -+ int is_sync, -+ struct bfq_io_cq *bic, -+ gfp_t gfp_mask) -+{ -+ struct bfq_queue *bfqq, *new_bfqq = NULL; -+ -+retry: -+ /* bic always exists here */ -+ bfqq = bic_to_bfqq(bic, is_sync); -+ -+ /* -+ * Always try a new alloc if we fall back to the OOM bfqq -+ * originally, since it should just be a temporary situation. -+ */ -+ if (bfqq == NULL || bfqq == &bfqd->oom_bfqq) { -+ bfqq = NULL; -+ if (new_bfqq != NULL) { -+ bfqq = new_bfqq; -+ new_bfqq = NULL; -+ } else if (gfp_mask & __GFP_WAIT) { -+ spin_unlock_irq(bfqd->queue->queue_lock); -+ new_bfqq = kmem_cache_alloc_node(bfq_pool, -+ gfp_mask | __GFP_ZERO, -+ bfqd->queue->node); -+ spin_lock_irq(bfqd->queue->queue_lock); -+ if (new_bfqq != NULL) -+ goto retry; -+ } else { -+ bfqq = kmem_cache_alloc_node(bfq_pool, -+ gfp_mask | __GFP_ZERO, -+ bfqd->queue->node); -+ } -+ -+ if (bfqq != NULL) { -+ bfq_init_bfqq(bfqd, bfqq, current->pid, is_sync); -+ bfq_init_prio_data(bfqq, bic); -+ bfq_init_entity(&bfqq->entity, bfqg); -+ bfq_log_bfqq(bfqd, bfqq, "allocated"); -+ } else { -+ bfqq = &bfqd->oom_bfqq; -+ bfq_log_bfqq(bfqd, bfqq, "using oom bfqq"); -+ } -+ } -+ -+ if (new_bfqq != NULL) -+ kmem_cache_free(bfq_pool, new_bfqq); -+ -+ return bfqq; -+} -+ -+static struct bfq_queue **bfq_async_queue_prio(struct bfq_data *bfqd, -+ struct bfq_group *bfqg, -+ int ioprio_class, int ioprio) -+{ -+ switch (ioprio_class) { -+ case IOPRIO_CLASS_RT: -+ return &bfqg->async_bfqq[0][ioprio]; -+ case IOPRIO_CLASS_NONE: -+ ioprio = IOPRIO_NORM; -+ /* fall through */ -+ case IOPRIO_CLASS_BE: -+ return &bfqg->async_bfqq[1][ioprio]; -+ case IOPRIO_CLASS_IDLE: -+ return &bfqg->async_idle_bfqq; -+ default: -+ BUG(); -+ } -+} -+ -+static struct bfq_queue *bfq_get_queue(struct bfq_data *bfqd, -+ struct bfq_group *bfqg, int is_sync, -+ struct bfq_io_cq *bic, gfp_t gfp_mask) -+{ -+ const int ioprio = IOPRIO_PRIO_DATA(bic->ioprio); -+ const int ioprio_class = IOPRIO_PRIO_CLASS(bic->ioprio); -+ struct bfq_queue **async_bfqq = NULL; -+ struct bfq_queue *bfqq = NULL; -+ -+ if (!is_sync) { -+ async_bfqq = bfq_async_queue_prio(bfqd, bfqg, ioprio_class, -+ ioprio); -+ bfqq = *async_bfqq; -+ } -+ -+ if (bfqq == NULL) -+ bfqq = bfq_find_alloc_queue(bfqd, bfqg, is_sync, bic, gfp_mask); -+ -+ /* -+ * Pin the queue now that it's allocated, scheduler exit will -+ * prune it. -+ */ -+ if (!is_sync && *async_bfqq == NULL) { -+ atomic_inc(&bfqq->ref); -+ bfq_log_bfqq(bfqd, bfqq, "get_queue, bfqq not in async: %p, %d", -+ bfqq, atomic_read(&bfqq->ref)); -+ *async_bfqq = bfqq; -+ } -+ -+ atomic_inc(&bfqq->ref); -+ bfq_log_bfqq(bfqd, bfqq, "get_queue, at end: %p, %d", bfqq, -+ atomic_read(&bfqq->ref)); -+ return bfqq; -+} -+ -+static void bfq_update_io_thinktime(struct bfq_data *bfqd, -+ struct bfq_io_cq *bic) -+{ -+ unsigned long elapsed = jiffies - bic->ttime.last_end_request; -+ unsigned long ttime = min(elapsed, 2UL * bfqd->bfq_slice_idle); -+ -+ bic->ttime.ttime_samples = (7*bic->ttime.ttime_samples + 256) / 8; -+ bic->ttime.ttime_total = (7*bic->ttime.ttime_total + 256*ttime) / 8; -+ bic->ttime.ttime_mean = (bic->ttime.ttime_total + 128) / -+ bic->ttime.ttime_samples; -+} -+ -+static void bfq_update_io_seektime(struct bfq_data *bfqd, -+ struct bfq_queue *bfqq, -+ struct request *rq) -+{ -+ sector_t sdist; -+ u64 total; -+ -+ if (bfqq->last_request_pos < blk_rq_pos(rq)) -+ sdist = blk_rq_pos(rq) - bfqq->last_request_pos; -+ else -+ sdist = bfqq->last_request_pos - blk_rq_pos(rq); -+ -+ /* -+ * Don't allow the seek distance to get too large from the -+ * odd fragment, pagein, etc. -+ */ -+ if (bfqq->seek_samples == 0) /* first request, not really a seek */ -+ sdist = 0; -+ else if (bfqq->seek_samples <= 60) /* second & third seek */ -+ sdist = min(sdist, (bfqq->seek_mean * 4) + 2*1024*1024); -+ else -+ sdist = min(sdist, (bfqq->seek_mean * 4) + 2*1024*64); -+ -+ bfqq->seek_samples = (7*bfqq->seek_samples + 256) / 8; -+ bfqq->seek_total = (7*bfqq->seek_total + (u64)256*sdist) / 8; -+ total = bfqq->seek_total + (bfqq->seek_samples/2); -+ do_div(total, bfqq->seek_samples); -+ bfqq->seek_mean = (sector_t)total; -+ -+ bfq_log_bfqq(bfqd, bfqq, "dist=%llu mean=%llu", (u64)sdist, -+ (u64)bfqq->seek_mean); -+} -+ -+/* -+ * Disable idle window if the process thinks too long or seeks so much that -+ * it doesn't matter. -+ */ -+static void bfq_update_idle_window(struct bfq_data *bfqd, -+ struct bfq_queue *bfqq, -+ struct bfq_io_cq *bic) -+{ -+ int enable_idle; -+ -+ /* Don't idle for async or idle io prio class. */ -+ if (!bfq_bfqq_sync(bfqq) || bfq_class_idle(bfqq)) -+ return; -+ -+ enable_idle = bfq_bfqq_idle_window(bfqq); -+ -+ if (atomic_read(&bic->icq.ioc->active_ref) == 0 || -+ bfqd->bfq_slice_idle == 0 || -+ (bfqd->hw_tag && BFQQ_SEEKY(bfqq) && -+ bfqq->wr_coeff == 1)) -+ enable_idle = 0; -+ else if (bfq_sample_valid(bic->ttime.ttime_samples)) { -+ if (bic->ttime.ttime_mean > bfqd->bfq_slice_idle && -+ bfqq->wr_coeff == 1) -+ enable_idle = 0; -+ else -+ enable_idle = 1; -+ } -+ bfq_log_bfqq(bfqd, bfqq, "update_idle_window: enable_idle %d", -+ enable_idle); -+ -+ if (enable_idle) -+ bfq_mark_bfqq_idle_window(bfqq); -+ else -+ bfq_clear_bfqq_idle_window(bfqq); -+} -+ -+/* -+ * Called when a new fs request (rq) is added to bfqq. Check if there's -+ * something we should do about it. -+ */ -+static void bfq_rq_enqueued(struct bfq_data *bfqd, struct bfq_queue *bfqq, -+ struct request *rq) -+{ -+ struct bfq_io_cq *bic = RQ_BIC(rq); -+ -+ if (rq->cmd_flags & REQ_META) -+ bfqq->meta_pending++; -+ -+ bfq_update_io_thinktime(bfqd, bic); -+ bfq_update_io_seektime(bfqd, bfqq, rq); -+ if (!BFQQ_SEEKY(bfqq) && bfq_bfqq_constantly_seeky(bfqq)) { -+ bfq_clear_bfqq_constantly_seeky(bfqq); -+ if (!blk_queue_nonrot(bfqd->queue)) { -+ BUG_ON(!bfqd->const_seeky_busy_in_flight_queues); -+ bfqd->const_seeky_busy_in_flight_queues--; -+ } -+ } -+ if (bfqq->entity.service > bfq_max_budget(bfqd) / 8 || -+ !BFQQ_SEEKY(bfqq)) -+ bfq_update_idle_window(bfqd, bfqq, bic); -+ -+ bfq_log_bfqq(bfqd, bfqq, -+ "rq_enqueued: idle_window=%d (seeky %d, mean %llu)", -+ bfq_bfqq_idle_window(bfqq), BFQQ_SEEKY(bfqq), -+ (long long unsigned)bfqq->seek_mean); -+ -+ bfqq->last_request_pos = blk_rq_pos(rq) + blk_rq_sectors(rq); -+ -+ if (bfqq == bfqd->in_service_queue && bfq_bfqq_wait_request(bfqq)) { -+ int small_req = bfqq->queued[rq_is_sync(rq)] == 1 && -+ blk_rq_sectors(rq) < 32; -+ int budget_timeout = bfq_bfqq_budget_timeout(bfqq); -+ -+ /* -+ * There is just this request queued: if the request -+ * is small and the queue is not to be expired, then -+ * just exit. -+ * -+ * In this way, if the disk is being idled to wait for -+ * a new request from the in-service queue, we avoid -+ * unplugging the device and committing the disk to serve -+ * just a small request. On the contrary, we wait for -+ * the block layer to decide when to unplug the device: -+ * hopefully, new requests will be merged to this one -+ * quickly, then the device will be unplugged and -+ * larger requests will be dispatched. -+ */ -+ if (small_req && !budget_timeout) -+ return; -+ -+ /* -+ * A large enough request arrived, or the queue is to -+ * be expired: in both cases disk idling is to be -+ * stopped, so clear wait_request flag and reset -+ * timer. -+ */ -+ bfq_clear_bfqq_wait_request(bfqq); -+ del_timer(&bfqd->idle_slice_timer); -+ -+ /* -+ * The queue is not empty, because a new request just -+ * arrived. Hence we can safely expire the queue, in -+ * case of budget timeout, without risking that the -+ * timestamps of the queue are not updated correctly. -+ * See [1] for more details. -+ */ -+ if (budget_timeout) -+ bfq_bfqq_expire(bfqd, bfqq, 0, BFQ_BFQQ_BUDGET_TIMEOUT); -+ -+ /* -+ * Let the request rip immediately, or let a new queue be -+ * selected if bfqq has just been expired. -+ */ -+ __blk_run_queue(bfqd->queue); -+ } -+} -+ -+static void bfq_insert_request(struct request_queue *q, struct request *rq) -+{ -+ struct bfq_data *bfqd = q->elevator->elevator_data; -+ struct bfq_queue *bfqq = RQ_BFQQ(rq); -+ -+ assert_spin_locked(bfqd->queue->queue_lock); -+ bfq_init_prio_data(bfqq, RQ_BIC(rq)); -+ -+ bfq_add_request(rq); -+ -+ rq->fifo_time = jiffies + bfqd->bfq_fifo_expire[rq_is_sync(rq)]; -+ list_add_tail(&rq->queuelist, &bfqq->fifo); -+ -+ bfq_rq_enqueued(bfqd, bfqq, rq); -+} -+ -+static void bfq_update_hw_tag(struct bfq_data *bfqd) -+{ -+ bfqd->max_rq_in_driver = max(bfqd->max_rq_in_driver, -+ bfqd->rq_in_driver); -+ -+ if (bfqd->hw_tag == 1) -+ return; -+ -+ /* -+ * This sample is valid if the number of outstanding requests -+ * is large enough to allow a queueing behavior. Note that the -+ * sum is not exact, as it's not taking into account deactivated -+ * requests. -+ */ -+ if (bfqd->rq_in_driver + bfqd->queued < BFQ_HW_QUEUE_THRESHOLD) -+ return; -+ -+ if (bfqd->hw_tag_samples++ < BFQ_HW_QUEUE_SAMPLES) -+ return; -+ -+ bfqd->hw_tag = bfqd->max_rq_in_driver > BFQ_HW_QUEUE_THRESHOLD; -+ bfqd->max_rq_in_driver = 0; -+ bfqd->hw_tag_samples = 0; -+} -+ -+static void bfq_completed_request(struct request_queue *q, struct request *rq) -+{ -+ struct bfq_queue *bfqq = RQ_BFQQ(rq); -+ struct bfq_data *bfqd = bfqq->bfqd; -+ bool sync = bfq_bfqq_sync(bfqq); -+ -+ bfq_log_bfqq(bfqd, bfqq, "completed one req with %u sects left (%d)", -+ blk_rq_sectors(rq), sync); -+ -+ bfq_update_hw_tag(bfqd); -+ -+ BUG_ON(!bfqd->rq_in_driver); -+ BUG_ON(!bfqq->dispatched); -+ bfqd->rq_in_driver--; -+ bfqq->dispatched--; -+ -+ if (!bfqq->dispatched && !bfq_bfqq_busy(bfqq)) { -+ bfq_weights_tree_remove(bfqd, &bfqq->entity, -+ &bfqd->queue_weights_tree); -+ if (!blk_queue_nonrot(bfqd->queue)) { -+ BUG_ON(!bfqd->busy_in_flight_queues); -+ bfqd->busy_in_flight_queues--; -+ if (bfq_bfqq_constantly_seeky(bfqq)) { -+ BUG_ON(!bfqd-> -+ const_seeky_busy_in_flight_queues); -+ bfqd->const_seeky_busy_in_flight_queues--; -+ } -+ } -+ } -+ -+ if (sync) { -+ bfqd->sync_flight--; -+ RQ_BIC(rq)->ttime.last_end_request = jiffies; -+ } -+ -+ /* -+ * If we are waiting to discover whether the request pattern of the -+ * task associated with the queue is actually isochronous, and -+ * both requisites for this condition to hold are satisfied, then -+ * compute soft_rt_next_start (see the comments to the function -+ * bfq_bfqq_softrt_next_start()). -+ */ -+ if (bfq_bfqq_softrt_update(bfqq) && bfqq->dispatched == 0 && -+ RB_EMPTY_ROOT(&bfqq->sort_list)) -+ bfqq->soft_rt_next_start = -+ bfq_bfqq_softrt_next_start(bfqd, bfqq); -+ -+ /* -+ * If this is the in-service queue, check if it needs to be expired, -+ * or if we want to idle in case it has no pending requests. -+ */ -+ if (bfqd->in_service_queue == bfqq) { -+ if (bfq_bfqq_budget_new(bfqq)) -+ bfq_set_budget_timeout(bfqd); -+ -+ if (bfq_bfqq_must_idle(bfqq)) { -+ bfq_arm_slice_timer(bfqd); -+ goto out; -+ } else if (bfq_may_expire_for_budg_timeout(bfqq)) -+ bfq_bfqq_expire(bfqd, bfqq, 0, BFQ_BFQQ_BUDGET_TIMEOUT); -+ else if (RB_EMPTY_ROOT(&bfqq->sort_list) && -+ (bfqq->dispatched == 0 || -+ !bfq_bfqq_must_not_expire(bfqq))) -+ bfq_bfqq_expire(bfqd, bfqq, 0, -+ BFQ_BFQQ_NO_MORE_REQUESTS); -+ } -+ -+ if (!bfqd->rq_in_driver) -+ bfq_schedule_dispatch(bfqd); -+ -+out: -+ return; -+} -+ -+static inline int __bfq_may_queue(struct bfq_queue *bfqq) -+{ -+ if (bfq_bfqq_wait_request(bfqq) && bfq_bfqq_must_alloc(bfqq)) { -+ bfq_clear_bfqq_must_alloc(bfqq); -+ return ELV_MQUEUE_MUST; -+ } -+ -+ return ELV_MQUEUE_MAY; -+} -+ -+static int bfq_may_queue(struct request_queue *q, int rw) -+{ -+ struct bfq_data *bfqd = q->elevator->elevator_data; -+ struct task_struct *tsk = current; -+ struct bfq_io_cq *bic; -+ struct bfq_queue *bfqq; -+ -+ /* -+ * Don't force setup of a queue from here, as a call to may_queue -+ * does not necessarily imply that a request actually will be -+ * queued. So just lookup a possibly existing queue, or return -+ * 'may queue' if that fails. -+ */ -+ bic = bfq_bic_lookup(bfqd, tsk->io_context); -+ if (bic == NULL) -+ return ELV_MQUEUE_MAY; -+ -+ bfqq = bic_to_bfqq(bic, rw_is_sync(rw)); -+ if (bfqq != NULL) { -+ bfq_init_prio_data(bfqq, bic); -+ -+ return __bfq_may_queue(bfqq); -+ } -+ -+ return ELV_MQUEUE_MAY; -+} -+ -+/* -+ * Queue lock held here. -+ */ -+static void bfq_put_request(struct request *rq) -+{ -+ struct bfq_queue *bfqq = RQ_BFQQ(rq); -+ -+ if (bfqq != NULL) { -+ const int rw = rq_data_dir(rq); -+ -+ BUG_ON(!bfqq->allocated[rw]); -+ bfqq->allocated[rw]--; -+ -+ rq->elv.priv[0] = NULL; -+ rq->elv.priv[1] = NULL; -+ -+ bfq_log_bfqq(bfqq->bfqd, bfqq, "put_request %p, %d", -+ bfqq, atomic_read(&bfqq->ref)); -+ bfq_put_queue(bfqq); -+ } -+} -+ -+static struct bfq_queue * -+bfq_merge_bfqqs(struct bfq_data *bfqd, struct bfq_io_cq *bic, -+ struct bfq_queue *bfqq) -+{ -+ bfq_log_bfqq(bfqd, bfqq, "merging with queue %lu", -+ (long unsigned)bfqq->new_bfqq->pid); -+ bic_set_bfqq(bic, bfqq->new_bfqq, 1); -+ bfq_mark_bfqq_coop(bfqq->new_bfqq); -+ bfq_put_queue(bfqq); -+ return bic_to_bfqq(bic, 1); -+} -+ -+/* -+ * Returns NULL if a new bfqq should be allocated, or the old bfqq if this -+ * was the last process referring to said bfqq. -+ */ -+static struct bfq_queue * -+bfq_split_bfqq(struct bfq_io_cq *bic, struct bfq_queue *bfqq) -+{ -+ bfq_log_bfqq(bfqq->bfqd, bfqq, "splitting queue"); -+ if (bfqq_process_refs(bfqq) == 1) { -+ bfqq->pid = current->pid; -+ bfq_clear_bfqq_coop(bfqq); -+ bfq_clear_bfqq_split_coop(bfqq); -+ return bfqq; -+ } -+ -+ bic_set_bfqq(bic, NULL, 1); -+ -+ bfq_put_cooperator(bfqq); -+ -+ bfq_put_queue(bfqq); -+ return NULL; -+} -+ -+/* -+ * Allocate bfq data structures associated with this request. -+ */ -+static int bfq_set_request(struct request_queue *q, struct request *rq, -+ struct bio *bio, gfp_t gfp_mask) -+{ -+ struct bfq_data *bfqd = q->elevator->elevator_data; -+ struct bfq_io_cq *bic = icq_to_bic(rq->elv.icq); -+ const int rw = rq_data_dir(rq); -+ const int is_sync = rq_is_sync(rq); -+ struct bfq_queue *bfqq; -+ struct bfq_group *bfqg; -+ unsigned long flags; -+ -+ might_sleep_if(gfp_mask & __GFP_WAIT); -+ -+ bfq_changed_ioprio(bic); -+ -+ spin_lock_irqsave(q->queue_lock, flags); -+ -+ if (bic == NULL) -+ goto queue_fail; -+ -+ bfqg = bfq_bic_update_cgroup(bic); -+ -+new_queue: -+ bfqq = bic_to_bfqq(bic, is_sync); -+ if (bfqq == NULL || bfqq == &bfqd->oom_bfqq) { -+ bfqq = bfq_get_queue(bfqd, bfqg, is_sync, bic, gfp_mask); -+ bic_set_bfqq(bic, bfqq, is_sync); -+ } else { -+ /* -+ * If the queue was seeky for too long, break it apart. -+ */ -+ if (bfq_bfqq_coop(bfqq) && bfq_bfqq_split_coop(bfqq)) { -+ bfq_log_bfqq(bfqd, bfqq, "breaking apart bfqq"); -+ bfqq = bfq_split_bfqq(bic, bfqq); -+ if (!bfqq) -+ goto new_queue; -+ } -+ -+ /* -+ * Check to see if this queue is scheduled to merge with -+ * another closely cooperating queue. The merging of queues -+ * happens here as it must be done in process context. -+ * The reference on new_bfqq was taken in merge_bfqqs. -+ */ -+ if (bfqq->new_bfqq != NULL) -+ bfqq = bfq_merge_bfqqs(bfqd, bic, bfqq); -+ } -+ -+ bfqq->allocated[rw]++; -+ atomic_inc(&bfqq->ref); -+ bfq_log_bfqq(bfqd, bfqq, "set_request: bfqq %p, %d", bfqq, -+ atomic_read(&bfqq->ref)); -+ -+ rq->elv.priv[0] = bic; -+ rq->elv.priv[1] = bfqq; -+ -+ spin_unlock_irqrestore(q->queue_lock, flags); -+ -+ return 0; -+ -+queue_fail: -+ bfq_schedule_dispatch(bfqd); -+ spin_unlock_irqrestore(q->queue_lock, flags); -+ -+ return 1; -+} -+ -+static void bfq_kick_queue(struct work_struct *work) -+{ -+ struct bfq_data *bfqd = -+ container_of(work, struct bfq_data, unplug_work); -+ struct request_queue *q = bfqd->queue; -+ -+ spin_lock_irq(q->queue_lock); -+ __blk_run_queue(q); -+ spin_unlock_irq(q->queue_lock); -+} -+ -+/* -+ * Handler of the expiration of the timer running if the in-service queue -+ * is idling inside its time slice. -+ */ -+static void bfq_idle_slice_timer(unsigned long data) -+{ -+ struct bfq_data *bfqd = (struct bfq_data *)data; -+ struct bfq_queue *bfqq; -+ unsigned long flags; -+ enum bfqq_expiration reason; -+ -+ spin_lock_irqsave(bfqd->queue->queue_lock, flags); -+ -+ bfqq = bfqd->in_service_queue; -+ /* -+ * Theoretical race here: the in-service queue can be NULL or -+ * different from the queue that was idling if the timer handler -+ * spins on the queue_lock and a new request arrives for the -+ * current queue and there is a full dispatch cycle that changes -+ * the in-service queue. This can hardly happen, but in the worst -+ * case we just expire a queue too early. -+ */ -+ if (bfqq != NULL) { -+ bfq_log_bfqq(bfqd, bfqq, "slice_timer expired"); -+ if (bfq_bfqq_budget_timeout(bfqq)) -+ /* -+ * Also here the queue can be safely expired -+ * for budget timeout without wasting -+ * guarantees -+ */ -+ reason = BFQ_BFQQ_BUDGET_TIMEOUT; -+ else if (bfqq->queued[0] == 0 && bfqq->queued[1] == 0) -+ /* -+ * The queue may not be empty upon timer expiration, -+ * because we may not disable the timer when the -+ * first request of the in-service queue arrives -+ * during disk idling. -+ */ -+ reason = BFQ_BFQQ_TOO_IDLE; -+ else -+ goto schedule_dispatch; -+ -+ bfq_bfqq_expire(bfqd, bfqq, 1, reason); -+ } -+ -+schedule_dispatch: -+ bfq_schedule_dispatch(bfqd); -+ -+ spin_unlock_irqrestore(bfqd->queue->queue_lock, flags); -+} -+ -+static void bfq_shutdown_timer_wq(struct bfq_data *bfqd) -+{ -+ del_timer_sync(&bfqd->idle_slice_timer); -+ cancel_work_sync(&bfqd->unplug_work); -+} -+ -+static inline void __bfq_put_async_bfqq(struct bfq_data *bfqd, -+ struct bfq_queue **bfqq_ptr) -+{ -+ struct bfq_group *root_group = bfqd->root_group; -+ struct bfq_queue *bfqq = *bfqq_ptr; -+ -+ bfq_log(bfqd, "put_async_bfqq: %p", bfqq); -+ if (bfqq != NULL) { -+ bfq_bfqq_move(bfqd, bfqq, &bfqq->entity, root_group); -+ bfq_log_bfqq(bfqd, bfqq, "put_async_bfqq: putting %p, %d", -+ bfqq, atomic_read(&bfqq->ref)); -+ bfq_put_queue(bfqq); -+ *bfqq_ptr = NULL; -+ } -+} -+ -+/* -+ * Release all the bfqg references to its async queues. If we are -+ * deallocating the group these queues may still contain requests, so -+ * we reparent them to the root cgroup (i.e., the only one that will -+ * exist for sure until all the requests on a device are gone). -+ */ -+static void bfq_put_async_queues(struct bfq_data *bfqd, struct bfq_group *bfqg) -+{ -+ int i, j; -+ -+ for (i = 0; i < 2; i++) -+ for (j = 0; j < IOPRIO_BE_NR; j++) -+ __bfq_put_async_bfqq(bfqd, &bfqg->async_bfqq[i][j]); -+ -+ __bfq_put_async_bfqq(bfqd, &bfqg->async_idle_bfqq); -+} -+ -+static void bfq_exit_queue(struct elevator_queue *e) -+{ -+ struct bfq_data *bfqd = e->elevator_data; -+ struct request_queue *q = bfqd->queue; -+ struct bfq_queue *bfqq, *n; -+ -+ bfq_shutdown_timer_wq(bfqd); -+ -+ spin_lock_irq(q->queue_lock); -+ -+ BUG_ON(bfqd->in_service_queue != NULL); -+ list_for_each_entry_safe(bfqq, n, &bfqd->idle_list, bfqq_list) -+ bfq_deactivate_bfqq(bfqd, bfqq, 0); -+ -+ bfq_disconnect_groups(bfqd); -+ spin_unlock_irq(q->queue_lock); -+ -+ bfq_shutdown_timer_wq(bfqd); -+ -+ synchronize_rcu(); -+ -+ BUG_ON(timer_pending(&bfqd->idle_slice_timer)); -+ -+ bfq_free_root_group(bfqd); -+ kfree(bfqd); -+} -+ -+static int bfq_init_queue(struct request_queue *q, struct elevator_type *e) -+{ -+ struct bfq_group *bfqg; -+ struct bfq_data *bfqd; -+ struct elevator_queue *eq; -+ -+ eq = elevator_alloc(q, e); -+ if (eq == NULL) -+ return -ENOMEM; -+ -+ bfqd = kzalloc_node(sizeof(*bfqd), GFP_KERNEL, q->node); -+ if (bfqd == NULL) { -+ kobject_put(&eq->kobj); -+ return -ENOMEM; -+ } -+ eq->elevator_data = bfqd; -+ -+ /* -+ * Our fallback bfqq if bfq_find_alloc_queue() runs into OOM issues. -+ * Grab a permanent reference to it, so that the normal code flow -+ * will not attempt to free it. -+ */ -+ bfq_init_bfqq(bfqd, &bfqd->oom_bfqq, 1, 0); -+ atomic_inc(&bfqd->oom_bfqq.ref); -+ bfqd->oom_bfqq.entity.new_ioprio = BFQ_DEFAULT_QUEUE_IOPRIO; -+ bfqd->oom_bfqq.entity.new_ioprio_class = IOPRIO_CLASS_BE; -+ /* -+ * Trigger weight initialization, according to ioprio, at the -+ * oom_bfqq's first activation. The oom_bfqq's ioprio and ioprio -+ * class won't be changed any more. -+ */ -+ bfqd->oom_bfqq.entity.ioprio_changed = 1; -+ -+ bfqd->queue = q; -+ -+ spin_lock_irq(q->queue_lock); -+ q->elevator = eq; -+ spin_unlock_irq(q->queue_lock); -+ -+ bfqg = bfq_alloc_root_group(bfqd, q->node); -+ if (bfqg == NULL) { -+ kfree(bfqd); -+ kobject_put(&eq->kobj); -+ return -ENOMEM; -+ } -+ -+ bfqd->root_group = bfqg; -+ bfq_init_entity(&bfqd->oom_bfqq.entity, bfqd->root_group); -+#ifdef CONFIG_CGROUP_BFQIO -+ bfqd->active_numerous_groups = 0; -+#endif -+ -+ init_timer(&bfqd->idle_slice_timer); -+ bfqd->idle_slice_timer.function = bfq_idle_slice_timer; -+ bfqd->idle_slice_timer.data = (unsigned long)bfqd; -+ -+ bfqd->rq_pos_tree = RB_ROOT; -+ bfqd->queue_weights_tree = RB_ROOT; -+ bfqd->group_weights_tree = RB_ROOT; -+ -+ INIT_WORK(&bfqd->unplug_work, bfq_kick_queue); -+ -+ INIT_LIST_HEAD(&bfqd->active_list); -+ INIT_LIST_HEAD(&bfqd->idle_list); -+ INIT_HLIST_HEAD(&bfqd->burst_list); -+ -+ bfqd->hw_tag = -1; -+ -+ bfqd->bfq_max_budget = bfq_default_max_budget; -+ -+ bfqd->bfq_quantum = bfq_quantum; -+ bfqd->bfq_fifo_expire[0] = bfq_fifo_expire[0]; -+ bfqd->bfq_fifo_expire[1] = bfq_fifo_expire[1]; -+ bfqd->bfq_back_max = bfq_back_max; -+ bfqd->bfq_back_penalty = bfq_back_penalty; -+ bfqd->bfq_slice_idle = bfq_slice_idle; -+ bfqd->bfq_class_idle_last_service = 0; -+ bfqd->bfq_max_budget_async_rq = bfq_max_budget_async_rq; -+ bfqd->bfq_timeout[BLK_RW_ASYNC] = bfq_timeout_async; -+ bfqd->bfq_timeout[BLK_RW_SYNC] = bfq_timeout_sync; -+ -+ bfqd->bfq_coop_thresh = 2; -+ bfqd->bfq_failed_cooperations = 7000; -+ bfqd->bfq_requests_within_timer = 120; -+ -+ bfqd->bfq_large_burst_thresh = 11; -+ bfqd->bfq_burst_interval = msecs_to_jiffies(500); -+ -+ bfqd->low_latency = true; -+ -+ bfqd->bfq_wr_coeff = 20; -+ bfqd->bfq_wr_rt_max_time = msecs_to_jiffies(300); -+ bfqd->bfq_wr_max_time = 0; -+ bfqd->bfq_wr_min_idle_time = msecs_to_jiffies(2000); -+ bfqd->bfq_wr_min_inter_arr_async = msecs_to_jiffies(500); -+ bfqd->bfq_wr_max_softrt_rate = 7000; /* -+ * Approximate rate required -+ * to playback or record a -+ * high-definition compressed -+ * video. -+ */ -+ bfqd->wr_busy_queues = 0; -+ bfqd->busy_in_flight_queues = 0; -+ bfqd->const_seeky_busy_in_flight_queues = 0; -+ -+ /* -+ * Begin by assuming, optimistically, that the device peak rate is -+ * equal to the highest reference rate. -+ */ -+ bfqd->RT_prod = R_fast[blk_queue_nonrot(bfqd->queue)] * -+ T_fast[blk_queue_nonrot(bfqd->queue)]; -+ bfqd->peak_rate = R_fast[blk_queue_nonrot(bfqd->queue)]; -+ bfqd->device_speed = BFQ_BFQD_FAST; -+ -+ return 0; -+} -+ -+static void bfq_slab_kill(void) -+{ -+ if (bfq_pool != NULL) -+ kmem_cache_destroy(bfq_pool); -+} -+ -+static int __init bfq_slab_setup(void) -+{ -+ bfq_pool = KMEM_CACHE(bfq_queue, 0); -+ if (bfq_pool == NULL) -+ return -ENOMEM; -+ return 0; -+} -+ -+static ssize_t bfq_var_show(unsigned int var, char *page) -+{ -+ return sprintf(page, "%d\n", var); -+} -+ -+static ssize_t bfq_var_store(unsigned long *var, const char *page, -+ size_t count) -+{ -+ unsigned long new_val; -+ int ret = kstrtoul(page, 10, &new_val); -+ -+ if (ret == 0) -+ *var = new_val; -+ -+ return count; -+} -+ -+static ssize_t bfq_wr_max_time_show(struct elevator_queue *e, char *page) -+{ -+ struct bfq_data *bfqd = e->elevator_data; -+ return sprintf(page, "%d\n", bfqd->bfq_wr_max_time > 0 ? -+ jiffies_to_msecs(bfqd->bfq_wr_max_time) : -+ jiffies_to_msecs(bfq_wr_duration(bfqd))); -+} -+ -+static ssize_t bfq_weights_show(struct elevator_queue *e, char *page) -+{ -+ struct bfq_queue *bfqq; -+ struct bfq_data *bfqd = e->elevator_data; -+ ssize_t num_char = 0; -+ -+ num_char += sprintf(page + num_char, "Tot reqs queued %d\n\n", -+ bfqd->queued); -+ -+ spin_lock_irq(bfqd->queue->queue_lock); -+ -+ num_char += sprintf(page + num_char, "Active:\n"); -+ list_for_each_entry(bfqq, &bfqd->active_list, bfqq_list) { -+ num_char += sprintf(page + num_char, -+ "pid%d: weight %hu, nr_queued %d %d, dur %d/%u\n", -+ bfqq->pid, -+ bfqq->entity.weight, -+ bfqq->queued[0], -+ bfqq->queued[1], -+ jiffies_to_msecs(jiffies - bfqq->last_wr_start_finish), -+ jiffies_to_msecs(bfqq->wr_cur_max_time)); -+ } -+ -+ num_char += sprintf(page + num_char, "Idle:\n"); -+ list_for_each_entry(bfqq, &bfqd->idle_list, bfqq_list) { -+ num_char += sprintf(page + num_char, -+ "pid%d: weight %hu, dur %d/%u\n", -+ bfqq->pid, -+ bfqq->entity.weight, -+ jiffies_to_msecs(jiffies - -+ bfqq->last_wr_start_finish), -+ jiffies_to_msecs(bfqq->wr_cur_max_time)); -+ } -+ -+ spin_unlock_irq(bfqd->queue->queue_lock); -+ -+ return num_char; -+} -+ -+#define SHOW_FUNCTION(__FUNC, __VAR, __CONV) \ -+static ssize_t __FUNC(struct elevator_queue *e, char *page) \ -+{ \ -+ struct bfq_data *bfqd = e->elevator_data; \ -+ unsigned int __data = __VAR; \ -+ if (__CONV) \ -+ __data = jiffies_to_msecs(__data); \ -+ return bfq_var_show(__data, (page)); \ -+} -+SHOW_FUNCTION(bfq_quantum_show, bfqd->bfq_quantum, 0); -+SHOW_FUNCTION(bfq_fifo_expire_sync_show, bfqd->bfq_fifo_expire[1], 1); -+SHOW_FUNCTION(bfq_fifo_expire_async_show, bfqd->bfq_fifo_expire[0], 1); -+SHOW_FUNCTION(bfq_back_seek_max_show, bfqd->bfq_back_max, 0); -+SHOW_FUNCTION(bfq_back_seek_penalty_show, bfqd->bfq_back_penalty, 0); -+SHOW_FUNCTION(bfq_slice_idle_show, bfqd->bfq_slice_idle, 1); -+SHOW_FUNCTION(bfq_max_budget_show, bfqd->bfq_user_max_budget, 0); -+SHOW_FUNCTION(bfq_max_budget_async_rq_show, -+ bfqd->bfq_max_budget_async_rq, 0); -+SHOW_FUNCTION(bfq_timeout_sync_show, bfqd->bfq_timeout[BLK_RW_SYNC], 1); -+SHOW_FUNCTION(bfq_timeout_async_show, bfqd->bfq_timeout[BLK_RW_ASYNC], 1); -+SHOW_FUNCTION(bfq_low_latency_show, bfqd->low_latency, 0); -+SHOW_FUNCTION(bfq_wr_coeff_show, bfqd->bfq_wr_coeff, 0); -+SHOW_FUNCTION(bfq_wr_rt_max_time_show, bfqd->bfq_wr_rt_max_time, 1); -+SHOW_FUNCTION(bfq_wr_min_idle_time_show, bfqd->bfq_wr_min_idle_time, 1); -+SHOW_FUNCTION(bfq_wr_min_inter_arr_async_show, bfqd->bfq_wr_min_inter_arr_async, -+ 1); -+SHOW_FUNCTION(bfq_wr_max_softrt_rate_show, bfqd->bfq_wr_max_softrt_rate, 0); -+#undef SHOW_FUNCTION -+ -+#define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV) \ -+static ssize_t \ -+__FUNC(struct elevator_queue *e, const char *page, size_t count) \ -+{ \ -+ struct bfq_data *bfqd = e->elevator_data; \ -+ unsigned long uninitialized_var(__data); \ -+ int ret = bfq_var_store(&__data, (page), count); \ -+ if (__data < (MIN)) \ -+ __data = (MIN); \ -+ else if (__data > (MAX)) \ -+ __data = (MAX); \ -+ if (__CONV) \ -+ *(__PTR) = msecs_to_jiffies(__data); \ -+ else \ -+ *(__PTR) = __data; \ -+ return ret; \ -+} -+STORE_FUNCTION(bfq_quantum_store, &bfqd->bfq_quantum, 1, INT_MAX, 0); -+STORE_FUNCTION(bfq_fifo_expire_sync_store, &bfqd->bfq_fifo_expire[1], 1, -+ INT_MAX, 1); -+STORE_FUNCTION(bfq_fifo_expire_async_store, &bfqd->bfq_fifo_expire[0], 1, -+ INT_MAX, 1); -+STORE_FUNCTION(bfq_back_seek_max_store, &bfqd->bfq_back_max, 0, INT_MAX, 0); -+STORE_FUNCTION(bfq_back_seek_penalty_store, &bfqd->bfq_back_penalty, 1, -+ INT_MAX, 0); -+STORE_FUNCTION(bfq_slice_idle_store, &bfqd->bfq_slice_idle, 0, INT_MAX, 1); -+STORE_FUNCTION(bfq_max_budget_async_rq_store, &bfqd->bfq_max_budget_async_rq, -+ 1, INT_MAX, 0); -+STORE_FUNCTION(bfq_timeout_async_store, &bfqd->bfq_timeout[BLK_RW_ASYNC], 0, -+ INT_MAX, 1); -+STORE_FUNCTION(bfq_wr_coeff_store, &bfqd->bfq_wr_coeff, 1, INT_MAX, 0); -+STORE_FUNCTION(bfq_wr_max_time_store, &bfqd->bfq_wr_max_time, 0, INT_MAX, 1); -+STORE_FUNCTION(bfq_wr_rt_max_time_store, &bfqd->bfq_wr_rt_max_time, 0, INT_MAX, -+ 1); -+STORE_FUNCTION(bfq_wr_min_idle_time_store, &bfqd->bfq_wr_min_idle_time, 0, -+ INT_MAX, 1); -+STORE_FUNCTION(bfq_wr_min_inter_arr_async_store, -+ &bfqd->bfq_wr_min_inter_arr_async, 0, INT_MAX, 1); -+STORE_FUNCTION(bfq_wr_max_softrt_rate_store, &bfqd->bfq_wr_max_softrt_rate, 0, -+ INT_MAX, 0); -+#undef STORE_FUNCTION -+ -+/* do nothing for the moment */ -+static ssize_t bfq_weights_store(struct elevator_queue *e, -+ const char *page, size_t count) -+{ -+ return count; -+} -+ -+static inline unsigned long bfq_estimated_max_budget(struct bfq_data *bfqd) -+{ -+ u64 timeout = jiffies_to_msecs(bfqd->bfq_timeout[BLK_RW_SYNC]); -+ -+ if (bfqd->peak_rate_samples >= BFQ_PEAK_RATE_SAMPLES) -+ return bfq_calc_max_budget(bfqd->peak_rate, timeout); -+ else -+ return bfq_default_max_budget; -+} -+ -+static ssize_t bfq_max_budget_store(struct elevator_queue *e, -+ const char *page, size_t count) -+{ -+ struct bfq_data *bfqd = e->elevator_data; -+ unsigned long uninitialized_var(__data); -+ int ret = bfq_var_store(&__data, (page), count); -+ -+ if (__data == 0) -+ bfqd->bfq_max_budget = bfq_estimated_max_budget(bfqd); -+ else { -+ if (__data > INT_MAX) -+ __data = INT_MAX; -+ bfqd->bfq_max_budget = __data; -+ } -+ -+ bfqd->bfq_user_max_budget = __data; -+ -+ return ret; -+} -+ -+static ssize_t bfq_timeout_sync_store(struct elevator_queue *e, -+ const char *page, size_t count) -+{ -+ struct bfq_data *bfqd = e->elevator_data; -+ unsigned long uninitialized_var(__data); -+ int ret = bfq_var_store(&__data, (page), count); -+ -+ if (__data < 1) -+ __data = 1; -+ else if (__data > INT_MAX) -+ __data = INT_MAX; -+ -+ bfqd->bfq_timeout[BLK_RW_SYNC] = msecs_to_jiffies(__data); -+ if (bfqd->bfq_user_max_budget == 0) -+ bfqd->bfq_max_budget = bfq_estimated_max_budget(bfqd); -+ -+ return ret; -+} -+ -+static ssize_t bfq_low_latency_store(struct elevator_queue *e, -+ const char *page, size_t count) -+{ -+ struct bfq_data *bfqd = e->elevator_data; -+ unsigned long uninitialized_var(__data); -+ int ret = bfq_var_store(&__data, (page), count); -+ -+ if (__data > 1) -+ __data = 1; -+ if (__data == 0 && bfqd->low_latency != 0) -+ bfq_end_wr(bfqd); -+ bfqd->low_latency = __data; -+ -+ return ret; -+} -+ -+#define BFQ_ATTR(name) \ -+ __ATTR(name, S_IRUGO|S_IWUSR, bfq_##name##_show, bfq_##name##_store) -+ -+static struct elv_fs_entry bfq_attrs[] = { -+ BFQ_ATTR(quantum), -+ BFQ_ATTR(fifo_expire_sync), -+ BFQ_ATTR(fifo_expire_async), -+ BFQ_ATTR(back_seek_max), -+ BFQ_ATTR(back_seek_penalty), -+ BFQ_ATTR(slice_idle), -+ BFQ_ATTR(max_budget), -+ BFQ_ATTR(max_budget_async_rq), -+ BFQ_ATTR(timeout_sync), -+ BFQ_ATTR(timeout_async), -+ BFQ_ATTR(low_latency), -+ BFQ_ATTR(wr_coeff), -+ BFQ_ATTR(wr_max_time), -+ BFQ_ATTR(wr_rt_max_time), -+ BFQ_ATTR(wr_min_idle_time), -+ BFQ_ATTR(wr_min_inter_arr_async), -+ BFQ_ATTR(wr_max_softrt_rate), -+ BFQ_ATTR(weights), -+ __ATTR_NULL -+}; -+ -+static struct elevator_type iosched_bfq = { -+ .ops = { -+ .elevator_merge_fn = bfq_merge, -+ .elevator_merged_fn = bfq_merged_request, -+ .elevator_merge_req_fn = bfq_merged_requests, -+ .elevator_allow_merge_fn = bfq_allow_merge, -+ .elevator_dispatch_fn = bfq_dispatch_requests, -+ .elevator_add_req_fn = bfq_insert_request, -+ .elevator_activate_req_fn = bfq_activate_request, -+ .elevator_deactivate_req_fn = bfq_deactivate_request, -+ .elevator_completed_req_fn = bfq_completed_request, -+ .elevator_former_req_fn = elv_rb_former_request, -+ .elevator_latter_req_fn = elv_rb_latter_request, -+ .elevator_init_icq_fn = bfq_init_icq, -+ .elevator_exit_icq_fn = bfq_exit_icq, -+ .elevator_set_req_fn = bfq_set_request, -+ .elevator_put_req_fn = bfq_put_request, -+ .elevator_may_queue_fn = bfq_may_queue, -+ .elevator_init_fn = bfq_init_queue, -+ .elevator_exit_fn = bfq_exit_queue, -+ }, -+ .icq_size = sizeof(struct bfq_io_cq), -+ .icq_align = __alignof__(struct bfq_io_cq), -+ .elevator_attrs = bfq_attrs, -+ .elevator_name = "bfq", -+ .elevator_owner = THIS_MODULE, -+}; -+ -+static int __init bfq_init(void) -+{ -+ /* -+ * Can be 0 on HZ < 1000 setups. -+ */ -+ if (bfq_slice_idle == 0) -+ bfq_slice_idle = 1; -+ -+ if (bfq_timeout_async == 0) -+ bfq_timeout_async = 1; -+ -+ if (bfq_slab_setup()) -+ return -ENOMEM; -+ -+ /* -+ * Times to load large popular applications for the typical systems -+ * installed on the reference devices (see the comments before the -+ * definitions of the two arrays). -+ */ -+ T_slow[0] = msecs_to_jiffies(2600); -+ T_slow[1] = msecs_to_jiffies(1000); -+ T_fast[0] = msecs_to_jiffies(5500); -+ T_fast[1] = msecs_to_jiffies(2000); -+ -+ /* -+ * Thresholds that determine the switch between speed classes (see -+ * the comments before the definition of the array). -+ */ -+ device_speed_thresh[0] = (R_fast[0] + R_slow[0]) / 2; -+ device_speed_thresh[1] = (R_fast[1] + R_slow[1]) / 2; -+ -+ elv_register(&iosched_bfq); -+ pr_info("BFQ I/O-scheduler version: v7r7"); -+ -+ return 0; -+} -+ -+static void __exit bfq_exit(void) -+{ -+ elv_unregister(&iosched_bfq); -+ bfq_slab_kill(); -+} -+ -+module_init(bfq_init); -+module_exit(bfq_exit); -+ -+MODULE_AUTHOR("Fabio Checconi, Paolo Valente"); -+MODULE_LICENSE("GPL"); -diff --git a/block/bfq-sched.c b/block/bfq-sched.c -new file mode 100644 -index 0000000..2931563 ---- /dev/null -+++ b/block/bfq-sched.c -@@ -0,0 +1,1214 @@ -+/* -+ * BFQ: Hierarchical B-WF2Q+ scheduler. -+ * -+ * Based on ideas and code from CFQ: -+ * Copyright (C) 2003 Jens Axboe -+ * -+ * Copyright (C) 2008 Fabio Checconi -+ * Paolo Valente -+ * -+ * Copyright (C) 2010 Paolo Valente -+ */ -+ -+#ifdef CONFIG_CGROUP_BFQIO -+#define for_each_entity(entity) \ -+ for (; entity != NULL; entity = entity->parent) -+ -+#define for_each_entity_safe(entity, parent) \ -+ for (; entity && ({ parent = entity->parent; 1; }); entity = parent) -+ -+static struct bfq_entity *bfq_lookup_next_entity(struct bfq_sched_data *sd, -+ int extract, -+ struct bfq_data *bfqd); -+ -+static inline void bfq_update_budget(struct bfq_entity *next_in_service) -+{ -+ struct bfq_entity *bfqg_entity; -+ struct bfq_group *bfqg; -+ struct bfq_sched_data *group_sd; -+ -+ BUG_ON(next_in_service == NULL); -+ -+ group_sd = next_in_service->sched_data; -+ -+ bfqg = container_of(group_sd, struct bfq_group, sched_data); -+ /* -+ * bfq_group's my_entity field is not NULL only if the group -+ * is not the root group. We must not touch the root entity -+ * as it must never become an in-service entity. -+ */ -+ bfqg_entity = bfqg->my_entity; -+ if (bfqg_entity != NULL) -+ bfqg_entity->budget = next_in_service->budget; -+} -+ -+static int bfq_update_next_in_service(struct bfq_sched_data *sd) -+{ -+ struct bfq_entity *next_in_service; -+ -+ if (sd->in_service_entity != NULL) -+ /* will update/requeue at the end of service */ -+ return 0; -+ -+ /* -+ * NOTE: this can be improved in many ways, such as returning -+ * 1 (and thus propagating upwards the update) only when the -+ * budget changes, or caching the bfqq that will be scheduled -+ * next from this subtree. By now we worry more about -+ * correctness than about performance... -+ */ -+ next_in_service = bfq_lookup_next_entity(sd, 0, NULL); -+ sd->next_in_service = next_in_service; -+ -+ if (next_in_service != NULL) -+ bfq_update_budget(next_in_service); -+ -+ return 1; -+} -+ -+static inline void bfq_check_next_in_service(struct bfq_sched_data *sd, -+ struct bfq_entity *entity) -+{ -+ BUG_ON(sd->next_in_service != entity); -+} -+#else -+#define for_each_entity(entity) \ -+ for (; entity != NULL; entity = NULL) -+ -+#define for_each_entity_safe(entity, parent) \ -+ for (parent = NULL; entity != NULL; entity = parent) -+ -+static inline int bfq_update_next_in_service(struct bfq_sched_data *sd) -+{ -+ return 0; -+} -+ -+static inline void bfq_check_next_in_service(struct bfq_sched_data *sd, -+ struct bfq_entity *entity) -+{ -+} -+ -+static inline void bfq_update_budget(struct bfq_entity *next_in_service) -+{ -+} -+#endif -+ -+/* -+ * Shift for timestamp calculations. This actually limits the maximum -+ * service allowed in one timestamp delta (small shift values increase it), -+ * the maximum total weight that can be used for the queues in the system -+ * (big shift values increase it), and the period of virtual time -+ * wraparounds. -+ */ -+#define WFQ_SERVICE_SHIFT 22 -+ -+/** -+ * bfq_gt - compare two timestamps. -+ * @a: first ts. -+ * @b: second ts. -+ * -+ * Return @a > @b, dealing with wrapping correctly. -+ */ -+static inline int bfq_gt(u64 a, u64 b) -+{ -+ return (s64)(a - b) > 0; -+} -+ -+static inline struct bfq_queue *bfq_entity_to_bfqq(struct bfq_entity *entity) -+{ -+ struct bfq_queue *bfqq = NULL; -+ -+ BUG_ON(entity == NULL); -+ -+ if (entity->my_sched_data == NULL) -+ bfqq = container_of(entity, struct bfq_queue, entity); -+ -+ return bfqq; -+} -+ -+ -+/** -+ * bfq_delta - map service into the virtual time domain. -+ * @service: amount of service. -+ * @weight: scale factor (weight of an entity or weight sum). -+ */ -+static inline u64 bfq_delta(unsigned long service, -+ unsigned long weight) -+{ -+ u64 d = (u64)service << WFQ_SERVICE_SHIFT; -+ -+ do_div(d, weight); -+ return d; -+} -+ -+/** -+ * bfq_calc_finish - assign the finish time to an entity. -+ * @entity: the entity to act upon. -+ * @service: the service to be charged to the entity. -+ */ -+static inline void bfq_calc_finish(struct bfq_entity *entity, -+ unsigned long service) -+{ -+ struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); -+ -+ BUG_ON(entity->weight == 0); -+ -+ entity->finish = entity->start + -+ bfq_delta(service, entity->weight); -+ -+ if (bfqq != NULL) { -+ bfq_log_bfqq(bfqq->bfqd, bfqq, -+ "calc_finish: serv %lu, w %d", -+ service, entity->weight); -+ bfq_log_bfqq(bfqq->bfqd, bfqq, -+ "calc_finish: start %llu, finish %llu, delta %llu", -+ entity->start, entity->finish, -+ bfq_delta(service, entity->weight)); -+ } -+} -+ -+/** -+ * bfq_entity_of - get an entity from a node. -+ * @node: the node field of the entity. -+ * -+ * Convert a node pointer to the relative entity. This is used only -+ * to simplify the logic of some functions and not as the generic -+ * conversion mechanism because, e.g., in the tree walking functions, -+ * the check for a %NULL value would be redundant. -+ */ -+static inline struct bfq_entity *bfq_entity_of(struct rb_node *node) -+{ -+ struct bfq_entity *entity = NULL; -+ -+ if (node != NULL) -+ entity = rb_entry(node, struct bfq_entity, rb_node); -+ -+ return entity; -+} -+ -+/** -+ * bfq_extract - remove an entity from a tree. -+ * @root: the tree root. -+ * @entity: the entity to remove. -+ */ -+static inline void bfq_extract(struct rb_root *root, -+ struct bfq_entity *entity) -+{ -+ BUG_ON(entity->tree != root); -+ -+ entity->tree = NULL; -+ rb_erase(&entity->rb_node, root); -+} -+ -+/** -+ * bfq_idle_extract - extract an entity from the idle tree. -+ * @st: the service tree of the owning @entity. -+ * @entity: the entity being removed. -+ */ -+static void bfq_idle_extract(struct bfq_service_tree *st, -+ struct bfq_entity *entity) -+{ -+ struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); -+ struct rb_node *next; -+ -+ BUG_ON(entity->tree != &st->idle); -+ -+ if (entity == st->first_idle) { -+ next = rb_next(&entity->rb_node); -+ st->first_idle = bfq_entity_of(next); -+ } -+ -+ if (entity == st->last_idle) { -+ next = rb_prev(&entity->rb_node); -+ st->last_idle = bfq_entity_of(next); -+ } -+ -+ bfq_extract(&st->idle, entity); -+ -+ if (bfqq != NULL) -+ list_del(&bfqq->bfqq_list); -+} -+ -+/** -+ * bfq_insert - generic tree insertion. -+ * @root: tree root. -+ * @entity: entity to insert. -+ * -+ * This is used for the idle and the active tree, since they are both -+ * ordered by finish time. -+ */ -+static void bfq_insert(struct rb_root *root, struct bfq_entity *entity) -+{ -+ struct bfq_entity *entry; -+ struct rb_node **node = &root->rb_node; -+ struct rb_node *parent = NULL; -+ -+ BUG_ON(entity->tree != NULL); -+ -+ while (*node != NULL) { -+ parent = *node; -+ entry = rb_entry(parent, struct bfq_entity, rb_node); -+ -+ if (bfq_gt(entry->finish, entity->finish)) -+ node = &parent->rb_left; -+ else -+ node = &parent->rb_right; -+ } -+ -+ rb_link_node(&entity->rb_node, parent, node); -+ rb_insert_color(&entity->rb_node, root); -+ -+ entity->tree = root; -+} -+ -+/** -+ * bfq_update_min - update the min_start field of a entity. -+ * @entity: the entity to update. -+ * @node: one of its children. -+ * -+ * This function is called when @entity may store an invalid value for -+ * min_start due to updates to the active tree. The function assumes -+ * that the subtree rooted at @node (which may be its left or its right -+ * child) has a valid min_start value. -+ */ -+static inline void bfq_update_min(struct bfq_entity *entity, -+ struct rb_node *node) -+{ -+ struct bfq_entity *child; -+ -+ if (node != NULL) { -+ child = rb_entry(node, struct bfq_entity, rb_node); -+ if (bfq_gt(entity->min_start, child->min_start)) -+ entity->min_start = child->min_start; -+ } -+} -+ -+/** -+ * bfq_update_active_node - recalculate min_start. -+ * @node: the node to update. -+ * -+ * @node may have changed position or one of its children may have moved, -+ * this function updates its min_start value. The left and right subtrees -+ * are assumed to hold a correct min_start value. -+ */ -+static inline void bfq_update_active_node(struct rb_node *node) -+{ -+ struct bfq_entity *entity = rb_entry(node, struct bfq_entity, rb_node); -+ -+ entity->min_start = entity->start; -+ bfq_update_min(entity, node->rb_right); -+ bfq_update_min(entity, node->rb_left); -+} -+ -+/** -+ * bfq_update_active_tree - update min_start for the whole active tree. -+ * @node: the starting node. -+ * -+ * @node must be the deepest modified node after an update. This function -+ * updates its min_start using the values held by its children, assuming -+ * that they did not change, and then updates all the nodes that may have -+ * changed in the path to the root. The only nodes that may have changed -+ * are the ones in the path or their siblings. -+ */ -+static void bfq_update_active_tree(struct rb_node *node) -+{ -+ struct rb_node *parent; -+ -+up: -+ bfq_update_active_node(node); -+ -+ parent = rb_parent(node); -+ if (parent == NULL) -+ return; -+ -+ if (node == parent->rb_left && parent->rb_right != NULL) -+ bfq_update_active_node(parent->rb_right); -+ else if (parent->rb_left != NULL) -+ bfq_update_active_node(parent->rb_left); -+ -+ node = parent; -+ goto up; -+} -+ -+static void bfq_weights_tree_add(struct bfq_data *bfqd, -+ struct bfq_entity *entity, -+ struct rb_root *root); -+ -+static void bfq_weights_tree_remove(struct bfq_data *bfqd, -+ struct bfq_entity *entity, -+ struct rb_root *root); -+ -+ -+/** -+ * bfq_active_insert - insert an entity in the active tree of its -+ * group/device. -+ * @st: the service tree of the entity. -+ * @entity: the entity being inserted. -+ * -+ * The active tree is ordered by finish time, but an extra key is kept -+ * per each node, containing the minimum value for the start times of -+ * its children (and the node itself), so it's possible to search for -+ * the eligible node with the lowest finish time in logarithmic time. -+ */ -+static void bfq_active_insert(struct bfq_service_tree *st, -+ struct bfq_entity *entity) -+{ -+ struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); -+ struct rb_node *node = &entity->rb_node; -+#ifdef CONFIG_CGROUP_BFQIO -+ struct bfq_sched_data *sd = NULL; -+ struct bfq_group *bfqg = NULL; -+ struct bfq_data *bfqd = NULL; -+#endif -+ -+ bfq_insert(&st->active, entity); -+ -+ if (node->rb_left != NULL) -+ node = node->rb_left; -+ else if (node->rb_right != NULL) -+ node = node->rb_right; -+ -+ bfq_update_active_tree(node); -+ -+#ifdef CONFIG_CGROUP_BFQIO -+ sd = entity->sched_data; -+ bfqg = container_of(sd, struct bfq_group, sched_data); -+ BUG_ON(!bfqg); -+ bfqd = (struct bfq_data *)bfqg->bfqd; -+#endif -+ if (bfqq != NULL) -+ list_add(&bfqq->bfqq_list, &bfqq->bfqd->active_list); -+#ifdef CONFIG_CGROUP_BFQIO -+ else { /* bfq_group */ -+ BUG_ON(!bfqd); -+ bfq_weights_tree_add(bfqd, entity, &bfqd->group_weights_tree); -+ } -+ if (bfqg != bfqd->root_group) { -+ BUG_ON(!bfqg); -+ BUG_ON(!bfqd); -+ bfqg->active_entities++; -+ if (bfqg->active_entities == 2) -+ bfqd->active_numerous_groups++; -+ } -+#endif -+} -+ -+/** -+ * bfq_ioprio_to_weight - calc a weight from an ioprio. -+ * @ioprio: the ioprio value to convert. -+ */ -+static inline unsigned short bfq_ioprio_to_weight(int ioprio) -+{ -+ BUG_ON(ioprio < 0 || ioprio >= IOPRIO_BE_NR); -+ return IOPRIO_BE_NR - ioprio; -+} -+ -+/** -+ * bfq_weight_to_ioprio - calc an ioprio from a weight. -+ * @weight: the weight value to convert. -+ * -+ * To preserve as mush as possible the old only-ioprio user interface, -+ * 0 is used as an escape ioprio value for weights (numerically) equal or -+ * larger than IOPRIO_BE_NR -+ */ -+static inline unsigned short bfq_weight_to_ioprio(int weight) -+{ -+ BUG_ON(weight < BFQ_MIN_WEIGHT || weight > BFQ_MAX_WEIGHT); -+ return IOPRIO_BE_NR - weight < 0 ? 0 : IOPRIO_BE_NR - weight; -+} -+ -+static inline void bfq_get_entity(struct bfq_entity *entity) -+{ -+ struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); -+ -+ if (bfqq != NULL) { -+ atomic_inc(&bfqq->ref); -+ bfq_log_bfqq(bfqq->bfqd, bfqq, "get_entity: %p %d", -+ bfqq, atomic_read(&bfqq->ref)); -+ } -+} -+ -+/** -+ * bfq_find_deepest - find the deepest node that an extraction can modify. -+ * @node: the node being removed. -+ * -+ * Do the first step of an extraction in an rb tree, looking for the -+ * node that will replace @node, and returning the deepest node that -+ * the following modifications to the tree can touch. If @node is the -+ * last node in the tree return %NULL. -+ */ -+static struct rb_node *bfq_find_deepest(struct rb_node *node) -+{ -+ struct rb_node *deepest; -+ -+ if (node->rb_right == NULL && node->rb_left == NULL) -+ deepest = rb_parent(node); -+ else if (node->rb_right == NULL) -+ deepest = node->rb_left; -+ else if (node->rb_left == NULL) -+ deepest = node->rb_right; -+ else { -+ deepest = rb_next(node); -+ if (deepest->rb_right != NULL) -+ deepest = deepest->rb_right; -+ else if (rb_parent(deepest) != node) -+ deepest = rb_parent(deepest); -+ } -+ -+ return deepest; -+} -+ -+/** -+ * bfq_active_extract - remove an entity from the active tree. -+ * @st: the service_tree containing the tree. -+ * @entity: the entity being removed. -+ */ -+static void bfq_active_extract(struct bfq_service_tree *st, -+ struct bfq_entity *entity) -+{ -+ struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); -+ struct rb_node *node; -+#ifdef CONFIG_CGROUP_BFQIO -+ struct bfq_sched_data *sd = NULL; -+ struct bfq_group *bfqg = NULL; -+ struct bfq_data *bfqd = NULL; -+#endif -+ -+ node = bfq_find_deepest(&entity->rb_node); -+ bfq_extract(&st->active, entity); -+ -+ if (node != NULL) -+ bfq_update_active_tree(node); -+ -+#ifdef CONFIG_CGROUP_BFQIO -+ sd = entity->sched_data; -+ bfqg = container_of(sd, struct bfq_group, sched_data); -+ BUG_ON(!bfqg); -+ bfqd = (struct bfq_data *)bfqg->bfqd; -+#endif -+ if (bfqq != NULL) -+ list_del(&bfqq->bfqq_list); -+#ifdef CONFIG_CGROUP_BFQIO -+ else { /* bfq_group */ -+ BUG_ON(!bfqd); -+ bfq_weights_tree_remove(bfqd, entity, -+ &bfqd->group_weights_tree); -+ } -+ if (bfqg != bfqd->root_group) { -+ BUG_ON(!bfqg); -+ BUG_ON(!bfqd); -+ BUG_ON(!bfqg->active_entities); -+ bfqg->active_entities--; -+ if (bfqg->active_entities == 1) { -+ BUG_ON(!bfqd->active_numerous_groups); -+ bfqd->active_numerous_groups--; -+ } -+ } -+#endif -+} -+ -+/** -+ * bfq_idle_insert - insert an entity into the idle tree. -+ * @st: the service tree containing the tree. -+ * @entity: the entity to insert. -+ */ -+static void bfq_idle_insert(struct bfq_service_tree *st, -+ struct bfq_entity *entity) -+{ -+ struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); -+ struct bfq_entity *first_idle = st->first_idle; -+ struct bfq_entity *last_idle = st->last_idle; -+ -+ if (first_idle == NULL || bfq_gt(first_idle->finish, entity->finish)) -+ st->first_idle = entity; -+ if (last_idle == NULL || bfq_gt(entity->finish, last_idle->finish)) -+ st->last_idle = entity; -+ -+ bfq_insert(&st->idle, entity); -+ -+ if (bfqq != NULL) -+ list_add(&bfqq->bfqq_list, &bfqq->bfqd->idle_list); -+} -+ -+/** -+ * bfq_forget_entity - remove an entity from the wfq trees. -+ * @st: the service tree. -+ * @entity: the entity being removed. -+ * -+ * Update the device status and forget everything about @entity, putting -+ * the device reference to it, if it is a queue. Entities belonging to -+ * groups are not refcounted. -+ */ -+static void bfq_forget_entity(struct bfq_service_tree *st, -+ struct bfq_entity *entity) -+{ -+ struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); -+ struct bfq_sched_data *sd; -+ -+ BUG_ON(!entity->on_st); -+ -+ entity->on_st = 0; -+ st->wsum -= entity->weight; -+ if (bfqq != NULL) { -+ sd = entity->sched_data; -+ bfq_log_bfqq(bfqq->bfqd, bfqq, "forget_entity: %p %d", -+ bfqq, atomic_read(&bfqq->ref)); -+ bfq_put_queue(bfqq); -+ } -+} -+ -+/** -+ * bfq_put_idle_entity - release the idle tree ref of an entity. -+ * @st: service tree for the entity. -+ * @entity: the entity being released. -+ */ -+static void bfq_put_idle_entity(struct bfq_service_tree *st, -+ struct bfq_entity *entity) -+{ -+ bfq_idle_extract(st, entity); -+ bfq_forget_entity(st, entity); -+} -+ -+/** -+ * bfq_forget_idle - update the idle tree if necessary. -+ * @st: the service tree to act upon. -+ * -+ * To preserve the global O(log N) complexity we only remove one entry here; -+ * as the idle tree will not grow indefinitely this can be done safely. -+ */ -+static void bfq_forget_idle(struct bfq_service_tree *st) -+{ -+ struct bfq_entity *first_idle = st->first_idle; -+ struct bfq_entity *last_idle = st->last_idle; -+ -+ if (RB_EMPTY_ROOT(&st->active) && last_idle != NULL && -+ !bfq_gt(last_idle->finish, st->vtime)) { -+ /* -+ * Forget the whole idle tree, increasing the vtime past -+ * the last finish time of idle entities. -+ */ -+ st->vtime = last_idle->finish; -+ } -+ -+ if (first_idle != NULL && !bfq_gt(first_idle->finish, st->vtime)) -+ bfq_put_idle_entity(st, first_idle); -+} -+ -+static struct bfq_service_tree * -+__bfq_entity_update_weight_prio(struct bfq_service_tree *old_st, -+ struct bfq_entity *entity) -+{ -+ struct bfq_service_tree *new_st = old_st; -+ -+ if (entity->ioprio_changed) { -+ struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); -+ unsigned short prev_weight, new_weight; -+ struct bfq_data *bfqd = NULL; -+ struct rb_root *root; -+#ifdef CONFIG_CGROUP_BFQIO -+ struct bfq_sched_data *sd; -+ struct bfq_group *bfqg; -+#endif -+ -+ if (bfqq != NULL) -+ bfqd = bfqq->bfqd; -+#ifdef CONFIG_CGROUP_BFQIO -+ else { -+ sd = entity->my_sched_data; -+ bfqg = container_of(sd, struct bfq_group, sched_data); -+ BUG_ON(!bfqg); -+ bfqd = (struct bfq_data *)bfqg->bfqd; -+ BUG_ON(!bfqd); -+ } -+#endif -+ -+ BUG_ON(old_st->wsum < entity->weight); -+ old_st->wsum -= entity->weight; -+ -+ if (entity->new_weight != entity->orig_weight) { -+ if (entity->new_weight < BFQ_MIN_WEIGHT || -+ entity->new_weight > BFQ_MAX_WEIGHT) { -+ printk(KERN_CRIT "update_weight_prio: " -+ "new_weight %d\n", -+ entity->new_weight); -+ BUG(); -+ } -+ entity->orig_weight = entity->new_weight; -+ entity->ioprio = -+ bfq_weight_to_ioprio(entity->orig_weight); -+ } else if (entity->new_ioprio != entity->ioprio) { -+ entity->ioprio = entity->new_ioprio; -+ entity->orig_weight = -+ bfq_ioprio_to_weight(entity->ioprio); -+ } else -+ entity->new_weight = entity->orig_weight = -+ bfq_ioprio_to_weight(entity->ioprio); -+ -+ entity->ioprio_class = entity->new_ioprio_class; -+ entity->ioprio_changed = 0; -+ -+ /* -+ * NOTE: here we may be changing the weight too early, -+ * this will cause unfairness. The correct approach -+ * would have required additional complexity to defer -+ * weight changes to the proper time instants (i.e., -+ * when entity->finish <= old_st->vtime). -+ */ -+ new_st = bfq_entity_service_tree(entity); -+ -+ prev_weight = entity->weight; -+ new_weight = entity->orig_weight * -+ (bfqq != NULL ? bfqq->wr_coeff : 1); -+ /* -+ * If the weight of the entity changes, remove the entity -+ * from its old weight counter (if there is a counter -+ * associated with the entity), and add it to the counter -+ * associated with its new weight. -+ */ -+ if (prev_weight != new_weight) { -+ root = bfqq ? &bfqd->queue_weights_tree : -+ &bfqd->group_weights_tree; -+ bfq_weights_tree_remove(bfqd, entity, root); -+ } -+ entity->weight = new_weight; -+ /* -+ * Add the entity to its weights tree only if it is -+ * not associated with a weight-raised queue. -+ */ -+ if (prev_weight != new_weight && -+ (bfqq ? bfqq->wr_coeff == 1 : 1)) -+ /* If we get here, root has been initialized. */ -+ bfq_weights_tree_add(bfqd, entity, root); -+ -+ new_st->wsum += entity->weight; -+ -+ if (new_st != old_st) -+ entity->start = new_st->vtime; -+ } -+ -+ return new_st; -+} -+ -+/** -+ * bfq_bfqq_served - update the scheduler status after selection for -+ * service. -+ * @bfqq: the queue being served. -+ * @served: bytes to transfer. -+ * -+ * NOTE: this can be optimized, as the timestamps of upper level entities -+ * are synchronized every time a new bfqq is selected for service. By now, -+ * we keep it to better check consistency. -+ */ -+static void bfq_bfqq_served(struct bfq_queue *bfqq, unsigned long served) -+{ -+ struct bfq_entity *entity = &bfqq->entity; -+ struct bfq_service_tree *st; -+ -+ for_each_entity(entity) { -+ st = bfq_entity_service_tree(entity); -+ -+ entity->service += served; -+ BUG_ON(entity->service > entity->budget); -+ BUG_ON(st->wsum == 0); -+ -+ st->vtime += bfq_delta(served, st->wsum); -+ bfq_forget_idle(st); -+ } -+ bfq_log_bfqq(bfqq->bfqd, bfqq, "bfqq_served %lu secs", served); -+} -+ -+/** -+ * bfq_bfqq_charge_full_budget - set the service to the entity budget. -+ * @bfqq: the queue that needs a service update. -+ * -+ * When it's not possible to be fair in the service domain, because -+ * a queue is not consuming its budget fast enough (the meaning of -+ * fast depends on the timeout parameter), we charge it a full -+ * budget. In this way we should obtain a sort of time-domain -+ * fairness among all the seeky/slow queues. -+ */ -+static inline void bfq_bfqq_charge_full_budget(struct bfq_queue *bfqq) -+{ -+ struct bfq_entity *entity = &bfqq->entity; -+ -+ bfq_log_bfqq(bfqq->bfqd, bfqq, "charge_full_budget"); -+ -+ bfq_bfqq_served(bfqq, entity->budget - entity->service); -+} -+ -+/** -+ * __bfq_activate_entity - activate an entity. -+ * @entity: the entity being activated. -+ * -+ * Called whenever an entity is activated, i.e., it is not active and one -+ * of its children receives a new request, or has to be reactivated due to -+ * budget exhaustion. It uses the current budget of the entity (and the -+ * service received if @entity is active) of the queue to calculate its -+ * timestamps. -+ */ -+static void __bfq_activate_entity(struct bfq_entity *entity) -+{ -+ struct bfq_sched_data *sd = entity->sched_data; -+ struct bfq_service_tree *st = bfq_entity_service_tree(entity); -+ -+ if (entity == sd->in_service_entity) { -+ BUG_ON(entity->tree != NULL); -+ /* -+ * If we are requeueing the current entity we have -+ * to take care of not charging to it service it has -+ * not received. -+ */ -+ bfq_calc_finish(entity, entity->service); -+ entity->start = entity->finish; -+ sd->in_service_entity = NULL; -+ } else if (entity->tree == &st->active) { -+ /* -+ * Requeueing an entity due to a change of some -+ * next_in_service entity below it. We reuse the -+ * old start time. -+ */ -+ bfq_active_extract(st, entity); -+ } else if (entity->tree == &st->idle) { -+ /* -+ * Must be on the idle tree, bfq_idle_extract() will -+ * check for that. -+ */ -+ bfq_idle_extract(st, entity); -+ entity->start = bfq_gt(st->vtime, entity->finish) ? -+ st->vtime : entity->finish; -+ } else { -+ /* -+ * The finish time of the entity may be invalid, and -+ * it is in the past for sure, otherwise the queue -+ * would have been on the idle tree. -+ */ -+ entity->start = st->vtime; -+ st->wsum += entity->weight; -+ bfq_get_entity(entity); -+ -+ BUG_ON(entity->on_st); -+ entity->on_st = 1; -+ } -+ -+ st = __bfq_entity_update_weight_prio(st, entity); -+ bfq_calc_finish(entity, entity->budget); -+ bfq_active_insert(st, entity); -+} -+ -+/** -+ * bfq_activate_entity - activate an entity and its ancestors if necessary. -+ * @entity: the entity to activate. -+ * -+ * Activate @entity and all the entities on the path from it to the root. -+ */ -+static void bfq_activate_entity(struct bfq_entity *entity) -+{ -+ struct bfq_sched_data *sd; -+ -+ for_each_entity(entity) { -+ __bfq_activate_entity(entity); -+ -+ sd = entity->sched_data; -+ if (!bfq_update_next_in_service(sd)) -+ /* -+ * No need to propagate the activation to the -+ * upper entities, as they will be updated when -+ * the in-service entity is rescheduled. -+ */ -+ break; -+ } -+} -+ -+/** -+ * __bfq_deactivate_entity - deactivate an entity from its service tree. -+ * @entity: the entity to deactivate. -+ * @requeue: if false, the entity will not be put into the idle tree. -+ * -+ * Deactivate an entity, independently from its previous state. If the -+ * entity was not on a service tree just return, otherwise if it is on -+ * any scheduler tree, extract it from that tree, and if necessary -+ * and if the caller did not specify @requeue, put it on the idle tree. -+ * -+ * Return %1 if the caller should update the entity hierarchy, i.e., -+ * if the entity was in service or if it was the next_in_service for -+ * its sched_data; return %0 otherwise. -+ */ -+static int __bfq_deactivate_entity(struct bfq_entity *entity, int requeue) -+{ -+ struct bfq_sched_data *sd = entity->sched_data; -+ struct bfq_service_tree *st = bfq_entity_service_tree(entity); -+ int was_in_service = entity == sd->in_service_entity; -+ int ret = 0; -+ -+ if (!entity->on_st) -+ return 0; -+ -+ BUG_ON(was_in_service && entity->tree != NULL); -+ -+ if (was_in_service) { -+ bfq_calc_finish(entity, entity->service); -+ sd->in_service_entity = NULL; -+ } else if (entity->tree == &st->active) -+ bfq_active_extract(st, entity); -+ else if (entity->tree == &st->idle) -+ bfq_idle_extract(st, entity); -+ else if (entity->tree != NULL) -+ BUG(); -+ -+ if (was_in_service || sd->next_in_service == entity) -+ ret = bfq_update_next_in_service(sd); -+ -+ if (!requeue || !bfq_gt(entity->finish, st->vtime)) -+ bfq_forget_entity(st, entity); -+ else -+ bfq_idle_insert(st, entity); -+ -+ BUG_ON(sd->in_service_entity == entity); -+ BUG_ON(sd->next_in_service == entity); -+ -+ return ret; -+} -+ -+/** -+ * bfq_deactivate_entity - deactivate an entity. -+ * @entity: the entity to deactivate. -+ * @requeue: true if the entity can be put on the idle tree -+ */ -+static void bfq_deactivate_entity(struct bfq_entity *entity, int requeue) -+{ -+ struct bfq_sched_data *sd; -+ struct bfq_entity *parent; -+ -+ for_each_entity_safe(entity, parent) { -+ sd = entity->sched_data; -+ -+ if (!__bfq_deactivate_entity(entity, requeue)) -+ /* -+ * The parent entity is still backlogged, and -+ * we don't need to update it as it is still -+ * in service. -+ */ -+ break; -+ -+ if (sd->next_in_service != NULL) -+ /* -+ * The parent entity is still backlogged and -+ * the budgets on the path towards the root -+ * need to be updated. -+ */ -+ goto update; -+ -+ /* -+ * If we reach there the parent is no more backlogged and -+ * we want to propagate the dequeue upwards. -+ */ -+ requeue = 1; -+ } -+ -+ return; -+ -+update: -+ entity = parent; -+ for_each_entity(entity) { -+ __bfq_activate_entity(entity); -+ -+ sd = entity->sched_data; -+ if (!bfq_update_next_in_service(sd)) -+ break; -+ } -+} -+ -+/** -+ * bfq_update_vtime - update vtime if necessary. -+ * @st: the service tree to act upon. -+ * -+ * If necessary update the service tree vtime to have at least one -+ * eligible entity, skipping to its start time. Assumes that the -+ * active tree of the device is not empty. -+ * -+ * NOTE: this hierarchical implementation updates vtimes quite often, -+ * we may end up with reactivated processes getting timestamps after a -+ * vtime skip done because we needed a ->first_active entity on some -+ * intermediate node. -+ */ -+static void bfq_update_vtime(struct bfq_service_tree *st) -+{ -+ struct bfq_entity *entry; -+ struct rb_node *node = st->active.rb_node; -+ -+ entry = rb_entry(node, struct bfq_entity, rb_node); -+ if (bfq_gt(entry->min_start, st->vtime)) { -+ st->vtime = entry->min_start; -+ bfq_forget_idle(st); -+ } -+} -+ -+/** -+ * bfq_first_active_entity - find the eligible entity with -+ * the smallest finish time -+ * @st: the service tree to select from. -+ * -+ * This function searches the first schedulable entity, starting from the -+ * root of the tree and going on the left every time on this side there is -+ * a subtree with at least one eligible (start >= vtime) entity. The path on -+ * the right is followed only if a) the left subtree contains no eligible -+ * entities and b) no eligible entity has been found yet. -+ */ -+static struct bfq_entity *bfq_first_active_entity(struct bfq_service_tree *st) -+{ -+ struct bfq_entity *entry, *first = NULL; -+ struct rb_node *node = st->active.rb_node; -+ -+ while (node != NULL) { -+ entry = rb_entry(node, struct bfq_entity, rb_node); -+left: -+ if (!bfq_gt(entry->start, st->vtime)) -+ first = entry; -+ -+ BUG_ON(bfq_gt(entry->min_start, st->vtime)); -+ -+ if (node->rb_left != NULL) { -+ entry = rb_entry(node->rb_left, -+ struct bfq_entity, rb_node); -+ if (!bfq_gt(entry->min_start, st->vtime)) { -+ node = node->rb_left; -+ goto left; -+ } -+ } -+ if (first != NULL) -+ break; -+ node = node->rb_right; -+ } -+ -+ BUG_ON(first == NULL && !RB_EMPTY_ROOT(&st->active)); -+ return first; -+} -+ -+/** -+ * __bfq_lookup_next_entity - return the first eligible entity in @st. -+ * @st: the service tree. -+ * -+ * Update the virtual time in @st and return the first eligible entity -+ * it contains. -+ */ -+static struct bfq_entity *__bfq_lookup_next_entity(struct bfq_service_tree *st, -+ bool force) -+{ -+ struct bfq_entity *entity, *new_next_in_service = NULL; -+ -+ if (RB_EMPTY_ROOT(&st->active)) -+ return NULL; -+ -+ bfq_update_vtime(st); -+ entity = bfq_first_active_entity(st); -+ BUG_ON(bfq_gt(entity->start, st->vtime)); -+ -+ /* -+ * If the chosen entity does not match with the sched_data's -+ * next_in_service and we are forcedly serving the IDLE priority -+ * class tree, bubble up budget update. -+ */ -+ if (unlikely(force && entity != entity->sched_data->next_in_service)) { -+ new_next_in_service = entity; -+ for_each_entity(new_next_in_service) -+ bfq_update_budget(new_next_in_service); -+ } -+ -+ return entity; -+} -+ -+/** -+ * bfq_lookup_next_entity - return the first eligible entity in @sd. -+ * @sd: the sched_data. -+ * @extract: if true the returned entity will be also extracted from @sd. -+ * -+ * NOTE: since we cache the next_in_service entity at each level of the -+ * hierarchy, the complexity of the lookup can be decreased with -+ * absolutely no effort just returning the cached next_in_service value; -+ * we prefer to do full lookups to test the consistency of * the data -+ * structures. -+ */ -+static struct bfq_entity *bfq_lookup_next_entity(struct bfq_sched_data *sd, -+ int extract, -+ struct bfq_data *bfqd) -+{ -+ struct bfq_service_tree *st = sd->service_tree; -+ struct bfq_entity *entity; -+ int i = 0; -+ -+ BUG_ON(sd->in_service_entity != NULL); -+ -+ if (bfqd != NULL && -+ jiffies - bfqd->bfq_class_idle_last_service > BFQ_CL_IDLE_TIMEOUT) { -+ entity = __bfq_lookup_next_entity(st + BFQ_IOPRIO_CLASSES - 1, -+ true); -+ if (entity != NULL) { -+ i = BFQ_IOPRIO_CLASSES - 1; -+ bfqd->bfq_class_idle_last_service = jiffies; -+ sd->next_in_service = entity; -+ } -+ } -+ for (; i < BFQ_IOPRIO_CLASSES; i++) { -+ entity = __bfq_lookup_next_entity(st + i, false); -+ if (entity != NULL) { -+ if (extract) { -+ bfq_check_next_in_service(sd, entity); -+ bfq_active_extract(st + i, entity); -+ sd->in_service_entity = entity; -+ sd->next_in_service = NULL; -+ } -+ break; -+ } -+ } -+ -+ return entity; -+} -+ -+/* -+ * Get next queue for service. -+ */ -+static struct bfq_queue *bfq_get_next_queue(struct bfq_data *bfqd) -+{ -+ struct bfq_entity *entity = NULL; -+ struct bfq_sched_data *sd; -+ struct bfq_queue *bfqq; -+ -+ BUG_ON(bfqd->in_service_queue != NULL); -+ -+ if (bfqd->busy_queues == 0) -+ return NULL; -+ -+ sd = &bfqd->root_group->sched_data; -+ for (; sd != NULL; sd = entity->my_sched_data) { -+ entity = bfq_lookup_next_entity(sd, 1, bfqd); -+ BUG_ON(entity == NULL); -+ entity->service = 0; -+ } -+ -+ bfqq = bfq_entity_to_bfqq(entity); -+ BUG_ON(bfqq == NULL); -+ -+ return bfqq; -+} -+ -+/* -+ * Forced extraction of the given queue. -+ */ -+static void bfq_get_next_queue_forced(struct bfq_data *bfqd, -+ struct bfq_queue *bfqq) -+{ -+ struct bfq_entity *entity; -+ struct bfq_sched_data *sd; -+ -+ BUG_ON(bfqd->in_service_queue != NULL); -+ -+ entity = &bfqq->entity; -+ /* -+ * Bubble up extraction/update from the leaf to the root. -+ */ -+ for_each_entity(entity) { -+ sd = entity->sched_data; -+ bfq_update_budget(entity); -+ bfq_update_vtime(bfq_entity_service_tree(entity)); -+ bfq_active_extract(bfq_entity_service_tree(entity), entity); -+ sd->in_service_entity = entity; -+ sd->next_in_service = NULL; -+ entity->service = 0; -+ } -+ -+ return; -+} -+ -+static void __bfq_bfqd_reset_in_service(struct bfq_data *bfqd) -+{ -+ if (bfqd->in_service_bic != NULL) { -+ put_io_context(bfqd->in_service_bic->icq.ioc); -+ bfqd->in_service_bic = NULL; -+ } -+ -+ bfqd->in_service_queue = NULL; -+ del_timer(&bfqd->idle_slice_timer); -+} -+ -+static void bfq_deactivate_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq, -+ int requeue) -+{ -+ struct bfq_entity *entity = &bfqq->entity; -+ -+ if (bfqq == bfqd->in_service_queue) -+ __bfq_bfqd_reset_in_service(bfqd); -+ -+ bfq_deactivate_entity(entity, requeue); -+} -+ -+static void bfq_activate_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq) -+{ -+ struct bfq_entity *entity = &bfqq->entity; -+ -+ bfq_activate_entity(entity); -+} -+ -+/* -+ * Called when the bfqq no longer has requests pending, remove it from -+ * the service tree. -+ */ -+static void bfq_del_bfqq_busy(struct bfq_data *bfqd, struct bfq_queue *bfqq, -+ int requeue) -+{ -+ BUG_ON(!bfq_bfqq_busy(bfqq)); -+ BUG_ON(!RB_EMPTY_ROOT(&bfqq->sort_list)); -+ -+ bfq_log_bfqq(bfqd, bfqq, "del from busy"); -+ -+ bfq_clear_bfqq_busy(bfqq); -+ -+ BUG_ON(bfqd->busy_queues == 0); -+ bfqd->busy_queues--; -+ -+ if (!bfqq->dispatched) { -+ bfq_weights_tree_remove(bfqd, &bfqq->entity, -+ &bfqd->queue_weights_tree); -+ if (!blk_queue_nonrot(bfqd->queue)) { -+ BUG_ON(!bfqd->busy_in_flight_queues); -+ bfqd->busy_in_flight_queues--; -+ if (bfq_bfqq_constantly_seeky(bfqq)) { -+ BUG_ON(!bfqd-> -+ const_seeky_busy_in_flight_queues); -+ bfqd->const_seeky_busy_in_flight_queues--; -+ } -+ } -+ } -+ if (bfqq->wr_coeff > 1) -+ bfqd->wr_busy_queues--; -+ -+ bfq_deactivate_bfqq(bfqd, bfqq, requeue); -+} -+ -+/* -+ * Called when an inactive queue receives a new request. -+ */ -+static void bfq_add_bfqq_busy(struct bfq_data *bfqd, struct bfq_queue *bfqq) -+{ -+ BUG_ON(bfq_bfqq_busy(bfqq)); -+ BUG_ON(bfqq == bfqd->in_service_queue); -+ -+ bfq_log_bfqq(bfqd, bfqq, "add to busy"); -+ -+ bfq_activate_bfqq(bfqd, bfqq); -+ -+ bfq_mark_bfqq_busy(bfqq); -+ bfqd->busy_queues++; -+ -+ if (!bfqq->dispatched) { -+ if (bfqq->wr_coeff == 1) -+ bfq_weights_tree_add(bfqd, &bfqq->entity, -+ &bfqd->queue_weights_tree); -+ if (!blk_queue_nonrot(bfqd->queue)) { -+ bfqd->busy_in_flight_queues++; -+ if (bfq_bfqq_constantly_seeky(bfqq)) -+ bfqd->const_seeky_busy_in_flight_queues++; -+ } -+ } -+ if (bfqq->wr_coeff > 1) -+ bfqd->wr_busy_queues++; -+} -diff --git a/block/bfq.h b/block/bfq.h -new file mode 100644 -index 0000000..3c5d85e ---- /dev/null -+++ b/block/bfq.h -@@ -0,0 +1,775 @@ -+/* -+ * BFQ-v7r7 for 3.19.0: data structures and common functions prototypes. -+ * -+ * Based on ideas and code from CFQ: -+ * Copyright (C) 2003 Jens Axboe -+ * -+ * Copyright (C) 2008 Fabio Checconi -+ * Paolo Valente -+ * -+ * Copyright (C) 2010 Paolo Valente -+ */ -+ -+#ifndef _BFQ_H -+#define _BFQ_H -+ -+#include -+#include -+#include -+#include -+ -+#define BFQ_IOPRIO_CLASSES 3 -+#define BFQ_CL_IDLE_TIMEOUT (HZ/5) -+ -+#define BFQ_MIN_WEIGHT 1 -+#define BFQ_MAX_WEIGHT 1000 -+ -+#define BFQ_DEFAULT_QUEUE_IOPRIO 4 -+ -+#define BFQ_DEFAULT_GRP_WEIGHT 10 -+#define BFQ_DEFAULT_GRP_IOPRIO 0 -+#define BFQ_DEFAULT_GRP_CLASS IOPRIO_CLASS_BE -+ -+struct bfq_entity; -+ -+/** -+ * struct bfq_service_tree - per ioprio_class service tree. -+ * @active: tree for active entities (i.e., those backlogged). -+ * @idle: tree for idle entities (i.e., those not backlogged, with V <= F_i). -+ * @first_idle: idle entity with minimum F_i. -+ * @last_idle: idle entity with maximum F_i. -+ * @vtime: scheduler virtual time. -+ * @wsum: scheduler weight sum; active and idle entities contribute to it. -+ * -+ * Each service tree represents a B-WF2Q+ scheduler on its own. Each -+ * ioprio_class has its own independent scheduler, and so its own -+ * bfq_service_tree. All the fields are protected by the queue lock -+ * of the containing bfqd. -+ */ -+struct bfq_service_tree { -+ struct rb_root active; -+ struct rb_root idle; -+ -+ struct bfq_entity *first_idle; -+ struct bfq_entity *last_idle; -+ -+ u64 vtime; -+ unsigned long wsum; -+}; -+ -+/** -+ * struct bfq_sched_data - multi-class scheduler. -+ * @in_service_entity: entity in service. -+ * @next_in_service: head-of-the-line entity in the scheduler. -+ * @service_tree: array of service trees, one per ioprio_class. -+ * -+ * bfq_sched_data is the basic scheduler queue. It supports three -+ * ioprio_classes, and can be used either as a toplevel queue or as -+ * an intermediate queue on a hierarchical setup. -+ * @next_in_service points to the active entity of the sched_data -+ * service trees that will be scheduled next. -+ * -+ * The supported ioprio_classes are the same as in CFQ, in descending -+ * priority order, IOPRIO_CLASS_RT, IOPRIO_CLASS_BE, IOPRIO_CLASS_IDLE. -+ * Requests from higher priority queues are served before all the -+ * requests from lower priority queues; among requests of the same -+ * queue requests are served according to B-WF2Q+. -+ * All the fields are protected by the queue lock of the containing bfqd. -+ */ -+struct bfq_sched_data { -+ struct bfq_entity *in_service_entity; -+ struct bfq_entity *next_in_service; -+ struct bfq_service_tree service_tree[BFQ_IOPRIO_CLASSES]; -+}; -+ -+/** -+ * struct bfq_weight_counter - counter of the number of all active entities -+ * with a given weight. -+ * @weight: weight of the entities that this counter refers to. -+ * @num_active: number of active entities with this weight. -+ * @weights_node: weights tree member (see bfq_data's @queue_weights_tree -+ * and @group_weights_tree). -+ */ -+struct bfq_weight_counter { -+ short int weight; -+ unsigned int num_active; -+ struct rb_node weights_node; -+}; -+ -+/** -+ * struct bfq_entity - schedulable entity. -+ * @rb_node: service_tree member. -+ * @weight_counter: pointer to the weight counter associated with this entity. -+ * @on_st: flag, true if the entity is on a tree (either the active or -+ * the idle one of its service_tree). -+ * @finish: B-WF2Q+ finish timestamp (aka F_i). -+ * @start: B-WF2Q+ start timestamp (aka S_i). -+ * @tree: tree the entity is enqueued into; %NULL if not on a tree. -+ * @min_start: minimum start time of the (active) subtree rooted at -+ * this entity; used for O(log N) lookups into active trees. -+ * @service: service received during the last round of service. -+ * @budget: budget used to calculate F_i; F_i = S_i + @budget / @weight. -+ * @weight: weight of the queue -+ * @parent: parent entity, for hierarchical scheduling. -+ * @my_sched_data: for non-leaf nodes in the cgroup hierarchy, the -+ * associated scheduler queue, %NULL on leaf nodes. -+ * @sched_data: the scheduler queue this entity belongs to. -+ * @ioprio: the ioprio in use. -+ * @new_weight: when a weight change is requested, the new weight value. -+ * @orig_weight: original weight, used to implement weight boosting -+ * @new_ioprio: when an ioprio change is requested, the new ioprio value. -+ * @ioprio_class: the ioprio_class in use. -+ * @new_ioprio_class: when an ioprio_class change is requested, the new -+ * ioprio_class value. -+ * @ioprio_changed: flag, true when the user requested a weight, ioprio or -+ * ioprio_class change. -+ * -+ * A bfq_entity is used to represent either a bfq_queue (leaf node in the -+ * cgroup hierarchy) or a bfq_group into the upper level scheduler. Each -+ * entity belongs to the sched_data of the parent group in the cgroup -+ * hierarchy. Non-leaf entities have also their own sched_data, stored -+ * in @my_sched_data. -+ * -+ * Each entity stores independently its priority values; this would -+ * allow different weights on different devices, but this -+ * functionality is not exported to userspace by now. Priorities and -+ * weights are updated lazily, first storing the new values into the -+ * new_* fields, then setting the @ioprio_changed flag. As soon as -+ * there is a transition in the entity state that allows the priority -+ * update to take place the effective and the requested priority -+ * values are synchronized. -+ * -+ * Unless cgroups are used, the weight value is calculated from the -+ * ioprio to export the same interface as CFQ. When dealing with -+ * ``well-behaved'' queues (i.e., queues that do not spend too much -+ * time to consume their budget and have true sequential behavior, and -+ * when there are no external factors breaking anticipation) the -+ * relative weights at each level of the cgroups hierarchy should be -+ * guaranteed. All the fields are protected by the queue lock of the -+ * containing bfqd. -+ */ -+struct bfq_entity { -+ struct rb_node rb_node; -+ struct bfq_weight_counter *weight_counter; -+ -+ int on_st; -+ -+ u64 finish; -+ u64 start; -+ -+ struct rb_root *tree; -+ -+ u64 min_start; -+ -+ unsigned long service, budget; -+ unsigned short weight, new_weight; -+ unsigned short orig_weight; -+ -+ struct bfq_entity *parent; -+ -+ struct bfq_sched_data *my_sched_data; -+ struct bfq_sched_data *sched_data; -+ -+ unsigned short ioprio, new_ioprio; -+ unsigned short ioprio_class, new_ioprio_class; -+ -+ int ioprio_changed; -+}; -+ -+struct bfq_group; -+ -+/** -+ * struct bfq_queue - leaf schedulable entity. -+ * @ref: reference counter. -+ * @bfqd: parent bfq_data. -+ * @new_bfqq: shared bfq_queue if queue is cooperating with -+ * one or more other queues. -+ * @pos_node: request-position tree member (see bfq_data's @rq_pos_tree). -+ * @pos_root: request-position tree root (see bfq_data's @rq_pos_tree). -+ * @sort_list: sorted list of pending requests. -+ * @next_rq: if fifo isn't expired, next request to serve. -+ * @queued: nr of requests queued in @sort_list. -+ * @allocated: currently allocated requests. -+ * @meta_pending: pending metadata requests. -+ * @fifo: fifo list of requests in sort_list. -+ * @entity: entity representing this queue in the scheduler. -+ * @max_budget: maximum budget allowed from the feedback mechanism. -+ * @budget_timeout: budget expiration (in jiffies). -+ * @dispatched: number of requests on the dispatch list or inside driver. -+ * @flags: status flags. -+ * @bfqq_list: node for active/idle bfqq list inside our bfqd. -+ * @burst_list_node: node for the device's burst list. -+ * @seek_samples: number of seeks sampled -+ * @seek_total: sum of the distances of the seeks sampled -+ * @seek_mean: mean seek distance -+ * @last_request_pos: position of the last request enqueued -+ * @requests_within_timer: number of consecutive pairs of request completion -+ * and arrival, such that the queue becomes idle -+ * after the completion, but the next request arrives -+ * within an idle time slice; used only if the queue's -+ * IO_bound has been cleared. -+ * @pid: pid of the process owning the queue, used for logging purposes. -+ * @last_wr_start_finish: start time of the current weight-raising period if -+ * the @bfq-queue is being weight-raised, otherwise -+ * finish time of the last weight-raising period -+ * @wr_cur_max_time: current max raising time for this queue -+ * @soft_rt_next_start: minimum time instant such that, only if a new -+ * request is enqueued after this time instant in an -+ * idle @bfq_queue with no outstanding requests, then -+ * the task associated with the queue it is deemed as -+ * soft real-time (see the comments to the function -+ * bfq_bfqq_softrt_next_start()). -+ * @last_idle_bklogged: time of the last transition of the @bfq_queue from -+ * idle to backlogged -+ * @service_from_backlogged: cumulative service received from the @bfq_queue -+ * since the last transition from idle to -+ * backlogged -+ * -+ * A bfq_queue is a leaf request queue; it can be associated with an io_context -+ * or more, if it is async or shared between cooperating processes. @cgroup -+ * holds a reference to the cgroup, to be sure that it does not disappear while -+ * a bfqq still references it (mostly to avoid races between request issuing and -+ * task migration followed by cgroup destruction). -+ * All the fields are protected by the queue lock of the containing bfqd. -+ */ -+struct bfq_queue { -+ atomic_t ref; -+ struct bfq_data *bfqd; -+ -+ /* fields for cooperating queues handling */ -+ struct bfq_queue *new_bfqq; -+ struct rb_node pos_node; -+ struct rb_root *pos_root; -+ -+ struct rb_root sort_list; -+ struct request *next_rq; -+ int queued[2]; -+ int allocated[2]; -+ int meta_pending; -+ struct list_head fifo; -+ -+ struct bfq_entity entity; -+ -+ unsigned long max_budget; -+ unsigned long budget_timeout; -+ -+ int dispatched; -+ -+ unsigned int flags; -+ -+ struct list_head bfqq_list; -+ -+ struct hlist_node burst_list_node; -+ -+ unsigned int seek_samples; -+ u64 seek_total; -+ sector_t seek_mean; -+ sector_t last_request_pos; -+ -+ unsigned int requests_within_timer; -+ -+ pid_t pid; -+ -+ /* weight-raising fields */ -+ unsigned long wr_cur_max_time; -+ unsigned long soft_rt_next_start; -+ unsigned long last_wr_start_finish; -+ unsigned int wr_coeff; -+ unsigned long last_idle_bklogged; -+ unsigned long service_from_backlogged; -+}; -+ -+/** -+ * struct bfq_ttime - per process thinktime stats. -+ * @ttime_total: total process thinktime -+ * @ttime_samples: number of thinktime samples -+ * @ttime_mean: average process thinktime -+ */ -+struct bfq_ttime { -+ unsigned long last_end_request; -+ -+ unsigned long ttime_total; -+ unsigned long ttime_samples; -+ unsigned long ttime_mean; -+}; -+ -+/** -+ * struct bfq_io_cq - per (request_queue, io_context) structure. -+ * @icq: associated io_cq structure -+ * @bfqq: array of two process queues, the sync and the async -+ * @ttime: associated @bfq_ttime struct -+ */ -+struct bfq_io_cq { -+ struct io_cq icq; /* must be the first member */ -+ struct bfq_queue *bfqq[2]; -+ struct bfq_ttime ttime; -+ int ioprio; -+}; -+ -+enum bfq_device_speed { -+ BFQ_BFQD_FAST, -+ BFQ_BFQD_SLOW, -+}; -+ -+/** -+ * struct bfq_data - per device data structure. -+ * @queue: request queue for the managed device. -+ * @root_group: root bfq_group for the device. -+ * @rq_pos_tree: rbtree sorted by next_request position, used when -+ * determining if two or more queues have interleaving -+ * requests (see bfq_close_cooperator()). -+ * @active_numerous_groups: number of bfq_groups containing more than one -+ * active @bfq_entity. -+ * @queue_weights_tree: rbtree of weight counters of @bfq_queues, sorted by -+ * weight. Used to keep track of whether all @bfq_queues -+ * have the same weight. The tree contains one counter -+ * for each distinct weight associated to some active -+ * and not weight-raised @bfq_queue (see the comments to -+ * the functions bfq_weights_tree_[add|remove] for -+ * further details). -+ * @group_weights_tree: rbtree of non-queue @bfq_entity weight counters, sorted -+ * by weight. Used to keep track of whether all -+ * @bfq_groups have the same weight. The tree contains -+ * one counter for each distinct weight associated to -+ * some active @bfq_group (see the comments to the -+ * functions bfq_weights_tree_[add|remove] for further -+ * details). -+ * @busy_queues: number of bfq_queues containing requests (including the -+ * queue in service, even if it is idling). -+ * @busy_in_flight_queues: number of @bfq_queues containing pending or -+ * in-flight requests, plus the @bfq_queue in -+ * service, even if idle but waiting for the -+ * possible arrival of its next sync request. This -+ * field is updated only if the device is rotational, -+ * but used only if the device is also NCQ-capable. -+ * The reason why the field is updated also for non- -+ * NCQ-capable rotational devices is related to the -+ * fact that the value of @hw_tag may be set also -+ * later than when busy_in_flight_queues may need to -+ * be incremented for the first time(s). Taking also -+ * this possibility into account, to avoid unbalanced -+ * increments/decrements, would imply more overhead -+ * than just updating busy_in_flight_queues -+ * regardless of the value of @hw_tag. -+ * @const_seeky_busy_in_flight_queues: number of constantly-seeky @bfq_queues -+ * (that is, seeky queues that expired -+ * for budget timeout at least once) -+ * containing pending or in-flight -+ * requests, including the in-service -+ * @bfq_queue if constantly seeky. This -+ * field is updated only if the device -+ * is rotational, but used only if the -+ * device is also NCQ-capable (see the -+ * comments to @busy_in_flight_queues). -+ * @wr_busy_queues: number of weight-raised busy @bfq_queues. -+ * @queued: number of queued requests. -+ * @rq_in_driver: number of requests dispatched and waiting for completion. -+ * @sync_flight: number of sync requests in the driver. -+ * @max_rq_in_driver: max number of reqs in driver in the last -+ * @hw_tag_samples completed requests. -+ * @hw_tag_samples: nr of samples used to calculate hw_tag. -+ * @hw_tag: flag set to one if the driver is showing a queueing behavior. -+ * @budgets_assigned: number of budgets assigned. -+ * @idle_slice_timer: timer set when idling for the next sequential request -+ * from the queue in service. -+ * @unplug_work: delayed work to restart dispatching on the request queue. -+ * @in_service_queue: bfq_queue in service. -+ * @in_service_bic: bfq_io_cq (bic) associated with the @in_service_queue. -+ * @last_position: on-disk position of the last served request. -+ * @last_budget_start: beginning of the last budget. -+ * @last_idling_start: beginning of the last idle slice. -+ * @peak_rate: peak transfer rate observed for a budget. -+ * @peak_rate_samples: number of samples used to calculate @peak_rate. -+ * @bfq_max_budget: maximum budget allotted to a bfq_queue before -+ * rescheduling. -+ * @group_list: list of all the bfq_groups active on the device. -+ * @active_list: list of all the bfq_queues active on the device. -+ * @idle_list: list of all the bfq_queues idle on the device. -+ * @bfq_quantum: max number of requests dispatched per dispatch round. -+ * @bfq_fifo_expire: timeout for async/sync requests; when it expires -+ * requests are served in fifo order. -+ * @bfq_back_penalty: weight of backward seeks wrt forward ones. -+ * @bfq_back_max: maximum allowed backward seek. -+ * @bfq_slice_idle: maximum idling time. -+ * @bfq_user_max_budget: user-configured max budget value -+ * (0 for auto-tuning). -+ * @bfq_max_budget_async_rq: maximum budget (in nr of requests) allotted to -+ * async queues. -+ * @bfq_timeout: timeout for bfq_queues to consume their budget; used to -+ * to prevent seeky queues to impose long latencies to well -+ * behaved ones (this also implies that seeky queues cannot -+ * receive guarantees in the service domain; after a timeout -+ * they are charged for the whole allocated budget, to try -+ * to preserve a behavior reasonably fair among them, but -+ * without service-domain guarantees). -+ * @bfq_coop_thresh: number of queue merges after which a @bfq_queue is -+ * no more granted any weight-raising. -+ * @bfq_failed_cooperations: number of consecutive failed cooperation -+ * chances after which weight-raising is restored -+ * to a queue subject to more than bfq_coop_thresh -+ * queue merges. -+ * @bfq_requests_within_timer: number of consecutive requests that must be -+ * issued within the idle time slice to set -+ * again idling to a queue which was marked as -+ * non-I/O-bound (see the definition of the -+ * IO_bound flag for further details). -+ * @last_ins_in_burst: last time at which a queue entered the current -+ * burst of queues being activated shortly after -+ * each other; for more details about this and the -+ * following parameters related to a burst of -+ * activations, see the comments to the function -+ * @bfq_handle_burst. -+ * @bfq_burst_interval: reference time interval used to decide whether a -+ * queue has been activated shortly after -+ * @last_ins_in_burst. -+ * @burst_size: number of queues in the current burst of queue activations. -+ * @bfq_large_burst_thresh: maximum burst size above which the current -+ * queue-activation burst is deemed as 'large'. -+ * @large_burst: true if a large queue-activation burst is in progress. -+ * @burst_list: head of the burst list (as for the above fields, more details -+ * in the comments to the function bfq_handle_burst). -+ * @low_latency: if set to true, low-latency heuristics are enabled. -+ * @bfq_wr_coeff: maximum factor by which the weight of a weight-raised -+ * queue is multiplied. -+ * @bfq_wr_max_time: maximum duration of a weight-raising period (jiffies). -+ * @bfq_wr_rt_max_time: maximum duration for soft real-time processes. -+ * @bfq_wr_min_idle_time: minimum idle period after which weight-raising -+ * may be reactivated for a queue (in jiffies). -+ * @bfq_wr_min_inter_arr_async: minimum period between request arrivals -+ * after which weight-raising may be -+ * reactivated for an already busy queue -+ * (in jiffies). -+ * @bfq_wr_max_softrt_rate: max service-rate for a soft real-time queue, -+ * sectors per seconds. -+ * @RT_prod: cached value of the product R*T used for computing the maximum -+ * duration of the weight raising automatically. -+ * @device_speed: device-speed class for the low-latency heuristic. -+ * @oom_bfqq: fallback dummy bfqq for extreme OOM conditions. -+ * -+ * All the fields are protected by the @queue lock. -+ */ -+struct bfq_data { -+ struct request_queue *queue; -+ -+ struct bfq_group *root_group; -+ struct rb_root rq_pos_tree; -+ -+#ifdef CONFIG_CGROUP_BFQIO -+ int active_numerous_groups; -+#endif -+ -+ struct rb_root queue_weights_tree; -+ struct rb_root group_weights_tree; -+ -+ int busy_queues; -+ int busy_in_flight_queues; -+ int const_seeky_busy_in_flight_queues; -+ int wr_busy_queues; -+ int queued; -+ int rq_in_driver; -+ int sync_flight; -+ -+ int max_rq_in_driver; -+ int hw_tag_samples; -+ int hw_tag; -+ -+ int budgets_assigned; -+ -+ struct timer_list idle_slice_timer; -+ struct work_struct unplug_work; -+ -+ struct bfq_queue *in_service_queue; -+ struct bfq_io_cq *in_service_bic; -+ -+ sector_t last_position; -+ -+ ktime_t last_budget_start; -+ ktime_t last_idling_start; -+ int peak_rate_samples; -+ u64 peak_rate; -+ unsigned long bfq_max_budget; -+ -+ struct hlist_head group_list; -+ struct list_head active_list; -+ struct list_head idle_list; -+ -+ unsigned int bfq_quantum; -+ unsigned int bfq_fifo_expire[2]; -+ unsigned int bfq_back_penalty; -+ unsigned int bfq_back_max; -+ unsigned int bfq_slice_idle; -+ u64 bfq_class_idle_last_service; -+ -+ unsigned int bfq_user_max_budget; -+ unsigned int bfq_max_budget_async_rq; -+ unsigned int bfq_timeout[2]; -+ -+ unsigned int bfq_coop_thresh; -+ unsigned int bfq_failed_cooperations; -+ unsigned int bfq_requests_within_timer; -+ -+ unsigned long last_ins_in_burst; -+ unsigned long bfq_burst_interval; -+ int burst_size; -+ unsigned long bfq_large_burst_thresh; -+ bool large_burst; -+ struct hlist_head burst_list; -+ -+ bool low_latency; -+ -+ /* parameters of the low_latency heuristics */ -+ unsigned int bfq_wr_coeff; -+ unsigned int bfq_wr_max_time; -+ unsigned int bfq_wr_rt_max_time; -+ unsigned int bfq_wr_min_idle_time; -+ unsigned long bfq_wr_min_inter_arr_async; -+ unsigned int bfq_wr_max_softrt_rate; -+ u64 RT_prod; -+ enum bfq_device_speed device_speed; -+ -+ struct bfq_queue oom_bfqq; -+}; -+ -+enum bfqq_state_flags { -+ BFQ_BFQQ_FLAG_busy = 0, /* has requests or is in service */ -+ BFQ_BFQQ_FLAG_wait_request, /* waiting for a request */ -+ BFQ_BFQQ_FLAG_must_alloc, /* must be allowed rq alloc */ -+ BFQ_BFQQ_FLAG_fifo_expire, /* FIFO checked in this slice */ -+ BFQ_BFQQ_FLAG_idle_window, /* slice idling enabled */ -+ BFQ_BFQQ_FLAG_prio_changed, /* task priority has changed */ -+ BFQ_BFQQ_FLAG_sync, /* synchronous queue */ -+ BFQ_BFQQ_FLAG_budget_new, /* no completion with this budget */ -+ BFQ_BFQQ_FLAG_IO_bound, /* -+ * bfqq has timed-out at least once -+ * having consumed at most 2/10 of -+ * its budget -+ */ -+ BFQ_BFQQ_FLAG_in_large_burst, /* -+ * bfqq activated in a large burst, -+ * see comments to bfq_handle_burst. -+ */ -+ BFQ_BFQQ_FLAG_constantly_seeky, /* -+ * bfqq has proved to be slow and -+ * seeky until budget timeout -+ */ -+ BFQ_BFQQ_FLAG_softrt_update, /* -+ * may need softrt-next-start -+ * update -+ */ -+ BFQ_BFQQ_FLAG_coop, /* bfqq is shared */ -+ BFQ_BFQQ_FLAG_split_coop, /* shared bfqq will be splitted */ -+}; -+ -+#define BFQ_BFQQ_FNS(name) \ -+static inline void bfq_mark_bfqq_##name(struct bfq_queue *bfqq) \ -+{ \ -+ (bfqq)->flags |= (1 << BFQ_BFQQ_FLAG_##name); \ -+} \ -+static inline void bfq_clear_bfqq_##name(struct bfq_queue *bfqq) \ -+{ \ -+ (bfqq)->flags &= ~(1 << BFQ_BFQQ_FLAG_##name); \ -+} \ -+static inline int bfq_bfqq_##name(const struct bfq_queue *bfqq) \ -+{ \ -+ return ((bfqq)->flags & (1 << BFQ_BFQQ_FLAG_##name)) != 0; \ -+} -+ -+BFQ_BFQQ_FNS(busy); -+BFQ_BFQQ_FNS(wait_request); -+BFQ_BFQQ_FNS(must_alloc); -+BFQ_BFQQ_FNS(fifo_expire); -+BFQ_BFQQ_FNS(idle_window); -+BFQ_BFQQ_FNS(prio_changed); -+BFQ_BFQQ_FNS(sync); -+BFQ_BFQQ_FNS(budget_new); -+BFQ_BFQQ_FNS(IO_bound); -+BFQ_BFQQ_FNS(in_large_burst); -+BFQ_BFQQ_FNS(constantly_seeky); -+BFQ_BFQQ_FNS(coop); -+BFQ_BFQQ_FNS(split_coop); -+BFQ_BFQQ_FNS(softrt_update); -+#undef BFQ_BFQQ_FNS -+ -+/* Logging facilities. */ -+#define bfq_log_bfqq(bfqd, bfqq, fmt, args...) \ -+ blk_add_trace_msg((bfqd)->queue, "bfq%d " fmt, (bfqq)->pid, ##args) -+ -+#define bfq_log(bfqd, fmt, args...) \ -+ blk_add_trace_msg((bfqd)->queue, "bfq " fmt, ##args) -+ -+/* Expiration reasons. */ -+enum bfqq_expiration { -+ BFQ_BFQQ_TOO_IDLE = 0, /* -+ * queue has been idling for -+ * too long -+ */ -+ BFQ_BFQQ_BUDGET_TIMEOUT, /* budget took too long to be used */ -+ BFQ_BFQQ_BUDGET_EXHAUSTED, /* budget consumed */ -+ BFQ_BFQQ_NO_MORE_REQUESTS, /* the queue has no more requests */ -+}; -+ -+#ifdef CONFIG_CGROUP_BFQIO -+/** -+ * struct bfq_group - per (device, cgroup) data structure. -+ * @entity: schedulable entity to insert into the parent group sched_data. -+ * @sched_data: own sched_data, to contain child entities (they may be -+ * both bfq_queues and bfq_groups). -+ * @group_node: node to be inserted into the bfqio_cgroup->group_data -+ * list of the containing cgroup's bfqio_cgroup. -+ * @bfqd_node: node to be inserted into the @bfqd->group_list list -+ * of the groups active on the same device; used for cleanup. -+ * @bfqd: the bfq_data for the device this group acts upon. -+ * @async_bfqq: array of async queues for all the tasks belonging to -+ * the group, one queue per ioprio value per ioprio_class, -+ * except for the idle class that has only one queue. -+ * @async_idle_bfqq: async queue for the idle class (ioprio is ignored). -+ * @my_entity: pointer to @entity, %NULL for the toplevel group; used -+ * to avoid too many special cases during group creation/ -+ * migration. -+ * @active_entities: number of active entities belonging to the group; -+ * unused for the root group. Used to know whether there -+ * are groups with more than one active @bfq_entity -+ * (see the comments to the function -+ * bfq_bfqq_must_not_expire()). -+ * -+ * Each (device, cgroup) pair has its own bfq_group, i.e., for each cgroup -+ * there is a set of bfq_groups, each one collecting the lower-level -+ * entities belonging to the group that are acting on the same device. -+ * -+ * Locking works as follows: -+ * o @group_node is protected by the bfqio_cgroup lock, and is accessed -+ * via RCU from its readers. -+ * o @bfqd is protected by the queue lock, RCU is used to access it -+ * from the readers. -+ * o All the other fields are protected by the @bfqd queue lock. -+ */ -+struct bfq_group { -+ struct bfq_entity entity; -+ struct bfq_sched_data sched_data; -+ -+ struct hlist_node group_node; -+ struct hlist_node bfqd_node; -+ -+ void *bfqd; -+ -+ struct bfq_queue *async_bfqq[2][IOPRIO_BE_NR]; -+ struct bfq_queue *async_idle_bfqq; -+ -+ struct bfq_entity *my_entity; -+ -+ int active_entities; -+}; -+ -+/** -+ * struct bfqio_cgroup - bfq cgroup data structure. -+ * @css: subsystem state for bfq in the containing cgroup. -+ * @online: flag marked when the subsystem is inserted. -+ * @weight: cgroup weight. -+ * @ioprio: cgroup ioprio. -+ * @ioprio_class: cgroup ioprio_class. -+ * @lock: spinlock that protects @ioprio, @ioprio_class and @group_data. -+ * @group_data: list containing the bfq_group belonging to this cgroup. -+ * -+ * @group_data is accessed using RCU, with @lock protecting the updates, -+ * @ioprio and @ioprio_class are protected by @lock. -+ */ -+struct bfqio_cgroup { -+ struct cgroup_subsys_state css; -+ bool online; -+ -+ unsigned short weight, ioprio, ioprio_class; -+ -+ spinlock_t lock; -+ struct hlist_head group_data; -+}; -+#else -+struct bfq_group { -+ struct bfq_sched_data sched_data; -+ -+ struct bfq_queue *async_bfqq[2][IOPRIO_BE_NR]; -+ struct bfq_queue *async_idle_bfqq; -+}; -+#endif -+ -+static inline struct bfq_service_tree * -+bfq_entity_service_tree(struct bfq_entity *entity) -+{ -+ struct bfq_sched_data *sched_data = entity->sched_data; -+ unsigned int idx = entity->ioprio_class - 1; -+ -+ BUG_ON(idx >= BFQ_IOPRIO_CLASSES); -+ BUG_ON(sched_data == NULL); -+ -+ return sched_data->service_tree + idx; -+} -+ -+static inline struct bfq_queue *bic_to_bfqq(struct bfq_io_cq *bic, -+ bool is_sync) -+{ -+ return bic->bfqq[is_sync]; -+} -+ -+static inline void bic_set_bfqq(struct bfq_io_cq *bic, -+ struct bfq_queue *bfqq, bool is_sync) -+{ -+ bic->bfqq[is_sync] = bfqq; -+} -+ -+static inline struct bfq_data *bic_to_bfqd(struct bfq_io_cq *bic) -+{ -+ return bic->icq.q->elevator->elevator_data; -+} -+ -+/** -+ * bfq_get_bfqd_locked - get a lock to a bfqd using a RCU protected pointer. -+ * @ptr: a pointer to a bfqd. -+ * @flags: storage for the flags to be saved. -+ * -+ * This function allows bfqg->bfqd to be protected by the -+ * queue lock of the bfqd they reference; the pointer is dereferenced -+ * under RCU, so the storage for bfqd is assured to be safe as long -+ * as the RCU read side critical section does not end. After the -+ * bfqd->queue->queue_lock is taken the pointer is rechecked, to be -+ * sure that no other writer accessed it. If we raced with a writer, -+ * the function returns NULL, with the queue unlocked, otherwise it -+ * returns the dereferenced pointer, with the queue locked. -+ */ -+static inline struct bfq_data *bfq_get_bfqd_locked(void **ptr, -+ unsigned long *flags) -+{ -+ struct bfq_data *bfqd; -+ -+ rcu_read_lock(); -+ bfqd = rcu_dereference(*(struct bfq_data **)ptr); -+ -+ if (bfqd != NULL) { -+ spin_lock_irqsave(bfqd->queue->queue_lock, *flags); -+ if (*ptr == bfqd) -+ goto out; -+ spin_unlock_irqrestore(bfqd->queue->queue_lock, *flags); -+ } -+ -+ bfqd = NULL; -+out: -+ rcu_read_unlock(); -+ return bfqd; -+} -+ -+static inline void bfq_put_bfqd_unlock(struct bfq_data *bfqd, -+ unsigned long *flags) -+{ -+ spin_unlock_irqrestore(bfqd->queue->queue_lock, *flags); -+} -+ -+static void bfq_changed_ioprio(struct bfq_io_cq *bic); -+static void bfq_put_queue(struct bfq_queue *bfqq); -+static void bfq_dispatch_insert(struct request_queue *q, struct request *rq); -+static struct bfq_queue *bfq_get_queue(struct bfq_data *bfqd, -+ struct bfq_group *bfqg, int is_sync, -+ struct bfq_io_cq *bic, gfp_t gfp_mask); -+static void bfq_end_wr_async_queues(struct bfq_data *bfqd, -+ struct bfq_group *bfqg); -+static void bfq_put_async_queues(struct bfq_data *bfqd, struct bfq_group *bfqg); -+static void bfq_exit_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq); -+ -+#endif /* _BFQ_H */ --- -2.3.0 - diff --git a/kernel/kernel/files/patches/gentoo/5002_block-introduce-the-BFQ-v7r7-I-O-sched-for-3.19.patch1.txt b/kernel/kernel/files/patches/gentoo/5002_block-introduce-the-BFQ-v7r7-I-O-sched-for-3.19.patch1.txt deleted file mode 100644 index fb96ff28..00000000 --- a/kernel/kernel/files/patches/gentoo/5002_block-introduce-the-BFQ-v7r7-I-O-sched-for-3.19.patch1.txt +++ /dev/null @@ -1,6966 +0,0 @@ -From 5bfaaa91a51940efaccb66bc5cd562ba3b9d4053 Mon Sep 17 00:00:00 2001 -From: Paolo Valente -Date: Thu, 9 May 2013 19:10:02 +0200 -Subject: [PATCH 2/3] block: introduce the BFQ-v7r7 I/O sched for 3.19 - -Add the BFQ-v7r7 I/O scheduler to 3.19. -The general structure is borrowed from CFQ, as much of the code for -handling I/O contexts. Over time, several useful features have been -ported from CFQ as well (details in the changelog in README.BFQ). A -(bfq_)queue is associated to each task doing I/O on a device, and each -time a scheduling decision has to be made a queue is selected and served -until it expires. - - - Slices are given in the service domain: tasks are assigned - budgets, measured in number of sectors. Once got the disk, a task - must however consume its assigned budget within a configurable - maximum time (by default, the maximum possible value of the - budgets is automatically computed to comply with this timeout). - This allows the desired latency vs "throughput boosting" tradeoff - to be set. - - - Budgets are scheduled according to a variant of WF2Q+, implemented - using an augmented rb-tree to take eligibility into account while - preserving an O(log N) overall complexity. - - - A low-latency tunable is provided; if enabled, both interactive - and soft real-time applications are guaranteed a very low latency. - - - Latency guarantees are preserved also in the presence of NCQ. - - - Also with flash-based devices, a high throughput is achieved - while still preserving latency guarantees. - - - BFQ features Early Queue Merge (EQM), a sort of fusion of the - cooperating-queue-merging and the preemption mechanisms present - in CFQ. EQM is in fact a unified mechanism that tries to get a - sequential read pattern, and hence a high throughput, with any - set of processes performing interleaved I/O over a contiguous - sequence of sectors. - - - BFQ supports full hierarchical scheduling, exporting a cgroups - interface. Since each node has a full scheduler, each group can - be assigned its own weight. - - - If the cgroups interface is not used, only I/O priorities can be - assigned to processes, with ioprio values mapped to weights - with the relation weight = IOPRIO_BE_NR - ioprio. - - - ioprio classes are served in strict priority order, i.e., lower - priority queues are not served as long as there are higher - priority queues. Among queues in the same class the bandwidth is - distributed in proportion to the weight of each queue. A very - thin extra bandwidth is however guaranteed to the Idle class, to - prevent it from starving. - -Signed-off-by: Paolo Valente -Signed-off-by: Arianna Avanzini ---- - block/bfq-cgroup.c | 936 ++++++++++++ - block/bfq-ioc.c | 36 + - block/bfq-iosched.c | 3902 +++++++++++++++++++++++++++++++++++++++++++++++++++ - block/bfq-sched.c | 1214 ++++++++++++++++ - block/bfq.h | 775 ++++++++++ - 5 files changed, 6863 insertions(+) - create mode 100644 block/bfq-cgroup.c - create mode 100644 block/bfq-ioc.c - create mode 100644 block/bfq-iosched.c - create mode 100644 block/bfq-sched.c - create mode 100644 block/bfq.h - -diff --git a/block/bfq-cgroup.c b/block/bfq-cgroup.c -new file mode 100644 -index 0000000..11e2f1d ---- /dev/null -+++ b/block/bfq-cgroup.c -@@ -0,0 +1,936 @@ -+/* -+ * BFQ: CGROUPS support. -+ * -+ * Based on ideas and code from CFQ: -+ * Copyright (C) 2003 Jens Axboe -+ * -+ * Copyright (C) 2008 Fabio Checconi -+ * Paolo Valente -+ * -+ * Copyright (C) 2010 Paolo Valente -+ * -+ * Licensed under the GPL-2 as detailed in the accompanying COPYING.BFQ -+ * file. -+ */ -+ -+#ifdef CONFIG_CGROUP_BFQIO -+ -+static DEFINE_MUTEX(bfqio_mutex); -+ -+static bool bfqio_is_removed(struct bfqio_cgroup *bgrp) -+{ -+ return bgrp ? !bgrp->online : false; -+} -+ -+static struct bfqio_cgroup bfqio_root_cgroup = { -+ .weight = BFQ_DEFAULT_GRP_WEIGHT, -+ .ioprio = BFQ_DEFAULT_GRP_IOPRIO, -+ .ioprio_class = BFQ_DEFAULT_GRP_CLASS, -+}; -+ -+static inline void bfq_init_entity(struct bfq_entity *entity, -+ struct bfq_group *bfqg) -+{ -+ entity->weight = entity->new_weight; -+ entity->orig_weight = entity->new_weight; -+ entity->ioprio = entity->new_ioprio; -+ entity->ioprio_class = entity->new_ioprio_class; -+ entity->parent = bfqg->my_entity; -+ entity->sched_data = &bfqg->sched_data; -+} -+ -+static struct bfqio_cgroup *css_to_bfqio(struct cgroup_subsys_state *css) -+{ -+ return css ? container_of(css, struct bfqio_cgroup, css) : NULL; -+} -+ -+/* -+ * Search the bfq_group for bfqd into the hash table (by now only a list) -+ * of bgrp. Must be called under rcu_read_lock(). -+ */ -+static struct bfq_group *bfqio_lookup_group(struct bfqio_cgroup *bgrp, -+ struct bfq_data *bfqd) -+{ -+ struct bfq_group *bfqg; -+ void *key; -+ -+ hlist_for_each_entry_rcu(bfqg, &bgrp->group_data, group_node) { -+ key = rcu_dereference(bfqg->bfqd); -+ if (key == bfqd) -+ return bfqg; -+ } -+ -+ return NULL; -+} -+ -+static inline void bfq_group_init_entity(struct bfqio_cgroup *bgrp, -+ struct bfq_group *bfqg) -+{ -+ struct bfq_entity *entity = &bfqg->entity; -+ -+ /* -+ * If the weight of the entity has never been set via the sysfs -+ * interface, then bgrp->weight == 0. In this case we initialize -+ * the weight from the current ioprio value. Otherwise, the group -+ * weight, if set, has priority over the ioprio value. -+ */ -+ if (bgrp->weight == 0) { -+ entity->new_weight = bfq_ioprio_to_weight(bgrp->ioprio); -+ entity->new_ioprio = bgrp->ioprio; -+ } else { -+ if (bgrp->weight < BFQ_MIN_WEIGHT || -+ bgrp->weight > BFQ_MAX_WEIGHT) { -+ printk(KERN_CRIT "bfq_group_init_entity: " -+ "bgrp->weight %d\n", bgrp->weight); -+ BUG(); -+ } -+ entity->new_weight = bgrp->weight; -+ entity->new_ioprio = bfq_weight_to_ioprio(bgrp->weight); -+ } -+ entity->orig_weight = entity->weight = entity->new_weight; -+ entity->ioprio = entity->new_ioprio; -+ entity->ioprio_class = entity->new_ioprio_class = bgrp->ioprio_class; -+ entity->my_sched_data = &bfqg->sched_data; -+ bfqg->active_entities = 0; -+} -+ -+static inline void bfq_group_set_parent(struct bfq_group *bfqg, -+ struct bfq_group *parent) -+{ -+ struct bfq_entity *entity; -+ -+ BUG_ON(parent == NULL); -+ BUG_ON(bfqg == NULL); -+ -+ entity = &bfqg->entity; -+ entity->parent = parent->my_entity; -+ entity->sched_data = &parent->sched_data; -+} -+ -+/** -+ * bfq_group_chain_alloc - allocate a chain of groups. -+ * @bfqd: queue descriptor. -+ * @css: the leaf cgroup_subsys_state this chain starts from. -+ * -+ * Allocate a chain of groups starting from the one belonging to -+ * @cgroup up to the root cgroup. Stop if a cgroup on the chain -+ * to the root has already an allocated group on @bfqd. -+ */ -+static struct bfq_group *bfq_group_chain_alloc(struct bfq_data *bfqd, -+ struct cgroup_subsys_state *css) -+{ -+ struct bfqio_cgroup *bgrp; -+ struct bfq_group *bfqg, *prev = NULL, *leaf = NULL; -+ -+ for (; css != NULL; css = css->parent) { -+ bgrp = css_to_bfqio(css); -+ -+ bfqg = bfqio_lookup_group(bgrp, bfqd); -+ if (bfqg != NULL) { -+ /* -+ * All the cgroups in the path from there to the -+ * root must have a bfq_group for bfqd, so we don't -+ * need any more allocations. -+ */ -+ break; -+ } -+ -+ bfqg = kzalloc(sizeof(*bfqg), GFP_ATOMIC); -+ if (bfqg == NULL) -+ goto cleanup; -+ -+ bfq_group_init_entity(bgrp, bfqg); -+ bfqg->my_entity = &bfqg->entity; -+ -+ if (leaf == NULL) { -+ leaf = bfqg; -+ prev = leaf; -+ } else { -+ bfq_group_set_parent(prev, bfqg); -+ /* -+ * Build a list of allocated nodes using the bfqd -+ * filed, that is still unused and will be -+ * initialized only after the node will be -+ * connected. -+ */ -+ prev->bfqd = bfqg; -+ prev = bfqg; -+ } -+ } -+ -+ return leaf; -+ -+cleanup: -+ while (leaf != NULL) { -+ prev = leaf; -+ leaf = leaf->bfqd; -+ kfree(prev); -+ } -+ -+ return NULL; -+} -+ -+/** -+ * bfq_group_chain_link - link an allocated group chain to a cgroup -+ * hierarchy. -+ * @bfqd: the queue descriptor. -+ * @css: the leaf cgroup_subsys_state to start from. -+ * @leaf: the leaf group (to be associated to @cgroup). -+ * -+ * Try to link a chain of groups to a cgroup hierarchy, connecting the -+ * nodes bottom-up, so we can be sure that when we find a cgroup in the -+ * hierarchy that already as a group associated to @bfqd all the nodes -+ * in the path to the root cgroup have one too. -+ * -+ * On locking: the queue lock protects the hierarchy (there is a hierarchy -+ * per device) while the bfqio_cgroup lock protects the list of groups -+ * belonging to the same cgroup. -+ */ -+static void bfq_group_chain_link(struct bfq_data *bfqd, -+ struct cgroup_subsys_state *css, -+ struct bfq_group *leaf) -+{ -+ struct bfqio_cgroup *bgrp; -+ struct bfq_group *bfqg, *next, *prev = NULL; -+ unsigned long flags; -+ -+ assert_spin_locked(bfqd->queue->queue_lock); -+ -+ for (; css != NULL && leaf != NULL; css = css->parent) { -+ bgrp = css_to_bfqio(css); -+ next = leaf->bfqd; -+ -+ bfqg = bfqio_lookup_group(bgrp, bfqd); -+ BUG_ON(bfqg != NULL); -+ -+ spin_lock_irqsave(&bgrp->lock, flags); -+ -+ rcu_assign_pointer(leaf->bfqd, bfqd); -+ hlist_add_head_rcu(&leaf->group_node, &bgrp->group_data); -+ hlist_add_head(&leaf->bfqd_node, &bfqd->group_list); -+ -+ spin_unlock_irqrestore(&bgrp->lock, flags); -+ -+ prev = leaf; -+ leaf = next; -+ } -+ -+ BUG_ON(css == NULL && leaf != NULL); -+ if (css != NULL && prev != NULL) { -+ bgrp = css_to_bfqio(css); -+ bfqg = bfqio_lookup_group(bgrp, bfqd); -+ bfq_group_set_parent(prev, bfqg); -+ } -+} -+ -+/** -+ * bfq_find_alloc_group - return the group associated to @bfqd in @cgroup. -+ * @bfqd: queue descriptor. -+ * @cgroup: cgroup being searched for. -+ * -+ * Return a group associated to @bfqd in @cgroup, allocating one if -+ * necessary. When a group is returned all the cgroups in the path -+ * to the root have a group associated to @bfqd. -+ * -+ * If the allocation fails, return the root group: this breaks guarantees -+ * but is a safe fallback. If this loss becomes a problem it can be -+ * mitigated using the equivalent weight (given by the product of the -+ * weights of the groups in the path from @group to the root) in the -+ * root scheduler. -+ * -+ * We allocate all the missing nodes in the path from the leaf cgroup -+ * to the root and we connect the nodes only after all the allocations -+ * have been successful. -+ */ -+static struct bfq_group *bfq_find_alloc_group(struct bfq_data *bfqd, -+ struct cgroup_subsys_state *css) -+{ -+ struct bfqio_cgroup *bgrp = css_to_bfqio(css); -+ struct bfq_group *bfqg; -+ -+ bfqg = bfqio_lookup_group(bgrp, bfqd); -+ if (bfqg != NULL) -+ return bfqg; -+ -+ bfqg = bfq_group_chain_alloc(bfqd, css); -+ if (bfqg != NULL) -+ bfq_group_chain_link(bfqd, css, bfqg); -+ else -+ bfqg = bfqd->root_group; -+ -+ return bfqg; -+} -+ -+/** -+ * bfq_bfqq_move - migrate @bfqq to @bfqg. -+ * @bfqd: queue descriptor. -+ * @bfqq: the queue to move. -+ * @entity: @bfqq's entity. -+ * @bfqg: the group to move to. -+ * -+ * Move @bfqq to @bfqg, deactivating it from its old group and reactivating -+ * it on the new one. Avoid putting the entity on the old group idle tree. -+ * -+ * Must be called under the queue lock; the cgroup owning @bfqg must -+ * not disappear (by now this just means that we are called under -+ * rcu_read_lock()). -+ */ -+static void bfq_bfqq_move(struct bfq_data *bfqd, struct bfq_queue *bfqq, -+ struct bfq_entity *entity, struct bfq_group *bfqg) -+{ -+ int busy, resume; -+ -+ busy = bfq_bfqq_busy(bfqq); -+ resume = !RB_EMPTY_ROOT(&bfqq->sort_list); -+ -+ BUG_ON(resume && !entity->on_st); -+ BUG_ON(busy && !resume && entity->on_st && -+ bfqq != bfqd->in_service_queue); -+ -+ if (busy) { -+ BUG_ON(atomic_read(&bfqq->ref) < 2); -+ -+ if (!resume) -+ bfq_del_bfqq_busy(bfqd, bfqq, 0); -+ else -+ bfq_deactivate_bfqq(bfqd, bfqq, 0); -+ } else if (entity->on_st) -+ bfq_put_idle_entity(bfq_entity_service_tree(entity), entity); -+ -+ /* -+ * Here we use a reference to bfqg. We don't need a refcounter -+ * as the cgroup reference will not be dropped, so that its -+ * destroy() callback will not be invoked. -+ */ -+ entity->parent = bfqg->my_entity; -+ entity->sched_data = &bfqg->sched_data; -+ -+ if (busy && resume) -+ bfq_activate_bfqq(bfqd, bfqq); -+ -+ if (bfqd->in_service_queue == NULL && !bfqd->rq_in_driver) -+ bfq_schedule_dispatch(bfqd); -+} -+ -+/** -+ * __bfq_bic_change_cgroup - move @bic to @cgroup. -+ * @bfqd: the queue descriptor. -+ * @bic: the bic to move. -+ * @cgroup: the cgroup to move to. -+ * -+ * Move bic to cgroup, assuming that bfqd->queue is locked; the caller -+ * has to make sure that the reference to cgroup is valid across the call. -+ * -+ * NOTE: an alternative approach might have been to store the current -+ * cgroup in bfqq and getting a reference to it, reducing the lookup -+ * time here, at the price of slightly more complex code. -+ */ -+static struct bfq_group *__bfq_bic_change_cgroup(struct bfq_data *bfqd, -+ struct bfq_io_cq *bic, -+ struct cgroup_subsys_state *css) -+{ -+ struct bfq_queue *async_bfqq = bic_to_bfqq(bic, 0); -+ struct bfq_queue *sync_bfqq = bic_to_bfqq(bic, 1); -+ struct bfq_entity *entity; -+ struct bfq_group *bfqg; -+ struct bfqio_cgroup *bgrp; -+ -+ bgrp = css_to_bfqio(css); -+ -+ bfqg = bfq_find_alloc_group(bfqd, css); -+ if (async_bfqq != NULL) { -+ entity = &async_bfqq->entity; -+ -+ if (entity->sched_data != &bfqg->sched_data) { -+ bic_set_bfqq(bic, NULL, 0); -+ bfq_log_bfqq(bfqd, async_bfqq, -+ "bic_change_group: %p %d", -+ async_bfqq, atomic_read(&async_bfqq->ref)); -+ bfq_put_queue(async_bfqq); -+ } -+ } -+ -+ if (sync_bfqq != NULL) { -+ entity = &sync_bfqq->entity; -+ if (entity->sched_data != &bfqg->sched_data) -+ bfq_bfqq_move(bfqd, sync_bfqq, entity, bfqg); -+ } -+ -+ return bfqg; -+} -+ -+/** -+ * bfq_bic_change_cgroup - move @bic to @cgroup. -+ * @bic: the bic being migrated. -+ * @cgroup: the destination cgroup. -+ * -+ * When the task owning @bic is moved to @cgroup, @bic is immediately -+ * moved into its new parent group. -+ */ -+static void bfq_bic_change_cgroup(struct bfq_io_cq *bic, -+ struct cgroup_subsys_state *css) -+{ -+ struct bfq_data *bfqd; -+ unsigned long uninitialized_var(flags); -+ -+ bfqd = bfq_get_bfqd_locked(&(bic->icq.q->elevator->elevator_data), -+ &flags); -+ if (bfqd != NULL) { -+ __bfq_bic_change_cgroup(bfqd, bic, css); -+ bfq_put_bfqd_unlock(bfqd, &flags); -+ } -+} -+ -+/** -+ * bfq_bic_update_cgroup - update the cgroup of @bic. -+ * @bic: the @bic to update. -+ * -+ * Make sure that @bic is enqueued in the cgroup of the current task. -+ * We need this in addition to moving bics during the cgroup attach -+ * phase because the task owning @bic could be at its first disk -+ * access or we may end up in the root cgroup as the result of a -+ * memory allocation failure and here we try to move to the right -+ * group. -+ * -+ * Must be called under the queue lock. It is safe to use the returned -+ * value even after the rcu_read_unlock() as the migration/destruction -+ * paths act under the queue lock too. IOW it is impossible to race with -+ * group migration/destruction and end up with an invalid group as: -+ * a) here cgroup has not yet been destroyed, nor its destroy callback -+ * has started execution, as current holds a reference to it, -+ * b) if it is destroyed after rcu_read_unlock() [after current is -+ * migrated to a different cgroup] its attach() callback will have -+ * taken care of remove all the references to the old cgroup data. -+ */ -+static struct bfq_group *bfq_bic_update_cgroup(struct bfq_io_cq *bic) -+{ -+ struct bfq_data *bfqd = bic_to_bfqd(bic); -+ struct bfq_group *bfqg; -+ struct cgroup_subsys_state *css; -+ -+ BUG_ON(bfqd == NULL); -+ -+ rcu_read_lock(); -+ css = task_css(current, bfqio_cgrp_id); -+ bfqg = __bfq_bic_change_cgroup(bfqd, bic, css); -+ rcu_read_unlock(); -+ -+ return bfqg; -+} -+ -+/** -+ * bfq_flush_idle_tree - deactivate any entity on the idle tree of @st. -+ * @st: the service tree being flushed. -+ */ -+static inline void bfq_flush_idle_tree(struct bfq_service_tree *st) -+{ -+ struct bfq_entity *entity = st->first_idle; -+ -+ for (; entity != NULL; entity = st->first_idle) -+ __bfq_deactivate_entity(entity, 0); -+} -+ -+/** -+ * bfq_reparent_leaf_entity - move leaf entity to the root_group. -+ * @bfqd: the device data structure with the root group. -+ * @entity: the entity to move. -+ */ -+static inline void bfq_reparent_leaf_entity(struct bfq_data *bfqd, -+ struct bfq_entity *entity) -+{ -+ struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); -+ -+ BUG_ON(bfqq == NULL); -+ bfq_bfqq_move(bfqd, bfqq, entity, bfqd->root_group); -+ return; -+} -+ -+/** -+ * bfq_reparent_active_entities - move to the root group all active -+ * entities. -+ * @bfqd: the device data structure with the root group. -+ * @bfqg: the group to move from. -+ * @st: the service tree with the entities. -+ * -+ * Needs queue_lock to be taken and reference to be valid over the call. -+ */ -+static inline void bfq_reparent_active_entities(struct bfq_data *bfqd, -+ struct bfq_group *bfqg, -+ struct bfq_service_tree *st) -+{ -+ struct rb_root *active = &st->active; -+ struct bfq_entity *entity = NULL; -+ -+ if (!RB_EMPTY_ROOT(&st->active)) -+ entity = bfq_entity_of(rb_first(active)); -+ -+ for (; entity != NULL; entity = bfq_entity_of(rb_first(active))) -+ bfq_reparent_leaf_entity(bfqd, entity); -+ -+ if (bfqg->sched_data.in_service_entity != NULL) -+ bfq_reparent_leaf_entity(bfqd, -+ bfqg->sched_data.in_service_entity); -+ -+ return; -+} -+ -+/** -+ * bfq_destroy_group - destroy @bfqg. -+ * @bgrp: the bfqio_cgroup containing @bfqg. -+ * @bfqg: the group being destroyed. -+ * -+ * Destroy @bfqg, making sure that it is not referenced from its parent. -+ */ -+static void bfq_destroy_group(struct bfqio_cgroup *bgrp, struct bfq_group *bfqg) -+{ -+ struct bfq_data *bfqd; -+ struct bfq_service_tree *st; -+ struct bfq_entity *entity = bfqg->my_entity; -+ unsigned long uninitialized_var(flags); -+ int i; -+ -+ hlist_del(&bfqg->group_node); -+ -+ /* -+ * Empty all service_trees belonging to this group before -+ * deactivating the group itself. -+ */ -+ for (i = 0; i < BFQ_IOPRIO_CLASSES; i++) { -+ st = bfqg->sched_data.service_tree + i; -+ -+ /* -+ * The idle tree may still contain bfq_queues belonging -+ * to exited task because they never migrated to a different -+ * cgroup from the one being destroyed now. No one else -+ * can access them so it's safe to act without any lock. -+ */ -+ bfq_flush_idle_tree(st); -+ -+ /* -+ * It may happen that some queues are still active -+ * (busy) upon group destruction (if the corresponding -+ * processes have been forced to terminate). We move -+ * all the leaf entities corresponding to these queues -+ * to the root_group. -+ * Also, it may happen that the group has an entity -+ * in service, which is disconnected from the active -+ * tree: it must be moved, too. -+ * There is no need to put the sync queues, as the -+ * scheduler has taken no reference. -+ */ -+ bfqd = bfq_get_bfqd_locked(&bfqg->bfqd, &flags); -+ if (bfqd != NULL) { -+ bfq_reparent_active_entities(bfqd, bfqg, st); -+ bfq_put_bfqd_unlock(bfqd, &flags); -+ } -+ BUG_ON(!RB_EMPTY_ROOT(&st->active)); -+ BUG_ON(!RB_EMPTY_ROOT(&st->idle)); -+ } -+ BUG_ON(bfqg->sched_data.next_in_service != NULL); -+ BUG_ON(bfqg->sched_data.in_service_entity != NULL); -+ -+ /* -+ * We may race with device destruction, take extra care when -+ * dereferencing bfqg->bfqd. -+ */ -+ bfqd = bfq_get_bfqd_locked(&bfqg->bfqd, &flags); -+ if (bfqd != NULL) { -+ hlist_del(&bfqg->bfqd_node); -+ __bfq_deactivate_entity(entity, 0); -+ bfq_put_async_queues(bfqd, bfqg); -+ bfq_put_bfqd_unlock(bfqd, &flags); -+ } -+ BUG_ON(entity->tree != NULL); -+ -+ /* -+ * No need to defer the kfree() to the end of the RCU grace -+ * period: we are called from the destroy() callback of our -+ * cgroup, so we can be sure that no one is a) still using -+ * this cgroup or b) doing lookups in it. -+ */ -+ kfree(bfqg); -+} -+ -+static void bfq_end_wr_async(struct bfq_data *bfqd) -+{ -+ struct hlist_node *tmp; -+ struct bfq_group *bfqg; -+ -+ hlist_for_each_entry_safe(bfqg, tmp, &bfqd->group_list, bfqd_node) -+ bfq_end_wr_async_queues(bfqd, bfqg); -+ bfq_end_wr_async_queues(bfqd, bfqd->root_group); -+} -+ -+/** -+ * bfq_disconnect_groups - disconnect @bfqd from all its groups. -+ * @bfqd: the device descriptor being exited. -+ * -+ * When the device exits we just make sure that no lookup can return -+ * the now unused group structures. They will be deallocated on cgroup -+ * destruction. -+ */ -+static void bfq_disconnect_groups(struct bfq_data *bfqd) -+{ -+ struct hlist_node *tmp; -+ struct bfq_group *bfqg; -+ -+ bfq_log(bfqd, "disconnect_groups beginning"); -+ hlist_for_each_entry_safe(bfqg, tmp, &bfqd->group_list, bfqd_node) { -+ hlist_del(&bfqg->bfqd_node); -+ -+ __bfq_deactivate_entity(bfqg->my_entity, 0); -+ -+ /* -+ * Don't remove from the group hash, just set an -+ * invalid key. No lookups can race with the -+ * assignment as bfqd is being destroyed; this -+ * implies also that new elements cannot be added -+ * to the list. -+ */ -+ rcu_assign_pointer(bfqg->bfqd, NULL); -+ -+ bfq_log(bfqd, "disconnect_groups: put async for group %p", -+ bfqg); -+ bfq_put_async_queues(bfqd, bfqg); -+ } -+} -+ -+static inline void bfq_free_root_group(struct bfq_data *bfqd) -+{ -+ struct bfqio_cgroup *bgrp = &bfqio_root_cgroup; -+ struct bfq_group *bfqg = bfqd->root_group; -+ -+ bfq_put_async_queues(bfqd, bfqg); -+ -+ spin_lock_irq(&bgrp->lock); -+ hlist_del_rcu(&bfqg->group_node); -+ spin_unlock_irq(&bgrp->lock); -+ -+ /* -+ * No need to synchronize_rcu() here: since the device is gone -+ * there cannot be any read-side access to its root_group. -+ */ -+ kfree(bfqg); -+} -+ -+static struct bfq_group *bfq_alloc_root_group(struct bfq_data *bfqd, int node) -+{ -+ struct bfq_group *bfqg; -+ struct bfqio_cgroup *bgrp; -+ int i; -+ -+ bfqg = kzalloc_node(sizeof(*bfqg), GFP_KERNEL, node); -+ if (bfqg == NULL) -+ return NULL; -+ -+ bfqg->entity.parent = NULL; -+ for (i = 0; i < BFQ_IOPRIO_CLASSES; i++) -+ bfqg->sched_data.service_tree[i] = BFQ_SERVICE_TREE_INIT; -+ -+ bgrp = &bfqio_root_cgroup; -+ spin_lock_irq(&bgrp->lock); -+ rcu_assign_pointer(bfqg->bfqd, bfqd); -+ hlist_add_head_rcu(&bfqg->group_node, &bgrp->group_data); -+ spin_unlock_irq(&bgrp->lock); -+ -+ return bfqg; -+} -+ -+#define SHOW_FUNCTION(__VAR) \ -+static u64 bfqio_cgroup_##__VAR##_read(struct cgroup_subsys_state *css, \ -+ struct cftype *cftype) \ -+{ \ -+ struct bfqio_cgroup *bgrp = css_to_bfqio(css); \ -+ u64 ret = -ENODEV; \ -+ \ -+ mutex_lock(&bfqio_mutex); \ -+ if (bfqio_is_removed(bgrp)) \ -+ goto out_unlock; \ -+ \ -+ spin_lock_irq(&bgrp->lock); \ -+ ret = bgrp->__VAR; \ -+ spin_unlock_irq(&bgrp->lock); \ -+ \ -+out_unlock: \ -+ mutex_unlock(&bfqio_mutex); \ -+ return ret; \ -+} -+ -+SHOW_FUNCTION(weight); -+SHOW_FUNCTION(ioprio); -+SHOW_FUNCTION(ioprio_class); -+#undef SHOW_FUNCTION -+ -+#define STORE_FUNCTION(__VAR, __MIN, __MAX) \ -+static int bfqio_cgroup_##__VAR##_write(struct cgroup_subsys_state *css,\ -+ struct cftype *cftype, \ -+ u64 val) \ -+{ \ -+ struct bfqio_cgroup *bgrp = css_to_bfqio(css); \ -+ struct bfq_group *bfqg; \ -+ int ret = -EINVAL; \ -+ \ -+ if (val < (__MIN) || val > (__MAX)) \ -+ return ret; \ -+ \ -+ ret = -ENODEV; \ -+ mutex_lock(&bfqio_mutex); \ -+ if (bfqio_is_removed(bgrp)) \ -+ goto out_unlock; \ -+ ret = 0; \ -+ \ -+ spin_lock_irq(&bgrp->lock); \ -+ bgrp->__VAR = (unsigned short)val; \ -+ hlist_for_each_entry(bfqg, &bgrp->group_data, group_node) { \ -+ /* \ -+ * Setting the ioprio_changed flag of the entity \ -+ * to 1 with new_##__VAR == ##__VAR would re-set \ -+ * the value of the weight to its ioprio mapping. \ -+ * Set the flag only if necessary. \ -+ */ \ -+ if ((unsigned short)val != bfqg->entity.new_##__VAR) { \ -+ bfqg->entity.new_##__VAR = (unsigned short)val; \ -+ /* \ -+ * Make sure that the above new value has been \ -+ * stored in bfqg->entity.new_##__VAR before \ -+ * setting the ioprio_changed flag. In fact, \ -+ * this flag may be read asynchronously (in \ -+ * critical sections protected by a different \ -+ * lock than that held here), and finding this \ -+ * flag set may cause the execution of the code \ -+ * for updating parameters whose value may \ -+ * depend also on bfqg->entity.new_##__VAR (in \ -+ * __bfq_entity_update_weight_prio). \ -+ * This barrier makes sure that the new value \ -+ * of bfqg->entity.new_##__VAR is correctly \ -+ * seen in that code. \ -+ */ \ -+ smp_wmb(); \ -+ bfqg->entity.ioprio_changed = 1; \ -+ } \ -+ } \ -+ spin_unlock_irq(&bgrp->lock); \ -+ \ -+out_unlock: \ -+ mutex_unlock(&bfqio_mutex); \ -+ return ret; \ -+} -+ -+STORE_FUNCTION(weight, BFQ_MIN_WEIGHT, BFQ_MAX_WEIGHT); -+STORE_FUNCTION(ioprio, 0, IOPRIO_BE_NR - 1); -+STORE_FUNCTION(ioprio_class, IOPRIO_CLASS_RT, IOPRIO_CLASS_IDLE); -+#undef STORE_FUNCTION -+ -+static struct cftype bfqio_files[] = { -+ { -+ .name = "weight", -+ .read_u64 = bfqio_cgroup_weight_read, -+ .write_u64 = bfqio_cgroup_weight_write, -+ }, -+ { -+ .name = "ioprio", -+ .read_u64 = bfqio_cgroup_ioprio_read, -+ .write_u64 = bfqio_cgroup_ioprio_write, -+ }, -+ { -+ .name = "ioprio_class", -+ .read_u64 = bfqio_cgroup_ioprio_class_read, -+ .write_u64 = bfqio_cgroup_ioprio_class_write, -+ }, -+ { }, /* terminate */ -+}; -+ -+static struct cgroup_subsys_state *bfqio_create(struct cgroup_subsys_state -+ *parent_css) -+{ -+ struct bfqio_cgroup *bgrp; -+ -+ if (parent_css != NULL) { -+ bgrp = kzalloc(sizeof(*bgrp), GFP_KERNEL); -+ if (bgrp == NULL) -+ return ERR_PTR(-ENOMEM); -+ } else -+ bgrp = &bfqio_root_cgroup; -+ -+ spin_lock_init(&bgrp->lock); -+ INIT_HLIST_HEAD(&bgrp->group_data); -+ bgrp->ioprio = BFQ_DEFAULT_GRP_IOPRIO; -+ bgrp->ioprio_class = BFQ_DEFAULT_GRP_CLASS; -+ -+ return &bgrp->css; -+} -+ -+/* -+ * We cannot support shared io contexts, as we have no means to support -+ * two tasks with the same ioc in two different groups without major rework -+ * of the main bic/bfqq data structures. By now we allow a task to change -+ * its cgroup only if it's the only owner of its ioc; the drawback of this -+ * behavior is that a group containing a task that forked using CLONE_IO -+ * will not be destroyed until the tasks sharing the ioc die. -+ */ -+static int bfqio_can_attach(struct cgroup_subsys_state *css, -+ struct cgroup_taskset *tset) -+{ -+ struct task_struct *task; -+ struct io_context *ioc; -+ int ret = 0; -+ -+ cgroup_taskset_for_each(task, tset) { -+ /* -+ * task_lock() is needed to avoid races with -+ * exit_io_context() -+ */ -+ task_lock(task); -+ ioc = task->io_context; -+ if (ioc != NULL && atomic_read(&ioc->nr_tasks) > 1) -+ /* -+ * ioc == NULL means that the task is either too -+ * young or exiting: if it has still no ioc the -+ * ioc can't be shared, if the task is exiting the -+ * attach will fail anyway, no matter what we -+ * return here. -+ */ -+ ret = -EINVAL; -+ task_unlock(task); -+ if (ret) -+ break; -+ } -+ -+ return ret; -+} -+ -+static void bfqio_attach(struct cgroup_subsys_state *css, -+ struct cgroup_taskset *tset) -+{ -+ struct task_struct *task; -+ struct io_context *ioc; -+ struct io_cq *icq; -+ -+ /* -+ * IMPORTANT NOTE: The move of more than one process at a time to a -+ * new group has not yet been tested. -+ */ -+ cgroup_taskset_for_each(task, tset) { -+ ioc = get_task_io_context(task, GFP_ATOMIC, NUMA_NO_NODE); -+ if (ioc) { -+ /* -+ * Handle cgroup change here. -+ */ -+ rcu_read_lock(); -+ hlist_for_each_entry_rcu(icq, &ioc->icq_list, ioc_node) -+ if (!strncmp( -+ icq->q->elevator->type->elevator_name, -+ "bfq", ELV_NAME_MAX)) -+ bfq_bic_change_cgroup(icq_to_bic(icq), -+ css); -+ rcu_read_unlock(); -+ put_io_context(ioc); -+ } -+ } -+} -+ -+static void bfqio_destroy(struct cgroup_subsys_state *css) -+{ -+ struct bfqio_cgroup *bgrp = css_to_bfqio(css); -+ struct hlist_node *tmp; -+ struct bfq_group *bfqg; -+ -+ /* -+ * Since we are destroying the cgroup, there are no more tasks -+ * referencing it, and all the RCU grace periods that may have -+ * referenced it are ended (as the destruction of the parent -+ * cgroup is RCU-safe); bgrp->group_data will not be accessed by -+ * anything else and we don't need any synchronization. -+ */ -+ hlist_for_each_entry_safe(bfqg, tmp, &bgrp->group_data, group_node) -+ bfq_destroy_group(bgrp, bfqg); -+ -+ BUG_ON(!hlist_empty(&bgrp->group_data)); -+ -+ kfree(bgrp); -+} -+ -+static int bfqio_css_online(struct cgroup_subsys_state *css) -+{ -+ struct bfqio_cgroup *bgrp = css_to_bfqio(css); -+ -+ mutex_lock(&bfqio_mutex); -+ bgrp->online = true; -+ mutex_unlock(&bfqio_mutex); -+ -+ return 0; -+} -+ -+static void bfqio_css_offline(struct cgroup_subsys_state *css) -+{ -+ struct bfqio_cgroup *bgrp = css_to_bfqio(css); -+ -+ mutex_lock(&bfqio_mutex); -+ bgrp->online = false; -+ mutex_unlock(&bfqio_mutex); -+} -+ -+struct cgroup_subsys bfqio_cgrp_subsys = { -+ .css_alloc = bfqio_create, -+ .css_online = bfqio_css_online, -+ .css_offline = bfqio_css_offline, -+ .can_attach = bfqio_can_attach, -+ .attach = bfqio_attach, -+ .css_free = bfqio_destroy, -+ .legacy_cftypes = bfqio_files, -+}; -+#else -+static inline void bfq_init_entity(struct bfq_entity *entity, -+ struct bfq_group *bfqg) -+{ -+ entity->weight = entity->new_weight; -+ entity->orig_weight = entity->new_weight; -+ entity->ioprio = entity->new_ioprio; -+ entity->ioprio_class = entity->new_ioprio_class; -+ entity->sched_data = &bfqg->sched_data; -+} -+ -+static inline struct bfq_group * -+bfq_bic_update_cgroup(struct bfq_io_cq *bic) -+{ -+ struct bfq_data *bfqd = bic_to_bfqd(bic); -+ return bfqd->root_group; -+} -+ -+static inline void bfq_bfqq_move(struct bfq_data *bfqd, -+ struct bfq_queue *bfqq, -+ struct bfq_entity *entity, -+ struct bfq_group *bfqg) -+{ -+} -+ -+static void bfq_end_wr_async(struct bfq_data *bfqd) -+{ -+ bfq_end_wr_async_queues(bfqd, bfqd->root_group); -+} -+ -+static inline void bfq_disconnect_groups(struct bfq_data *bfqd) -+{ -+ bfq_put_async_queues(bfqd, bfqd->root_group); -+} -+ -+static inline void bfq_free_root_group(struct bfq_data *bfqd) -+{ -+ kfree(bfqd->root_group); -+} -+ -+static struct bfq_group *bfq_alloc_root_group(struct bfq_data *bfqd, int node) -+{ -+ struct bfq_group *bfqg; -+ int i; -+ -+ bfqg = kmalloc_node(sizeof(*bfqg), GFP_KERNEL | __GFP_ZERO, node); -+ if (bfqg == NULL) -+ return NULL; -+ -+ for (i = 0; i < BFQ_IOPRIO_CLASSES; i++) -+ bfqg->sched_data.service_tree[i] = BFQ_SERVICE_TREE_INIT; -+ -+ return bfqg; -+} -+#endif -diff --git a/block/bfq-ioc.c b/block/bfq-ioc.c -new file mode 100644 -index 0000000..7f6b000 ---- /dev/null -+++ b/block/bfq-ioc.c -@@ -0,0 +1,36 @@ -+/* -+ * BFQ: I/O context handling. -+ * -+ * Based on ideas and code from CFQ: -+ * Copyright (C) 2003 Jens Axboe -+ * -+ * Copyright (C) 2008 Fabio Checconi -+ * Paolo Valente -+ * -+ * Copyright (C) 2010 Paolo Valente -+ */ -+ -+/** -+ * icq_to_bic - convert iocontext queue structure to bfq_io_cq. -+ * @icq: the iocontext queue. -+ */ -+static inline struct bfq_io_cq *icq_to_bic(struct io_cq *icq) -+{ -+ /* bic->icq is the first member, %NULL will convert to %NULL */ -+ return container_of(icq, struct bfq_io_cq, icq); -+} -+ -+/** -+ * bfq_bic_lookup - search into @ioc a bic associated to @bfqd. -+ * @bfqd: the lookup key. -+ * @ioc: the io_context of the process doing I/O. -+ * -+ * Queue lock must be held. -+ */ -+static inline struct bfq_io_cq *bfq_bic_lookup(struct bfq_data *bfqd, -+ struct io_context *ioc) -+{ -+ if (ioc) -+ return icq_to_bic(ioc_lookup_icq(ioc, bfqd->queue)); -+ return NULL; -+} -diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c -new file mode 100644 -index 0000000..97ee934 ---- /dev/null -+++ b/block/bfq-iosched.c -@@ -0,0 +1,3902 @@ -+/* -+ * Budget Fair Queueing (BFQ) disk scheduler. -+ * -+ * Based on ideas and code from CFQ: -+ * Copyright (C) 2003 Jens Axboe -+ * -+ * Copyright (C) 2008 Fabio Checconi -+ * Paolo Valente -+ * -+ * Copyright (C) 2010 Paolo Valente -+ * -+ * Licensed under the GPL-2 as detailed in the accompanying COPYING.BFQ -+ * file. -+ * -+ * BFQ is a proportional-share storage-I/O scheduling algorithm based on -+ * the slice-by-slice service scheme of CFQ. But BFQ assigns budgets, -+ * measured in number of sectors, to processes instead of time slices. The -+ * device is not granted to the in-service process for a given time slice, -+ * but until it has exhausted its assigned budget. This change from the time -+ * to the service domain allows BFQ to distribute the device throughput -+ * among processes as desired, without any distortion due to ZBR, workload -+ * fluctuations or other factors. BFQ uses an ad hoc internal scheduler, -+ * called B-WF2Q+, to schedule processes according to their budgets. More -+ * precisely, BFQ schedules queues associated to processes. Thanks to the -+ * accurate policy of B-WF2Q+, BFQ can afford to assign high budgets to -+ * I/O-bound processes issuing sequential requests (to boost the -+ * throughput), and yet guarantee a low latency to interactive and soft -+ * real-time applications. -+ * -+ * BFQ is described in [1], where also a reference to the initial, more -+ * theoretical paper on BFQ can be found. The interested reader can find -+ * in the latter paper full details on the main algorithm, as well as -+ * formulas of the guarantees and formal proofs of all the properties. -+ * With respect to the version of BFQ presented in these papers, this -+ * implementation adds a few more heuristics, such as the one that -+ * guarantees a low latency to soft real-time applications, and a -+ * hierarchical extension based on H-WF2Q+. -+ * -+ * B-WF2Q+ is based on WF2Q+, that is described in [2], together with -+ * H-WF2Q+, while the augmented tree used to implement B-WF2Q+ with O(log N) -+ * complexity derives from the one introduced with EEVDF in [3]. -+ * -+ * [1] P. Valente and M. Andreolini, ``Improving Application Responsiveness -+ * with the BFQ Disk I/O Scheduler'', -+ * Proceedings of the 5th Annual International Systems and Storage -+ * Conference (SYSTOR '12), June 2012. -+ * -+ * http://algogroup.unimo.it/people/paolo/disk_sched/bf1-v1-suite-results.pdf -+ * -+ * [2] Jon C.R. Bennett and H. Zhang, ``Hierarchical Packet Fair Queueing -+ * Algorithms,'' IEEE/ACM Transactions on Networking, 5(5):675-689, -+ * Oct 1997. -+ * -+ * http://www.cs.cmu.edu/~hzhang/papers/TON-97-Oct.ps.gz -+ * -+ * [3] I. Stoica and H. Abdel-Wahab, ``Earliest Eligible Virtual Deadline -+ * First: A Flexible and Accurate Mechanism for Proportional Share -+ * Resource Allocation,'' technical report. -+ * -+ * http://www.cs.berkeley.edu/~istoica/papers/eevdf-tr-95.pdf -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "bfq.h" -+#include "blk.h" -+ -+/* Max number of dispatches in one round of service. */ -+static const int bfq_quantum = 4; -+ -+/* Expiration time of sync (0) and async (1) requests, in jiffies. */ -+static const int bfq_fifo_expire[2] = { HZ / 4, HZ / 8 }; -+ -+/* Maximum backwards seek, in KiB. */ -+static const int bfq_back_max = 16 * 1024; -+ -+/* Penalty of a backwards seek, in number of sectors. */ -+static const int bfq_back_penalty = 2; -+ -+/* Idling period duration, in jiffies. */ -+static int bfq_slice_idle = HZ / 125; -+ -+/* Default maximum budget values, in sectors and number of requests. */ -+static const int bfq_default_max_budget = 16 * 1024; -+static const int bfq_max_budget_async_rq = 4; -+ -+/* -+ * Async to sync throughput distribution is controlled as follows: -+ * when an async request is served, the entity is charged the number -+ * of sectors of the request, multiplied by the factor below -+ */ -+static const int bfq_async_charge_factor = 10; -+ -+/* Default timeout values, in jiffies, approximating CFQ defaults. */ -+static const int bfq_timeout_sync = HZ / 8; -+static int bfq_timeout_async = HZ / 25; -+ -+struct kmem_cache *bfq_pool; -+ -+/* Below this threshold (in ms), we consider thinktime immediate. */ -+#define BFQ_MIN_TT 2 -+ -+/* hw_tag detection: parallel requests threshold and min samples needed. */ -+#define BFQ_HW_QUEUE_THRESHOLD 4 -+#define BFQ_HW_QUEUE_SAMPLES 32 -+ -+#define BFQQ_SEEK_THR (sector_t)(8 * 1024) -+#define BFQQ_SEEKY(bfqq) ((bfqq)->seek_mean > BFQQ_SEEK_THR) -+ -+/* Min samples used for peak rate estimation (for autotuning). */ -+#define BFQ_PEAK_RATE_SAMPLES 32 -+ -+/* Shift used for peak rate fixed precision calculations. */ -+#define BFQ_RATE_SHIFT 16 -+ -+/* -+ * By default, BFQ computes the duration of the weight raising for -+ * interactive applications automatically, using the following formula: -+ * duration = (R / r) * T, where r is the peak rate of the device, and -+ * R and T are two reference parameters. -+ * In particular, R is the peak rate of the reference device (see below), -+ * and T is a reference time: given the systems that are likely to be -+ * installed on the reference device according to its speed class, T is -+ * about the maximum time needed, under BFQ and while reading two files in -+ * parallel, to load typical large applications on these systems. -+ * In practice, the slower/faster the device at hand is, the more/less it -+ * takes to load applications with respect to the reference device. -+ * Accordingly, the longer/shorter BFQ grants weight raising to interactive -+ * applications. -+ * -+ * BFQ uses four different reference pairs (R, T), depending on: -+ * . whether the device is rotational or non-rotational; -+ * . whether the device is slow, such as old or portable HDDs, as well as -+ * SD cards, or fast, such as newer HDDs and SSDs. -+ * -+ * The device's speed class is dynamically (re)detected in -+ * bfq_update_peak_rate() every time the estimated peak rate is updated. -+ * -+ * In the following definitions, R_slow[0]/R_fast[0] and T_slow[0]/T_fast[0] -+ * are the reference values for a slow/fast rotational device, whereas -+ * R_slow[1]/R_fast[1] and T_slow[1]/T_fast[1] are the reference values for -+ * a slow/fast non-rotational device. Finally, device_speed_thresh are the -+ * thresholds used to switch between speed classes. -+ * Both the reference peak rates and the thresholds are measured in -+ * sectors/usec, left-shifted by BFQ_RATE_SHIFT. -+ */ -+static int R_slow[2] = {1536, 10752}; -+static int R_fast[2] = {17415, 34791}; -+/* -+ * To improve readability, a conversion function is used to initialize the -+ * following arrays, which entails that they can be initialized only in a -+ * function. -+ */ -+static int T_slow[2]; -+static int T_fast[2]; -+static int device_speed_thresh[2]; -+ -+#define BFQ_SERVICE_TREE_INIT ((struct bfq_service_tree) \ -+ { RB_ROOT, RB_ROOT, NULL, NULL, 0, 0 }) -+ -+#define RQ_BIC(rq) ((struct bfq_io_cq *) (rq)->elv.priv[0]) -+#define RQ_BFQQ(rq) ((rq)->elv.priv[1]) -+ -+static inline void bfq_schedule_dispatch(struct bfq_data *bfqd); -+ -+#include "bfq-ioc.c" -+#include "bfq-sched.c" -+#include "bfq-cgroup.c" -+ -+#define bfq_class_idle(bfqq) ((bfqq)->entity.ioprio_class ==\ -+ IOPRIO_CLASS_IDLE) -+#define bfq_class_rt(bfqq) ((bfqq)->entity.ioprio_class ==\ -+ IOPRIO_CLASS_RT) -+ -+#define bfq_sample_valid(samples) ((samples) > 80) -+ -+/* -+ * We regard a request as SYNC, if either it's a read or has the SYNC bit -+ * set (in which case it could also be a direct WRITE). -+ */ -+static inline int bfq_bio_sync(struct bio *bio) -+{ -+ if (bio_data_dir(bio) == READ || (bio->bi_rw & REQ_SYNC)) -+ return 1; -+ -+ return 0; -+} -+ -+/* -+ * Scheduler run of queue, if there are requests pending and no one in the -+ * driver that will restart queueing. -+ */ -+static inline void bfq_schedule_dispatch(struct bfq_data *bfqd) -+{ -+ if (bfqd->queued != 0) { -+ bfq_log(bfqd, "schedule dispatch"); -+ kblockd_schedule_work(&bfqd->unplug_work); -+ } -+} -+ -+/* -+ * Lifted from AS - choose which of rq1 and rq2 that is best served now. -+ * We choose the request that is closesr to the head right now. Distance -+ * behind the head is penalized and only allowed to a certain extent. -+ */ -+static struct request *bfq_choose_req(struct bfq_data *bfqd, -+ struct request *rq1, -+ struct request *rq2, -+ sector_t last) -+{ -+ sector_t s1, s2, d1 = 0, d2 = 0; -+ unsigned long back_max; -+#define BFQ_RQ1_WRAP 0x01 /* request 1 wraps */ -+#define BFQ_RQ2_WRAP 0x02 /* request 2 wraps */ -+ unsigned wrap = 0; /* bit mask: requests behind the disk head? */ -+ -+ if (rq1 == NULL || rq1 == rq2) -+ return rq2; -+ if (rq2 == NULL) -+ return rq1; -+ -+ if (rq_is_sync(rq1) && !rq_is_sync(rq2)) -+ return rq1; -+ else if (rq_is_sync(rq2) && !rq_is_sync(rq1)) -+ return rq2; -+ if ((rq1->cmd_flags & REQ_META) && !(rq2->cmd_flags & REQ_META)) -+ return rq1; -+ else if ((rq2->cmd_flags & REQ_META) && !(rq1->cmd_flags & REQ_META)) -+ return rq2; -+ -+ s1 = blk_rq_pos(rq1); -+ s2 = blk_rq_pos(rq2); -+ -+ /* -+ * By definition, 1KiB is 2 sectors. -+ */ -+ back_max = bfqd->bfq_back_max * 2; -+ -+ /* -+ * Strict one way elevator _except_ in the case where we allow -+ * short backward seeks which are biased as twice the cost of a -+ * similar forward seek. -+ */ -+ if (s1 >= last) -+ d1 = s1 - last; -+ else if (s1 + back_max >= last) -+ d1 = (last - s1) * bfqd->bfq_back_penalty; -+ else -+ wrap |= BFQ_RQ1_WRAP; -+ -+ if (s2 >= last) -+ d2 = s2 - last; -+ else if (s2 + back_max >= last) -+ d2 = (last - s2) * bfqd->bfq_back_penalty; -+ else -+ wrap |= BFQ_RQ2_WRAP; -+ -+ /* Found required data */ -+ -+ /* -+ * By doing switch() on the bit mask "wrap" we avoid having to -+ * check two variables for all permutations: --> faster! -+ */ -+ switch (wrap) { -+ case 0: /* common case for CFQ: rq1 and rq2 not wrapped */ -+ if (d1 < d2) -+ return rq1; -+ else if (d2 < d1) -+ return rq2; -+ else { -+ if (s1 >= s2) -+ return rq1; -+ else -+ return rq2; -+ } -+ -+ case BFQ_RQ2_WRAP: -+ return rq1; -+ case BFQ_RQ1_WRAP: -+ return rq2; -+ case (BFQ_RQ1_WRAP|BFQ_RQ2_WRAP): /* both rqs wrapped */ -+ default: -+ /* -+ * Since both rqs are wrapped, -+ * start with the one that's further behind head -+ * (--> only *one* back seek required), -+ * since back seek takes more time than forward. -+ */ -+ if (s1 <= s2) -+ return rq1; -+ else -+ return rq2; -+ } -+} -+ -+static struct bfq_queue * -+bfq_rq_pos_tree_lookup(struct bfq_data *bfqd, struct rb_root *root, -+ sector_t sector, struct rb_node **ret_parent, -+ struct rb_node ***rb_link) -+{ -+ struct rb_node **p, *parent; -+ struct bfq_queue *bfqq = NULL; -+ -+ parent = NULL; -+ p = &root->rb_node; -+ while (*p) { -+ struct rb_node **n; -+ -+ parent = *p; -+ bfqq = rb_entry(parent, struct bfq_queue, pos_node); -+ -+ /* -+ * Sort strictly based on sector. Smallest to the left, -+ * largest to the right. -+ */ -+ if (sector > blk_rq_pos(bfqq->next_rq)) -+ n = &(*p)->rb_right; -+ else if (sector < blk_rq_pos(bfqq->next_rq)) -+ n = &(*p)->rb_left; -+ else -+ break; -+ p = n; -+ bfqq = NULL; -+ } -+ -+ *ret_parent = parent; -+ if (rb_link) -+ *rb_link = p; -+ -+ bfq_log(bfqd, "rq_pos_tree_lookup %llu: returning %d", -+ (long long unsigned)sector, -+ bfqq != NULL ? bfqq->pid : 0); -+ -+ return bfqq; -+} -+ -+static void bfq_rq_pos_tree_add(struct bfq_data *bfqd, struct bfq_queue *bfqq) -+{ -+ struct rb_node **p, *parent; -+ struct bfq_queue *__bfqq; -+ -+ if (bfqq->pos_root != NULL) { -+ rb_erase(&bfqq->pos_node, bfqq->pos_root); -+ bfqq->pos_root = NULL; -+ } -+ -+ if (bfq_class_idle(bfqq)) -+ return; -+ if (!bfqq->next_rq) -+ return; -+ -+ bfqq->pos_root = &bfqd->rq_pos_tree; -+ __bfqq = bfq_rq_pos_tree_lookup(bfqd, bfqq->pos_root, -+ blk_rq_pos(bfqq->next_rq), &parent, &p); -+ if (__bfqq == NULL) { -+ rb_link_node(&bfqq->pos_node, parent, p); -+ rb_insert_color(&bfqq->pos_node, bfqq->pos_root); -+ } else -+ bfqq->pos_root = NULL; -+} -+ -+/* -+ * Tell whether there are active queues or groups with differentiated weights. -+ */ -+static inline bool bfq_differentiated_weights(struct bfq_data *bfqd) -+{ -+ BUG_ON(!bfqd->hw_tag); -+ /* -+ * For weights to differ, at least one of the trees must contain -+ * at least two nodes. -+ */ -+ return (!RB_EMPTY_ROOT(&bfqd->queue_weights_tree) && -+ (bfqd->queue_weights_tree.rb_node->rb_left || -+ bfqd->queue_weights_tree.rb_node->rb_right) -+#ifdef CONFIG_CGROUP_BFQIO -+ ) || -+ (!RB_EMPTY_ROOT(&bfqd->group_weights_tree) && -+ (bfqd->group_weights_tree.rb_node->rb_left || -+ bfqd->group_weights_tree.rb_node->rb_right) -+#endif -+ ); -+} -+ -+/* -+ * If the weight-counter tree passed as input contains no counter for -+ * the weight of the input entity, then add that counter; otherwise just -+ * increment the existing counter. -+ * -+ * Note that weight-counter trees contain few nodes in mostly symmetric -+ * scenarios. For example, if all queues have the same weight, then the -+ * weight-counter tree for the queues may contain at most one node. -+ * This holds even if low_latency is on, because weight-raised queues -+ * are not inserted in the tree. -+ * In most scenarios, the rate at which nodes are created/destroyed -+ * should be low too. -+ */ -+static void bfq_weights_tree_add(struct bfq_data *bfqd, -+ struct bfq_entity *entity, -+ struct rb_root *root) -+{ -+ struct rb_node **new = &(root->rb_node), *parent = NULL; -+ -+ /* -+ * Do not insert if: -+ * - the device does not support queueing; -+ * - the entity is already associated with a counter, which happens if: -+ * 1) the entity is associated with a queue, 2) a request arrival -+ * has caused the queue to become both non-weight-raised, and hence -+ * change its weight, and backlogged; in this respect, each -+ * of the two events causes an invocation of this function, -+ * 3) this is the invocation of this function caused by the second -+ * event. This second invocation is actually useless, and we handle -+ * this fact by exiting immediately. More efficient or clearer -+ * solutions might possibly be adopted. -+ */ -+ if (!bfqd->hw_tag || entity->weight_counter) -+ return; -+ -+ while (*new) { -+ struct bfq_weight_counter *__counter = container_of(*new, -+ struct bfq_weight_counter, -+ weights_node); -+ parent = *new; -+ -+ if (entity->weight == __counter->weight) { -+ entity->weight_counter = __counter; -+ goto inc_counter; -+ } -+ if (entity->weight < __counter->weight) -+ new = &((*new)->rb_left); -+ else -+ new = &((*new)->rb_right); -+ } -+ -+ entity->weight_counter = kzalloc(sizeof(struct bfq_weight_counter), -+ GFP_ATOMIC); -+ entity->weight_counter->weight = entity->weight; -+ rb_link_node(&entity->weight_counter->weights_node, parent, new); -+ rb_insert_color(&entity->weight_counter->weights_node, root); -+ -+inc_counter: -+ entity->weight_counter->num_active++; -+} -+ -+/* -+ * Decrement the weight counter associated with the entity, and, if the -+ * counter reaches 0, remove the counter from the tree. -+ * See the comments to the function bfq_weights_tree_add() for considerations -+ * about overhead. -+ */ -+static void bfq_weights_tree_remove(struct bfq_data *bfqd, -+ struct bfq_entity *entity, -+ struct rb_root *root) -+{ -+ /* -+ * Check whether the entity is actually associated with a counter. -+ * In fact, the device may not be considered NCQ-capable for a while, -+ * which implies that no insertion in the weight trees is performed, -+ * after which the device may start to be deemed NCQ-capable, and hence -+ * this function may start to be invoked. This may cause the function -+ * to be invoked for entities that are not associated with any counter. -+ */ -+ if (!entity->weight_counter) -+ return; -+ -+ BUG_ON(RB_EMPTY_ROOT(root)); -+ BUG_ON(entity->weight_counter->weight != entity->weight); -+ -+ BUG_ON(!entity->weight_counter->num_active); -+ entity->weight_counter->num_active--; -+ if (entity->weight_counter->num_active > 0) -+ goto reset_entity_pointer; -+ -+ rb_erase(&entity->weight_counter->weights_node, root); -+ kfree(entity->weight_counter); -+ -+reset_entity_pointer: -+ entity->weight_counter = NULL; -+} -+ -+static struct request *bfq_find_next_rq(struct bfq_data *bfqd, -+ struct bfq_queue *bfqq, -+ struct request *last) -+{ -+ struct rb_node *rbnext = rb_next(&last->rb_node); -+ struct rb_node *rbprev = rb_prev(&last->rb_node); -+ struct request *next = NULL, *prev = NULL; -+ -+ BUG_ON(RB_EMPTY_NODE(&last->rb_node)); -+ -+ if (rbprev != NULL) -+ prev = rb_entry_rq(rbprev); -+ -+ if (rbnext != NULL) -+ next = rb_entry_rq(rbnext); -+ else { -+ rbnext = rb_first(&bfqq->sort_list); -+ if (rbnext && rbnext != &last->rb_node) -+ next = rb_entry_rq(rbnext); -+ } -+ -+ return bfq_choose_req(bfqd, next, prev, blk_rq_pos(last)); -+} -+ -+/* see the definition of bfq_async_charge_factor for details */ -+static inline unsigned long bfq_serv_to_charge(struct request *rq, -+ struct bfq_queue *bfqq) -+{ -+ return blk_rq_sectors(rq) * -+ (1 + ((!bfq_bfqq_sync(bfqq)) * (bfqq->wr_coeff == 1) * -+ bfq_async_charge_factor)); -+} -+ -+/** -+ * bfq_updated_next_req - update the queue after a new next_rq selection. -+ * @bfqd: the device data the queue belongs to. -+ * @bfqq: the queue to update. -+ * -+ * If the first request of a queue changes we make sure that the queue -+ * has enough budget to serve at least its first request (if the -+ * request has grown). We do this because if the queue has not enough -+ * budget for its first request, it has to go through two dispatch -+ * rounds to actually get it dispatched. -+ */ -+static void bfq_updated_next_req(struct bfq_data *bfqd, -+ struct bfq_queue *bfqq) -+{ -+ struct bfq_entity *entity = &bfqq->entity; -+ struct bfq_service_tree *st = bfq_entity_service_tree(entity); -+ struct request *next_rq = bfqq->next_rq; -+ unsigned long new_budget; -+ -+ if (next_rq == NULL) -+ return; -+ -+ if (bfqq == bfqd->in_service_queue) -+ /* -+ * In order not to break guarantees, budgets cannot be -+ * changed after an entity has been selected. -+ */ -+ return; -+ -+ BUG_ON(entity->tree != &st->active); -+ BUG_ON(entity == entity->sched_data->in_service_entity); -+ -+ new_budget = max_t(unsigned long, bfqq->max_budget, -+ bfq_serv_to_charge(next_rq, bfqq)); -+ if (entity->budget != new_budget) { -+ entity->budget = new_budget; -+ bfq_log_bfqq(bfqd, bfqq, "updated next rq: new budget %lu", -+ new_budget); -+ bfq_activate_bfqq(bfqd, bfqq); -+ } -+} -+ -+static inline unsigned int bfq_wr_duration(struct bfq_data *bfqd) -+{ -+ u64 dur; -+ -+ if (bfqd->bfq_wr_max_time > 0) -+ return bfqd->bfq_wr_max_time; -+ -+ dur = bfqd->RT_prod; -+ do_div(dur, bfqd->peak_rate); -+ -+ return dur; -+} -+ -+/* Empty burst list and add just bfqq (see comments to bfq_handle_burst) */ -+static inline void bfq_reset_burst_list(struct bfq_data *bfqd, -+ struct bfq_queue *bfqq) -+{ -+ struct bfq_queue *item; -+ struct hlist_node *n; -+ -+ hlist_for_each_entry_safe(item, n, &bfqd->burst_list, burst_list_node) -+ hlist_del_init(&item->burst_list_node); -+ hlist_add_head(&bfqq->burst_list_node, &bfqd->burst_list); -+ bfqd->burst_size = 1; -+} -+ -+/* Add bfqq to the list of queues in current burst (see bfq_handle_burst) */ -+static void bfq_add_to_burst(struct bfq_data *bfqd, struct bfq_queue *bfqq) -+{ -+ /* Increment burst size to take into account also bfqq */ -+ bfqd->burst_size++; -+ -+ if (bfqd->burst_size == bfqd->bfq_large_burst_thresh) { -+ struct bfq_queue *pos, *bfqq_item; -+ struct hlist_node *n; -+ -+ /* -+ * Enough queues have been activated shortly after each -+ * other to consider this burst as large. -+ */ -+ bfqd->large_burst = true; -+ -+ /* -+ * We can now mark all queues in the burst list as -+ * belonging to a large burst. -+ */ -+ hlist_for_each_entry(bfqq_item, &bfqd->burst_list, -+ burst_list_node) -+ bfq_mark_bfqq_in_large_burst(bfqq_item); -+ bfq_mark_bfqq_in_large_burst(bfqq); -+ -+ /* -+ * From now on, and until the current burst finishes, any -+ * new queue being activated shortly after the last queue -+ * was inserted in the burst can be immediately marked as -+ * belonging to a large burst. So the burst list is not -+ * needed any more. Remove it. -+ */ -+ hlist_for_each_entry_safe(pos, n, &bfqd->burst_list, -+ burst_list_node) -+ hlist_del_init(&pos->burst_list_node); -+ } else /* burst not yet large: add bfqq to the burst list */ -+ hlist_add_head(&bfqq->burst_list_node, &bfqd->burst_list); -+} -+ -+/* -+ * If many queues happen to become active shortly after each other, then, -+ * to help the processes associated to these queues get their job done as -+ * soon as possible, it is usually better to not grant either weight-raising -+ * or device idling to these queues. In this comment we describe, firstly, -+ * the reasons why this fact holds, and, secondly, the next function, which -+ * implements the main steps needed to properly mark these queues so that -+ * they can then be treated in a different way. -+ * -+ * As for the terminology, we say that a queue becomes active, i.e., -+ * switches from idle to backlogged, either when it is created (as a -+ * consequence of the arrival of an I/O request), or, if already existing, -+ * when a new request for the queue arrives while the queue is idle. -+ * Bursts of activations, i.e., activations of different queues occurring -+ * shortly after each other, are typically caused by services or applications -+ * that spawn or reactivate many parallel threads/processes. Examples are -+ * systemd during boot or git grep. -+ * -+ * These services or applications benefit mostly from a high throughput: -+ * the quicker the requests of the activated queues are cumulatively served, -+ * the sooner the target job of these queues gets completed. As a consequence, -+ * weight-raising any of these queues, which also implies idling the device -+ * for it, is almost always counterproductive: in most cases it just lowers -+ * throughput. -+ * -+ * On the other hand, a burst of activations may be also caused by the start -+ * of an application that does not consist in a lot of parallel I/O-bound -+ * threads. In fact, with a complex application, the burst may be just a -+ * consequence of the fact that several processes need to be executed to -+ * start-up the application. To start an application as quickly as possible, -+ * the best thing to do is to privilege the I/O related to the application -+ * with respect to all other I/O. Therefore, the best strategy to start as -+ * quickly as possible an application that causes a burst of activations is -+ * to weight-raise all the queues activated during the burst. This is the -+ * exact opposite of the best strategy for the other type of bursts. -+ * -+ * In the end, to take the best action for each of the two cases, the two -+ * types of bursts need to be distinguished. Fortunately, this seems -+ * relatively easy to do, by looking at the sizes of the bursts. In -+ * particular, we found a threshold such that bursts with a larger size -+ * than that threshold are apparently caused only by services or commands -+ * such as systemd or git grep. For brevity, hereafter we call just 'large' -+ * these bursts. BFQ *does not* weight-raise queues whose activations occur -+ * in a large burst. In addition, for each of these queues BFQ performs or -+ * does not perform idling depending on which choice boosts the throughput -+ * most. The exact choice depends on the device and request pattern at -+ * hand. -+ * -+ * Turning back to the next function, it implements all the steps needed -+ * to detect the occurrence of a large burst and to properly mark all the -+ * queues belonging to it (so that they can then be treated in a different -+ * way). This goal is achieved by maintaining a special "burst list" that -+ * holds, temporarily, the queues that belong to the burst in progress. The -+ * list is then used to mark these queues as belonging to a large burst if -+ * the burst does become large. The main steps are the following. -+ * -+ * . when the very first queue is activated, the queue is inserted into the -+ * list (as it could be the first queue in a possible burst) -+ * -+ * . if the current burst has not yet become large, and a queue Q that does -+ * not yet belong to the burst is activated shortly after the last time -+ * at which a new queue entered the burst list, then the function appends -+ * Q to the burst list -+ * -+ * . if, as a consequence of the previous step, the burst size reaches -+ * the large-burst threshold, then -+ * -+ * . all the queues in the burst list are marked as belonging to a -+ * large burst -+ * -+ * . the burst list is deleted; in fact, the burst list already served -+ * its purpose (keeping temporarily track of the queues in a burst, -+ * so as to be able to mark them as belonging to a large burst in the -+ * previous sub-step), and now is not needed any more -+ * -+ * . the device enters a large-burst mode -+ * -+ * . if a queue Q that does not belong to the burst is activated while -+ * the device is in large-burst mode and shortly after the last time -+ * at which a queue either entered the burst list or was marked as -+ * belonging to the current large burst, then Q is immediately marked -+ * as belonging to a large burst. -+ * -+ * . if a queue Q that does not belong to the burst is activated a while -+ * later, i.e., not shortly after, than the last time at which a queue -+ * either entered the burst list or was marked as belonging to the -+ * current large burst, then the current burst is deemed as finished and: -+ * -+ * . the large-burst mode is reset if set -+ * -+ * . the burst list is emptied -+ * -+ * . Q is inserted in the burst list, as Q may be the first queue -+ * in a possible new burst (then the burst list contains just Q -+ * after this step). -+ */ -+static void bfq_handle_burst(struct bfq_data *bfqd, struct bfq_queue *bfqq, -+ bool idle_for_long_time) -+{ -+ /* -+ * If bfqq happened to be activated in a burst, but has been idle -+ * for at least as long as an interactive queue, then we assume -+ * that, in the overall I/O initiated in the burst, the I/O -+ * associated to bfqq is finished. So bfqq does not need to be -+ * treated as a queue belonging to a burst anymore. Accordingly, -+ * we reset bfqq's in_large_burst flag if set, and remove bfqq -+ * from the burst list if it's there. We do not decrement instead -+ * burst_size, because the fact that bfqq does not need to belong -+ * to the burst list any more does not invalidate the fact that -+ * bfqq may have been activated during the current burst. -+ */ -+ if (idle_for_long_time) { -+ hlist_del_init(&bfqq->burst_list_node); -+ bfq_clear_bfqq_in_large_burst(bfqq); -+ } -+ -+ /* -+ * If bfqq is already in the burst list or is part of a large -+ * burst, then there is nothing else to do. -+ */ -+ if (!hlist_unhashed(&bfqq->burst_list_node) || -+ bfq_bfqq_in_large_burst(bfqq)) -+ return; -+ -+ /* -+ * If bfqq's activation happens late enough, then the current -+ * burst is finished, and related data structures must be reset. -+ * -+ * In this respect, consider the special case where bfqq is the very -+ * first queue being activated. In this case, last_ins_in_burst is -+ * not yet significant when we get here. But it is easy to verify -+ * that, whether or not the following condition is true, bfqq will -+ * end up being inserted into the burst list. In particular the -+ * list will happen to contain only bfqq. And this is exactly what -+ * has to happen, as bfqq may be the first queue in a possible -+ * burst. -+ */ -+ if (time_is_before_jiffies(bfqd->last_ins_in_burst + -+ bfqd->bfq_burst_interval)) { -+ bfqd->large_burst = false; -+ bfq_reset_burst_list(bfqd, bfqq); -+ return; -+ } -+ -+ /* -+ * If we get here, then bfqq is being activated shortly after the -+ * last queue. So, if the current burst is also large, we can mark -+ * bfqq as belonging to this large burst immediately. -+ */ -+ if (bfqd->large_burst) { -+ bfq_mark_bfqq_in_large_burst(bfqq); -+ return; -+ } -+ -+ /* -+ * If we get here, then a large-burst state has not yet been -+ * reached, but bfqq is being activated shortly after the last -+ * queue. Then we add bfqq to the burst. -+ */ -+ bfq_add_to_burst(bfqd, bfqq); -+} -+ -+static void bfq_add_request(struct request *rq) -+{ -+ struct bfq_queue *bfqq = RQ_BFQQ(rq); -+ struct bfq_entity *entity = &bfqq->entity; -+ struct bfq_data *bfqd = bfqq->bfqd; -+ struct request *next_rq, *prev; -+ unsigned long old_wr_coeff = bfqq->wr_coeff; -+ bool interactive = false; -+ -+ bfq_log_bfqq(bfqd, bfqq, "add_request %d", rq_is_sync(rq)); -+ bfqq->queued[rq_is_sync(rq)]++; -+ bfqd->queued++; -+ -+ elv_rb_add(&bfqq->sort_list, rq); -+ -+ /* -+ * Check if this request is a better next-serve candidate. -+ */ -+ prev = bfqq->next_rq; -+ next_rq = bfq_choose_req(bfqd, bfqq->next_rq, rq, bfqd->last_position); -+ BUG_ON(next_rq == NULL); -+ bfqq->next_rq = next_rq; -+ -+ /* -+ * Adjust priority tree position, if next_rq changes. -+ */ -+ if (prev != bfqq->next_rq) -+ bfq_rq_pos_tree_add(bfqd, bfqq); -+ -+ if (!bfq_bfqq_busy(bfqq)) { -+ bool soft_rt, -+ idle_for_long_time = time_is_before_jiffies( -+ bfqq->budget_timeout + -+ bfqd->bfq_wr_min_idle_time); -+ -+ if (bfq_bfqq_sync(bfqq)) { -+ bool already_in_burst = -+ !hlist_unhashed(&bfqq->burst_list_node) || -+ bfq_bfqq_in_large_burst(bfqq); -+ bfq_handle_burst(bfqd, bfqq, idle_for_long_time); -+ /* -+ * If bfqq was not already in the current burst, -+ * then, at this point, bfqq either has been -+ * added to the current burst or has caused the -+ * current burst to terminate. In particular, in -+ * the second case, bfqq has become the first -+ * queue in a possible new burst. -+ * In both cases last_ins_in_burst needs to be -+ * moved forward. -+ */ -+ if (!already_in_burst) -+ bfqd->last_ins_in_burst = jiffies; -+ } -+ -+ soft_rt = bfqd->bfq_wr_max_softrt_rate > 0 && -+ !bfq_bfqq_in_large_burst(bfqq) && -+ time_is_before_jiffies(bfqq->soft_rt_next_start); -+ interactive = !bfq_bfqq_in_large_burst(bfqq) && -+ idle_for_long_time; -+ entity->budget = max_t(unsigned long, bfqq->max_budget, -+ bfq_serv_to_charge(next_rq, bfqq)); -+ -+ if (!bfq_bfqq_IO_bound(bfqq)) { -+ if (time_before(jiffies, -+ RQ_BIC(rq)->ttime.last_end_request + -+ bfqd->bfq_slice_idle)) { -+ bfqq->requests_within_timer++; -+ if (bfqq->requests_within_timer >= -+ bfqd->bfq_requests_within_timer) -+ bfq_mark_bfqq_IO_bound(bfqq); -+ } else -+ bfqq->requests_within_timer = 0; -+ } -+ -+ if (!bfqd->low_latency) -+ goto add_bfqq_busy; -+ -+ /* -+ * If the queue is not being boosted and has been idle -+ * for enough time, start a weight-raising period -+ */ -+ if (old_wr_coeff == 1 && (interactive || soft_rt)) { -+ bfqq->wr_coeff = bfqd->bfq_wr_coeff; -+ if (interactive) -+ bfqq->wr_cur_max_time = bfq_wr_duration(bfqd); -+ else -+ bfqq->wr_cur_max_time = -+ bfqd->bfq_wr_rt_max_time; -+ bfq_log_bfqq(bfqd, bfqq, -+ "wrais starting at %lu, rais_max_time %u", -+ jiffies, -+ jiffies_to_msecs(bfqq->wr_cur_max_time)); -+ } else if (old_wr_coeff > 1) { -+ if (interactive) -+ bfqq->wr_cur_max_time = bfq_wr_duration(bfqd); -+ else if (bfq_bfqq_in_large_burst(bfqq) || -+ (bfqq->wr_cur_max_time == -+ bfqd->bfq_wr_rt_max_time && -+ !soft_rt)) { -+ bfqq->wr_coeff = 1; -+ bfq_log_bfqq(bfqd, bfqq, -+ "wrais ending at %lu, rais_max_time %u", -+ jiffies, -+ jiffies_to_msecs(bfqq-> -+ wr_cur_max_time)); -+ } else if (time_before( -+ bfqq->last_wr_start_finish + -+ bfqq->wr_cur_max_time, -+ jiffies + -+ bfqd->bfq_wr_rt_max_time) && -+ soft_rt) { -+ /* -+ * -+ * The remaining weight-raising time is lower -+ * than bfqd->bfq_wr_rt_max_time, which -+ * means that the application is enjoying -+ * weight raising either because deemed soft- -+ * rt in the near past, or because deemed -+ * interactive a long ago. In both cases, -+ * resetting now the current remaining weight- -+ * raising time for the application to the -+ * weight-raising duration for soft rt -+ * applications would not cause any latency -+ * increase for the application (as the new -+ * duration would be higher than the remaining -+ * time). -+ * -+ * In addition, the application is now meeting -+ * the requirements for being deemed soft rt. -+ * In the end we can correctly and safely -+ * (re)charge the weight-raising duration for -+ * the application with the weight-raising -+ * duration for soft rt applications. -+ * -+ * In particular, doing this recharge now, i.e., -+ * before the weight-raising period for the -+ * application finishes, reduces the probability -+ * of the following negative scenario: -+ * 1) the weight of a soft rt application is -+ * raised at startup (as for any newly -+ * created application), -+ * 2) since the application is not interactive, -+ * at a certain time weight-raising is -+ * stopped for the application, -+ * 3) at that time the application happens to -+ * still have pending requests, and hence -+ * is destined to not have a chance to be -+ * deemed soft rt before these requests are -+ * completed (see the comments to the -+ * function bfq_bfqq_softrt_next_start() -+ * for details on soft rt detection), -+ * 4) these pending requests experience a high -+ * latency because the application is not -+ * weight-raised while they are pending. -+ */ -+ bfqq->last_wr_start_finish = jiffies; -+ bfqq->wr_cur_max_time = -+ bfqd->bfq_wr_rt_max_time; -+ } -+ } -+ if (old_wr_coeff != bfqq->wr_coeff) -+ entity->ioprio_changed = 1; -+add_bfqq_busy: -+ bfqq->last_idle_bklogged = jiffies; -+ bfqq->service_from_backlogged = 0; -+ bfq_clear_bfqq_softrt_update(bfqq); -+ bfq_add_bfqq_busy(bfqd, bfqq); -+ } else { -+ if (bfqd->low_latency && old_wr_coeff == 1 && !rq_is_sync(rq) && -+ time_is_before_jiffies( -+ bfqq->last_wr_start_finish + -+ bfqd->bfq_wr_min_inter_arr_async)) { -+ bfqq->wr_coeff = bfqd->bfq_wr_coeff; -+ bfqq->wr_cur_max_time = bfq_wr_duration(bfqd); -+ -+ bfqd->wr_busy_queues++; -+ entity->ioprio_changed = 1; -+ bfq_log_bfqq(bfqd, bfqq, -+ "non-idle wrais starting at %lu, rais_max_time %u", -+ jiffies, -+ jiffies_to_msecs(bfqq->wr_cur_max_time)); -+ } -+ if (prev != bfqq->next_rq) -+ bfq_updated_next_req(bfqd, bfqq); -+ } -+ -+ if (bfqd->low_latency && -+ (old_wr_coeff == 1 || bfqq->wr_coeff == 1 || interactive)) -+ bfqq->last_wr_start_finish = jiffies; -+} -+ -+static struct request *bfq_find_rq_fmerge(struct bfq_data *bfqd, -+ struct bio *bio) -+{ -+ struct task_struct *tsk = current; -+ struct bfq_io_cq *bic; -+ struct bfq_queue *bfqq; -+ -+ bic = bfq_bic_lookup(bfqd, tsk->io_context); -+ if (bic == NULL) -+ return NULL; -+ -+ bfqq = bic_to_bfqq(bic, bfq_bio_sync(bio)); -+ if (bfqq != NULL) -+ return elv_rb_find(&bfqq->sort_list, bio_end_sector(bio)); -+ -+ return NULL; -+} -+ -+static void bfq_activate_request(struct request_queue *q, struct request *rq) -+{ -+ struct bfq_data *bfqd = q->elevator->elevator_data; -+ -+ bfqd->rq_in_driver++; -+ bfqd->last_position = blk_rq_pos(rq) + blk_rq_sectors(rq); -+ bfq_log(bfqd, "activate_request: new bfqd->last_position %llu", -+ (long long unsigned)bfqd->last_position); -+} -+ -+static inline void bfq_deactivate_request(struct request_queue *q, -+ struct request *rq) -+{ -+ struct bfq_data *bfqd = q->elevator->elevator_data; -+ -+ BUG_ON(bfqd->rq_in_driver == 0); -+ bfqd->rq_in_driver--; -+} -+ -+static void bfq_remove_request(struct request *rq) -+{ -+ struct bfq_queue *bfqq = RQ_BFQQ(rq); -+ struct bfq_data *bfqd = bfqq->bfqd; -+ const int sync = rq_is_sync(rq); -+ -+ if (bfqq->next_rq == rq) { -+ bfqq->next_rq = bfq_find_next_rq(bfqd, bfqq, rq); -+ bfq_updated_next_req(bfqd, bfqq); -+ } -+ -+ list_del_init(&rq->queuelist); -+ BUG_ON(bfqq->queued[sync] == 0); -+ bfqq->queued[sync]--; -+ bfqd->queued--; -+ elv_rb_del(&bfqq->sort_list, rq); -+ -+ if (RB_EMPTY_ROOT(&bfqq->sort_list)) { -+ if (bfq_bfqq_busy(bfqq) && bfqq != bfqd->in_service_queue) -+ bfq_del_bfqq_busy(bfqd, bfqq, 1); -+ /* -+ * Remove queue from request-position tree as it is empty. -+ */ -+ if (bfqq->pos_root != NULL) { -+ rb_erase(&bfqq->pos_node, bfqq->pos_root); -+ bfqq->pos_root = NULL; -+ } -+ } -+ -+ if (rq->cmd_flags & REQ_META) { -+ BUG_ON(bfqq->meta_pending == 0); -+ bfqq->meta_pending--; -+ } -+} -+ -+static int bfq_merge(struct request_queue *q, struct request **req, -+ struct bio *bio) -+{ -+ struct bfq_data *bfqd = q->elevator->elevator_data; -+ struct request *__rq; -+ -+ __rq = bfq_find_rq_fmerge(bfqd, bio); -+ if (__rq != NULL && elv_rq_merge_ok(__rq, bio)) { -+ *req = __rq; -+ return ELEVATOR_FRONT_MERGE; -+ } -+ -+ return ELEVATOR_NO_MERGE; -+} -+ -+static void bfq_merged_request(struct request_queue *q, struct request *req, -+ int type) -+{ -+ if (type == ELEVATOR_FRONT_MERGE && -+ rb_prev(&req->rb_node) && -+ blk_rq_pos(req) < -+ blk_rq_pos(container_of(rb_prev(&req->rb_node), -+ struct request, rb_node))) { -+ struct bfq_queue *bfqq = RQ_BFQQ(req); -+ struct bfq_data *bfqd = bfqq->bfqd; -+ struct request *prev, *next_rq; -+ -+ /* Reposition request in its sort_list */ -+ elv_rb_del(&bfqq->sort_list, req); -+ elv_rb_add(&bfqq->sort_list, req); -+ /* Choose next request to be served for bfqq */ -+ prev = bfqq->next_rq; -+ next_rq = bfq_choose_req(bfqd, bfqq->next_rq, req, -+ bfqd->last_position); -+ BUG_ON(next_rq == NULL); -+ bfqq->next_rq = next_rq; -+ /* -+ * If next_rq changes, update both the queue's budget to -+ * fit the new request and the queue's position in its -+ * rq_pos_tree. -+ */ -+ if (prev != bfqq->next_rq) { -+ bfq_updated_next_req(bfqd, bfqq); -+ bfq_rq_pos_tree_add(bfqd, bfqq); -+ } -+ } -+} -+ -+static void bfq_merged_requests(struct request_queue *q, struct request *rq, -+ struct request *next) -+{ -+ struct bfq_queue *bfqq = RQ_BFQQ(rq); -+ -+ /* -+ * Reposition in fifo if next is older than rq. -+ */ -+ if (!list_empty(&rq->queuelist) && !list_empty(&next->queuelist) && -+ time_before(next->fifo_time, rq->fifo_time)) { -+ list_move(&rq->queuelist, &next->queuelist); -+ rq->fifo_time = next->fifo_time; -+ } -+ -+ if (bfqq->next_rq == next) -+ bfqq->next_rq = rq; -+ -+ bfq_remove_request(next); -+} -+ -+/* Must be called with bfqq != NULL */ -+static inline void bfq_bfqq_end_wr(struct bfq_queue *bfqq) -+{ -+ BUG_ON(bfqq == NULL); -+ if (bfq_bfqq_busy(bfqq)) -+ bfqq->bfqd->wr_busy_queues--; -+ bfqq->wr_coeff = 1; -+ bfqq->wr_cur_max_time = 0; -+ /* Trigger a weight change on the next activation of the queue */ -+ bfqq->entity.ioprio_changed = 1; -+} -+ -+static void bfq_end_wr_async_queues(struct bfq_data *bfqd, -+ struct bfq_group *bfqg) -+{ -+ int i, j; -+ -+ for (i = 0; i < 2; i++) -+ for (j = 0; j < IOPRIO_BE_NR; j++) -+ if (bfqg->async_bfqq[i][j] != NULL) -+ bfq_bfqq_end_wr(bfqg->async_bfqq[i][j]); -+ if (bfqg->async_idle_bfqq != NULL) -+ bfq_bfqq_end_wr(bfqg->async_idle_bfqq); -+} -+ -+static void bfq_end_wr(struct bfq_data *bfqd) -+{ -+ struct bfq_queue *bfqq; -+ -+ spin_lock_irq(bfqd->queue->queue_lock); -+ -+ list_for_each_entry(bfqq, &bfqd->active_list, bfqq_list) -+ bfq_bfqq_end_wr(bfqq); -+ list_for_each_entry(bfqq, &bfqd->idle_list, bfqq_list) -+ bfq_bfqq_end_wr(bfqq); -+ bfq_end_wr_async(bfqd); -+ -+ spin_unlock_irq(bfqd->queue->queue_lock); -+} -+ -+static int bfq_allow_merge(struct request_queue *q, struct request *rq, -+ struct bio *bio) -+{ -+ struct bfq_data *bfqd = q->elevator->elevator_data; -+ struct bfq_io_cq *bic; -+ struct bfq_queue *bfqq; -+ -+ /* -+ * Disallow merge of a sync bio into an async request. -+ */ -+ if (bfq_bio_sync(bio) && !rq_is_sync(rq)) -+ return 0; -+ -+ /* -+ * Lookup the bfqq that this bio will be queued with. Allow -+ * merge only if rq is queued there. -+ * Queue lock is held here. -+ */ -+ bic = bfq_bic_lookup(bfqd, current->io_context); -+ if (bic == NULL) -+ return 0; -+ -+ bfqq = bic_to_bfqq(bic, bfq_bio_sync(bio)); -+ return bfqq == RQ_BFQQ(rq); -+} -+ -+static void __bfq_set_in_service_queue(struct bfq_data *bfqd, -+ struct bfq_queue *bfqq) -+{ -+ if (bfqq != NULL) { -+ bfq_mark_bfqq_must_alloc(bfqq); -+ bfq_mark_bfqq_budget_new(bfqq); -+ bfq_clear_bfqq_fifo_expire(bfqq); -+ -+ bfqd->budgets_assigned = (bfqd->budgets_assigned*7 + 256) / 8; -+ -+ bfq_log_bfqq(bfqd, bfqq, -+ "set_in_service_queue, cur-budget = %lu", -+ bfqq->entity.budget); -+ } -+ -+ bfqd->in_service_queue = bfqq; -+} -+ -+/* -+ * Get and set a new queue for service. -+ */ -+static struct bfq_queue *bfq_set_in_service_queue(struct bfq_data *bfqd, -+ struct bfq_queue *bfqq) -+{ -+ if (!bfqq) -+ bfqq = bfq_get_next_queue(bfqd); -+ else -+ bfq_get_next_queue_forced(bfqd, bfqq); -+ -+ __bfq_set_in_service_queue(bfqd, bfqq); -+ return bfqq; -+} -+ -+static inline sector_t bfq_dist_from_last(struct bfq_data *bfqd, -+ struct request *rq) -+{ -+ if (blk_rq_pos(rq) >= bfqd->last_position) -+ return blk_rq_pos(rq) - bfqd->last_position; -+ else -+ return bfqd->last_position - blk_rq_pos(rq); -+} -+ -+/* -+ * Return true if bfqq has no request pending and rq is close enough to -+ * bfqd->last_position, or if rq is closer to bfqd->last_position than -+ * bfqq->next_rq -+ */ -+static inline int bfq_rq_close(struct bfq_data *bfqd, struct request *rq) -+{ -+ return bfq_dist_from_last(bfqd, rq) <= BFQQ_SEEK_THR; -+} -+ -+static struct bfq_queue *bfqq_close(struct bfq_data *bfqd) -+{ -+ struct rb_root *root = &bfqd->rq_pos_tree; -+ struct rb_node *parent, *node; -+ struct bfq_queue *__bfqq; -+ sector_t sector = bfqd->last_position; -+ -+ if (RB_EMPTY_ROOT(root)) -+ return NULL; -+ -+ /* -+ * First, if we find a request starting at the end of the last -+ * request, choose it. -+ */ -+ __bfqq = bfq_rq_pos_tree_lookup(bfqd, root, sector, &parent, NULL); -+ if (__bfqq != NULL) -+ return __bfqq; -+ -+ /* -+ * If the exact sector wasn't found, the parent of the NULL leaf -+ * will contain the closest sector (rq_pos_tree sorted by -+ * next_request position). -+ */ -+ __bfqq = rb_entry(parent, struct bfq_queue, pos_node); -+ if (bfq_rq_close(bfqd, __bfqq->next_rq)) -+ return __bfqq; -+ -+ if (blk_rq_pos(__bfqq->next_rq) < sector) -+ node = rb_next(&__bfqq->pos_node); -+ else -+ node = rb_prev(&__bfqq->pos_node); -+ if (node == NULL) -+ return NULL; -+ -+ __bfqq = rb_entry(node, struct bfq_queue, pos_node); -+ if (bfq_rq_close(bfqd, __bfqq->next_rq)) -+ return __bfqq; -+ -+ return NULL; -+} -+ -+/* -+ * bfqd - obvious -+ * cur_bfqq - passed in so that we don't decide that the current queue -+ * is closely cooperating with itself. -+ * -+ * We are assuming that cur_bfqq has dispatched at least one request, -+ * and that bfqd->last_position reflects a position on the disk associated -+ * with the I/O issued by cur_bfqq. -+ */ -+static struct bfq_queue *bfq_close_cooperator(struct bfq_data *bfqd, -+ struct bfq_queue *cur_bfqq) -+{ -+ struct bfq_queue *bfqq; -+ -+ if (bfq_class_idle(cur_bfqq)) -+ return NULL; -+ if (!bfq_bfqq_sync(cur_bfqq)) -+ return NULL; -+ if (BFQQ_SEEKY(cur_bfqq)) -+ return NULL; -+ -+ /* If device has only one backlogged bfq_queue, don't search. */ -+ if (bfqd->busy_queues == 1) -+ return NULL; -+ -+ /* -+ * We should notice if some of the queues are cooperating, e.g. -+ * working closely on the same area of the disk. In that case, -+ * we can group them together and don't waste time idling. -+ */ -+ bfqq = bfqq_close(bfqd); -+ if (bfqq == NULL || bfqq == cur_bfqq) -+ return NULL; -+ -+ /* -+ * Do not merge queues from different bfq_groups. -+ */ -+ if (bfqq->entity.parent != cur_bfqq->entity.parent) -+ return NULL; -+ -+ /* -+ * It only makes sense to merge sync queues. -+ */ -+ if (!bfq_bfqq_sync(bfqq)) -+ return NULL; -+ if (BFQQ_SEEKY(bfqq)) -+ return NULL; -+ -+ /* -+ * Do not merge queues of different priority classes. -+ */ -+ if (bfq_class_rt(bfqq) != bfq_class_rt(cur_bfqq)) -+ return NULL; -+ -+ return bfqq; -+} -+ -+/* -+ * If enough samples have been computed, return the current max budget -+ * stored in bfqd, which is dynamically updated according to the -+ * estimated disk peak rate; otherwise return the default max budget -+ */ -+static inline unsigned long bfq_max_budget(struct bfq_data *bfqd) -+{ -+ if (bfqd->budgets_assigned < 194) -+ return bfq_default_max_budget; -+ else -+ return bfqd->bfq_max_budget; -+} -+ -+/* -+ * Return min budget, which is a fraction of the current or default -+ * max budget (trying with 1/32) -+ */ -+static inline unsigned long bfq_min_budget(struct bfq_data *bfqd) -+{ -+ if (bfqd->budgets_assigned < 194) -+ return bfq_default_max_budget / 32; -+ else -+ return bfqd->bfq_max_budget / 32; -+} -+ -+static void bfq_arm_slice_timer(struct bfq_data *bfqd) -+{ -+ struct bfq_queue *bfqq = bfqd->in_service_queue; -+ struct bfq_io_cq *bic; -+ unsigned long sl; -+ -+ BUG_ON(!RB_EMPTY_ROOT(&bfqq->sort_list)); -+ -+ /* Processes have exited, don't wait. */ -+ bic = bfqd->in_service_bic; -+ if (bic == NULL || atomic_read(&bic->icq.ioc->active_ref) == 0) -+ return; -+ -+ bfq_mark_bfqq_wait_request(bfqq); -+ -+ /* -+ * We don't want to idle for seeks, but we do want to allow -+ * fair distribution of slice time for a process doing back-to-back -+ * seeks. So allow a little bit of time for him to submit a new rq. -+ * -+ * To prevent processes with (partly) seeky workloads from -+ * being too ill-treated, grant them a small fraction of the -+ * assigned budget before reducing the waiting time to -+ * BFQ_MIN_TT. This happened to help reduce latency. -+ */ -+ sl = bfqd->bfq_slice_idle; -+ /* -+ * Unless the queue is being weight-raised, grant only minimum idle -+ * time if the queue either has been seeky for long enough or has -+ * already proved to be constantly seeky. -+ */ -+ if (bfq_sample_valid(bfqq->seek_samples) && -+ ((BFQQ_SEEKY(bfqq) && bfqq->entity.service > -+ bfq_max_budget(bfqq->bfqd) / 8) || -+ bfq_bfqq_constantly_seeky(bfqq)) && bfqq->wr_coeff == 1) -+ sl = min(sl, msecs_to_jiffies(BFQ_MIN_TT)); -+ else if (bfqq->wr_coeff > 1) -+ sl = sl * 3; -+ bfqd->last_idling_start = ktime_get(); -+ mod_timer(&bfqd->idle_slice_timer, jiffies + sl); -+ bfq_log(bfqd, "arm idle: %u/%u ms", -+ jiffies_to_msecs(sl), jiffies_to_msecs(bfqd->bfq_slice_idle)); -+} -+ -+/* -+ * Set the maximum time for the in-service queue to consume its -+ * budget. This prevents seeky processes from lowering the disk -+ * throughput (always guaranteed with a time slice scheme as in CFQ). -+ */ -+static void bfq_set_budget_timeout(struct bfq_data *bfqd) -+{ -+ struct bfq_queue *bfqq = bfqd->in_service_queue; -+ unsigned int timeout_coeff; -+ if (bfqq->wr_cur_max_time == bfqd->bfq_wr_rt_max_time) -+ timeout_coeff = 1; -+ else -+ timeout_coeff = bfqq->entity.weight / bfqq->entity.orig_weight; -+ -+ bfqd->last_budget_start = ktime_get(); -+ -+ bfq_clear_bfqq_budget_new(bfqq); -+ bfqq->budget_timeout = jiffies + -+ bfqd->bfq_timeout[bfq_bfqq_sync(bfqq)] * timeout_coeff; -+ -+ bfq_log_bfqq(bfqd, bfqq, "set budget_timeout %u", -+ jiffies_to_msecs(bfqd->bfq_timeout[bfq_bfqq_sync(bfqq)] * -+ timeout_coeff)); -+} -+ -+/* -+ * Move request from internal lists to the request queue dispatch list. -+ */ -+static void bfq_dispatch_insert(struct request_queue *q, struct request *rq) -+{ -+ struct bfq_data *bfqd = q->elevator->elevator_data; -+ struct bfq_queue *bfqq = RQ_BFQQ(rq); -+ -+ /* -+ * For consistency, the next instruction should have been executed -+ * after removing the request from the queue and dispatching it. -+ * We execute instead this instruction before bfq_remove_request() -+ * (and hence introduce a temporary inconsistency), for efficiency. -+ * In fact, in a forced_dispatch, this prevents two counters related -+ * to bfqq->dispatched to risk to be uselessly decremented if bfqq -+ * is not in service, and then to be incremented again after -+ * incrementing bfqq->dispatched. -+ */ -+ bfqq->dispatched++; -+ bfq_remove_request(rq); -+ elv_dispatch_sort(q, rq); -+ -+ if (bfq_bfqq_sync(bfqq)) -+ bfqd->sync_flight++; -+} -+ -+/* -+ * Return expired entry, or NULL to just start from scratch in rbtree. -+ */ -+static struct request *bfq_check_fifo(struct bfq_queue *bfqq) -+{ -+ struct request *rq = NULL; -+ -+ if (bfq_bfqq_fifo_expire(bfqq)) -+ return NULL; -+ -+ bfq_mark_bfqq_fifo_expire(bfqq); -+ -+ if (list_empty(&bfqq->fifo)) -+ return NULL; -+ -+ rq = rq_entry_fifo(bfqq->fifo.next); -+ -+ if (time_before(jiffies, rq->fifo_time)) -+ return NULL; -+ -+ return rq; -+} -+ -+/* Must be called with the queue_lock held. */ -+static int bfqq_process_refs(struct bfq_queue *bfqq) -+{ -+ int process_refs, io_refs; -+ -+ io_refs = bfqq->allocated[READ] + bfqq->allocated[WRITE]; -+ process_refs = atomic_read(&bfqq->ref) - io_refs - bfqq->entity.on_st; -+ BUG_ON(process_refs < 0); -+ return process_refs; -+} -+ -+static void bfq_setup_merge(struct bfq_queue *bfqq, struct bfq_queue *new_bfqq) -+{ -+ int process_refs, new_process_refs; -+ struct bfq_queue *__bfqq; -+ -+ /* -+ * If there are no process references on the new_bfqq, then it is -+ * unsafe to follow the ->new_bfqq chain as other bfqq's in the chain -+ * may have dropped their last reference (not just their last process -+ * reference). -+ */ -+ if (!bfqq_process_refs(new_bfqq)) -+ return; -+ -+ /* Avoid a circular list and skip interim queue merges. */ -+ while ((__bfqq = new_bfqq->new_bfqq)) { -+ if (__bfqq == bfqq) -+ return; -+ new_bfqq = __bfqq; -+ } -+ -+ process_refs = bfqq_process_refs(bfqq); -+ new_process_refs = bfqq_process_refs(new_bfqq); -+ /* -+ * If the process for the bfqq has gone away, there is no -+ * sense in merging the queues. -+ */ -+ if (process_refs == 0 || new_process_refs == 0) -+ return; -+ -+ /* -+ * Merge in the direction of the lesser amount of work. -+ */ -+ if (new_process_refs >= process_refs) { -+ bfqq->new_bfqq = new_bfqq; -+ atomic_add(process_refs, &new_bfqq->ref); -+ } else { -+ new_bfqq->new_bfqq = bfqq; -+ atomic_add(new_process_refs, &bfqq->ref); -+ } -+ bfq_log_bfqq(bfqq->bfqd, bfqq, "scheduling merge with queue %d", -+ new_bfqq->pid); -+} -+ -+static inline unsigned long bfq_bfqq_budget_left(struct bfq_queue *bfqq) -+{ -+ struct bfq_entity *entity = &bfqq->entity; -+ return entity->budget - entity->service; -+} -+ -+static void __bfq_bfqq_expire(struct bfq_data *bfqd, struct bfq_queue *bfqq) -+{ -+ BUG_ON(bfqq != bfqd->in_service_queue); -+ -+ __bfq_bfqd_reset_in_service(bfqd); -+ -+ /* -+ * If this bfqq is shared between multiple processes, check -+ * to make sure that those processes are still issuing I/Os -+ * within the mean seek distance. If not, it may be time to -+ * break the queues apart again. -+ */ -+ if (bfq_bfqq_coop(bfqq) && BFQQ_SEEKY(bfqq)) -+ bfq_mark_bfqq_split_coop(bfqq); -+ -+ if (RB_EMPTY_ROOT(&bfqq->sort_list)) { -+ /* -+ * Overloading budget_timeout field to store the time -+ * at which the queue remains with no backlog; used by -+ * the weight-raising mechanism. -+ */ -+ bfqq->budget_timeout = jiffies; -+ bfq_del_bfqq_busy(bfqd, bfqq, 1); -+ } else { -+ bfq_activate_bfqq(bfqd, bfqq); -+ /* -+ * Resort priority tree of potential close cooperators. -+ */ -+ bfq_rq_pos_tree_add(bfqd, bfqq); -+ } -+} -+ -+/** -+ * __bfq_bfqq_recalc_budget - try to adapt the budget to the @bfqq behavior. -+ * @bfqd: device data. -+ * @bfqq: queue to update. -+ * @reason: reason for expiration. -+ * -+ * Handle the feedback on @bfqq budget. See the body for detailed -+ * comments. -+ */ -+static void __bfq_bfqq_recalc_budget(struct bfq_data *bfqd, -+ struct bfq_queue *bfqq, -+ enum bfqq_expiration reason) -+{ -+ struct request *next_rq; -+ unsigned long budget, min_budget; -+ -+ budget = bfqq->max_budget; -+ min_budget = bfq_min_budget(bfqd); -+ -+ BUG_ON(bfqq != bfqd->in_service_queue); -+ -+ bfq_log_bfqq(bfqd, bfqq, "recalc_budg: last budg %lu, budg left %lu", -+ bfqq->entity.budget, bfq_bfqq_budget_left(bfqq)); -+ bfq_log_bfqq(bfqd, bfqq, "recalc_budg: last max_budg %lu, min budg %lu", -+ budget, bfq_min_budget(bfqd)); -+ bfq_log_bfqq(bfqd, bfqq, "recalc_budg: sync %d, seeky %d", -+ bfq_bfqq_sync(bfqq), BFQQ_SEEKY(bfqd->in_service_queue)); -+ -+ if (bfq_bfqq_sync(bfqq)) { -+ switch (reason) { -+ /* -+ * Caveat: in all the following cases we trade latency -+ * for throughput. -+ */ -+ case BFQ_BFQQ_TOO_IDLE: -+ /* -+ * This is the only case where we may reduce -+ * the budget: if there is no request of the -+ * process still waiting for completion, then -+ * we assume (tentatively) that the timer has -+ * expired because the batch of requests of -+ * the process could have been served with a -+ * smaller budget. Hence, betting that -+ * process will behave in the same way when it -+ * becomes backlogged again, we reduce its -+ * next budget. As long as we guess right, -+ * this budget cut reduces the latency -+ * experienced by the process. -+ * -+ * However, if there are still outstanding -+ * requests, then the process may have not yet -+ * issued its next request just because it is -+ * still waiting for the completion of some of -+ * the still outstanding ones. So in this -+ * subcase we do not reduce its budget, on the -+ * contrary we increase it to possibly boost -+ * the throughput, as discussed in the -+ * comments to the BUDGET_TIMEOUT case. -+ */ -+ if (bfqq->dispatched > 0) /* still outstanding reqs */ -+ budget = min(budget * 2, bfqd->bfq_max_budget); -+ else { -+ if (budget > 5 * min_budget) -+ budget -= 4 * min_budget; -+ else -+ budget = min_budget; -+ } -+ break; -+ case BFQ_BFQQ_BUDGET_TIMEOUT: -+ /* -+ * We double the budget here because: 1) it -+ * gives the chance to boost the throughput if -+ * this is not a seeky process (which may have -+ * bumped into this timeout because of, e.g., -+ * ZBR), 2) together with charge_full_budget -+ * it helps give seeky processes higher -+ * timestamps, and hence be served less -+ * frequently. -+ */ -+ budget = min(budget * 2, bfqd->bfq_max_budget); -+ break; -+ case BFQ_BFQQ_BUDGET_EXHAUSTED: -+ /* -+ * The process still has backlog, and did not -+ * let either the budget timeout or the disk -+ * idling timeout expire. Hence it is not -+ * seeky, has a short thinktime and may be -+ * happy with a higher budget too. So -+ * definitely increase the budget of this good -+ * candidate to boost the disk throughput. -+ */ -+ budget = min(budget * 4, bfqd->bfq_max_budget); -+ break; -+ case BFQ_BFQQ_NO_MORE_REQUESTS: -+ /* -+ * Leave the budget unchanged. -+ */ -+ default: -+ return; -+ } -+ } else /* async queue */ -+ /* async queues get always the maximum possible budget -+ * (their ability to dispatch is limited by -+ * @bfqd->bfq_max_budget_async_rq). -+ */ -+ budget = bfqd->bfq_max_budget; -+ -+ bfqq->max_budget = budget; -+ -+ if (bfqd->budgets_assigned >= 194 && bfqd->bfq_user_max_budget == 0 && -+ bfqq->max_budget > bfqd->bfq_max_budget) -+ bfqq->max_budget = bfqd->bfq_max_budget; -+ -+ /* -+ * Make sure that we have enough budget for the next request. -+ * Since the finish time of the bfqq must be kept in sync with -+ * the budget, be sure to call __bfq_bfqq_expire() after the -+ * update. -+ */ -+ next_rq = bfqq->next_rq; -+ if (next_rq != NULL) -+ bfqq->entity.budget = max_t(unsigned long, bfqq->max_budget, -+ bfq_serv_to_charge(next_rq, bfqq)); -+ else -+ bfqq->entity.budget = bfqq->max_budget; -+ -+ bfq_log_bfqq(bfqd, bfqq, "head sect: %u, new budget %lu", -+ next_rq != NULL ? blk_rq_sectors(next_rq) : 0, -+ bfqq->entity.budget); -+} -+ -+static unsigned long bfq_calc_max_budget(u64 peak_rate, u64 timeout) -+{ -+ unsigned long max_budget; -+ -+ /* -+ * The max_budget calculated when autotuning is equal to the -+ * amount of sectors transfered in timeout_sync at the -+ * estimated peak rate. -+ */ -+ max_budget = (unsigned long)(peak_rate * 1000 * -+ timeout >> BFQ_RATE_SHIFT); -+ -+ return max_budget; -+} -+ -+/* -+ * In addition to updating the peak rate, checks whether the process -+ * is "slow", and returns 1 if so. This slow flag is used, in addition -+ * to the budget timeout, to reduce the amount of service provided to -+ * seeky processes, and hence reduce their chances to lower the -+ * throughput. See the code for more details. -+ */ -+static int bfq_update_peak_rate(struct bfq_data *bfqd, struct bfq_queue *bfqq, -+ int compensate, enum bfqq_expiration reason) -+{ -+ u64 bw, usecs, expected, timeout; -+ ktime_t delta; -+ int update = 0; -+ -+ if (!bfq_bfqq_sync(bfqq) || bfq_bfqq_budget_new(bfqq)) -+ return 0; -+ -+ if (compensate) -+ delta = bfqd->last_idling_start; -+ else -+ delta = ktime_get(); -+ delta = ktime_sub(delta, bfqd->last_budget_start); -+ usecs = ktime_to_us(delta); -+ -+ /* Don't trust short/unrealistic values. */ -+ if (usecs < 100 || usecs >= LONG_MAX) -+ return 0; -+ -+ /* -+ * Calculate the bandwidth for the last slice. We use a 64 bit -+ * value to store the peak rate, in sectors per usec in fixed -+ * point math. We do so to have enough precision in the estimate -+ * and to avoid overflows. -+ */ -+ bw = (u64)bfqq->entity.service << BFQ_RATE_SHIFT; -+ do_div(bw, (unsigned long)usecs); -+ -+ timeout = jiffies_to_msecs(bfqd->bfq_timeout[BLK_RW_SYNC]); -+ -+ /* -+ * Use only long (> 20ms) intervals to filter out spikes for -+ * the peak rate estimation. -+ */ -+ if (usecs > 20000) { -+ if (bw > bfqd->peak_rate || -+ (!BFQQ_SEEKY(bfqq) && -+ reason == BFQ_BFQQ_BUDGET_TIMEOUT)) { -+ bfq_log(bfqd, "measured bw =%llu", bw); -+ /* -+ * To smooth oscillations use a low-pass filter with -+ * alpha=7/8, i.e., -+ * new_rate = (7/8) * old_rate + (1/8) * bw -+ */ -+ do_div(bw, 8); -+ if (bw == 0) -+ return 0; -+ bfqd->peak_rate *= 7; -+ do_div(bfqd->peak_rate, 8); -+ bfqd->peak_rate += bw; -+ update = 1; -+ bfq_log(bfqd, "new peak_rate=%llu", bfqd->peak_rate); -+ } -+ -+ update |= bfqd->peak_rate_samples == BFQ_PEAK_RATE_SAMPLES - 1; -+ -+ if (bfqd->peak_rate_samples < BFQ_PEAK_RATE_SAMPLES) -+ bfqd->peak_rate_samples++; -+ -+ if (bfqd->peak_rate_samples == BFQ_PEAK_RATE_SAMPLES && -+ update) { -+ int dev_type = blk_queue_nonrot(bfqd->queue); -+ if (bfqd->bfq_user_max_budget == 0) { -+ bfqd->bfq_max_budget = -+ bfq_calc_max_budget(bfqd->peak_rate, -+ timeout); -+ bfq_log(bfqd, "new max_budget=%lu", -+ bfqd->bfq_max_budget); -+ } -+ if (bfqd->device_speed == BFQ_BFQD_FAST && -+ bfqd->peak_rate < device_speed_thresh[dev_type]) { -+ bfqd->device_speed = BFQ_BFQD_SLOW; -+ bfqd->RT_prod = R_slow[dev_type] * -+ T_slow[dev_type]; -+ } else if (bfqd->device_speed == BFQ_BFQD_SLOW && -+ bfqd->peak_rate > device_speed_thresh[dev_type]) { -+ bfqd->device_speed = BFQ_BFQD_FAST; -+ bfqd->RT_prod = R_fast[dev_type] * -+ T_fast[dev_type]; -+ } -+ } -+ } -+ -+ /* -+ * If the process has been served for a too short time -+ * interval to let its possible sequential accesses prevail on -+ * the initial seek time needed to move the disk head on the -+ * first sector it requested, then give the process a chance -+ * and for the moment return false. -+ */ -+ if (bfqq->entity.budget <= bfq_max_budget(bfqd) / 8) -+ return 0; -+ -+ /* -+ * A process is considered ``slow'' (i.e., seeky, so that we -+ * cannot treat it fairly in the service domain, as it would -+ * slow down too much the other processes) if, when a slice -+ * ends for whatever reason, it has received service at a -+ * rate that would not be high enough to complete the budget -+ * before the budget timeout expiration. -+ */ -+ expected = bw * 1000 * timeout >> BFQ_RATE_SHIFT; -+ -+ /* -+ * Caveat: processes doing IO in the slower disk zones will -+ * tend to be slow(er) even if not seeky. And the estimated -+ * peak rate will actually be an average over the disk -+ * surface. Hence, to not be too harsh with unlucky processes, -+ * we keep a budget/3 margin of safety before declaring a -+ * process slow. -+ */ -+ return expected > (4 * bfqq->entity.budget) / 3; -+} -+ -+/* -+ * To be deemed as soft real-time, an application must meet two -+ * requirements. First, the application must not require an average -+ * bandwidth higher than the approximate bandwidth required to playback or -+ * record a compressed high-definition video. -+ * The next function is invoked on the completion of the last request of a -+ * batch, to compute the next-start time instant, soft_rt_next_start, such -+ * that, if the next request of the application does not arrive before -+ * soft_rt_next_start, then the above requirement on the bandwidth is met. -+ * -+ * The second requirement is that the request pattern of the application is -+ * isochronous, i.e., that, after issuing a request or a batch of requests, -+ * the application stops issuing new requests until all its pending requests -+ * have been completed. After that, the application may issue a new batch, -+ * and so on. -+ * For this reason the next function is invoked to compute -+ * soft_rt_next_start only for applications that meet this requirement, -+ * whereas soft_rt_next_start is set to infinity for applications that do -+ * not. -+ * -+ * Unfortunately, even a greedy application may happen to behave in an -+ * isochronous way if the CPU load is high. In fact, the application may -+ * stop issuing requests while the CPUs are busy serving other processes, -+ * then restart, then stop again for a while, and so on. In addition, if -+ * the disk achieves a low enough throughput with the request pattern -+ * issued by the application (e.g., because the request pattern is random -+ * and/or the device is slow), then the application may meet the above -+ * bandwidth requirement too. To prevent such a greedy application to be -+ * deemed as soft real-time, a further rule is used in the computation of -+ * soft_rt_next_start: soft_rt_next_start must be higher than the current -+ * time plus the maximum time for which the arrival of a request is waited -+ * for when a sync queue becomes idle, namely bfqd->bfq_slice_idle. -+ * This filters out greedy applications, as the latter issue instead their -+ * next request as soon as possible after the last one has been completed -+ * (in contrast, when a batch of requests is completed, a soft real-time -+ * application spends some time processing data). -+ * -+ * Unfortunately, the last filter may easily generate false positives if -+ * only bfqd->bfq_slice_idle is used as a reference time interval and one -+ * or both the following cases occur: -+ * 1) HZ is so low that the duration of a jiffy is comparable to or higher -+ * than bfqd->bfq_slice_idle. This happens, e.g., on slow devices with -+ * HZ=100. -+ * 2) jiffies, instead of increasing at a constant rate, may stop increasing -+ * for a while, then suddenly 'jump' by several units to recover the lost -+ * increments. This seems to happen, e.g., inside virtual machines. -+ * To address this issue, we do not use as a reference time interval just -+ * bfqd->bfq_slice_idle, but bfqd->bfq_slice_idle plus a few jiffies. In -+ * particular we add the minimum number of jiffies for which the filter -+ * seems to be quite precise also in embedded systems and KVM/QEMU virtual -+ * machines. -+ */ -+static inline unsigned long bfq_bfqq_softrt_next_start(struct bfq_data *bfqd, -+ struct bfq_queue *bfqq) -+{ -+ return max(bfqq->last_idle_bklogged + -+ HZ * bfqq->service_from_backlogged / -+ bfqd->bfq_wr_max_softrt_rate, -+ jiffies + bfqq->bfqd->bfq_slice_idle + 4); -+} -+ -+/* -+ * Return the largest-possible time instant such that, for as long as possible, -+ * the current time will be lower than this time instant according to the macro -+ * time_is_before_jiffies(). -+ */ -+static inline unsigned long bfq_infinity_from_now(unsigned long now) -+{ -+ return now + ULONG_MAX / 2; -+} -+ -+/** -+ * bfq_bfqq_expire - expire a queue. -+ * @bfqd: device owning the queue. -+ * @bfqq: the queue to expire. -+ * @compensate: if true, compensate for the time spent idling. -+ * @reason: the reason causing the expiration. -+ * -+ * -+ * If the process associated to the queue is slow (i.e., seeky), or in -+ * case of budget timeout, or, finally, if it is async, we -+ * artificially charge it an entire budget (independently of the -+ * actual service it received). As a consequence, the queue will get -+ * higher timestamps than the correct ones upon reactivation, and -+ * hence it will be rescheduled as if it had received more service -+ * than what it actually received. In the end, this class of processes -+ * will receive less service in proportion to how slowly they consume -+ * their budgets (and hence how seriously they tend to lower the -+ * throughput). -+ * -+ * In contrast, when a queue expires because it has been idling for -+ * too much or because it exhausted its budget, we do not touch the -+ * amount of service it has received. Hence when the queue will be -+ * reactivated and its timestamps updated, the latter will be in sync -+ * with the actual service received by the queue until expiration. -+ * -+ * Charging a full budget to the first type of queues and the exact -+ * service to the others has the effect of using the WF2Q+ policy to -+ * schedule the former on a timeslice basis, without violating the -+ * service domain guarantees of the latter. -+ */ -+static void bfq_bfqq_expire(struct bfq_data *bfqd, -+ struct bfq_queue *bfqq, -+ int compensate, -+ enum bfqq_expiration reason) -+{ -+ int slow; -+ BUG_ON(bfqq != bfqd->in_service_queue); -+ -+ /* Update disk peak rate for autotuning and check whether the -+ * process is slow (see bfq_update_peak_rate). -+ */ -+ slow = bfq_update_peak_rate(bfqd, bfqq, compensate, reason); -+ -+ /* -+ * As above explained, 'punish' slow (i.e., seeky), timed-out -+ * and async queues, to favor sequential sync workloads. -+ * -+ * Processes doing I/O in the slower disk zones will tend to be -+ * slow(er) even if not seeky. Hence, since the estimated peak -+ * rate is actually an average over the disk surface, these -+ * processes may timeout just for bad luck. To avoid punishing -+ * them we do not charge a full budget to a process that -+ * succeeded in consuming at least 2/3 of its budget. -+ */ -+ if (slow || (reason == BFQ_BFQQ_BUDGET_TIMEOUT && -+ bfq_bfqq_budget_left(bfqq) >= bfqq->entity.budget / 3)) -+ bfq_bfqq_charge_full_budget(bfqq); -+ -+ bfqq->service_from_backlogged += bfqq->entity.service; -+ -+ if (BFQQ_SEEKY(bfqq) && reason == BFQ_BFQQ_BUDGET_TIMEOUT && -+ !bfq_bfqq_constantly_seeky(bfqq)) { -+ bfq_mark_bfqq_constantly_seeky(bfqq); -+ if (!blk_queue_nonrot(bfqd->queue)) -+ bfqd->const_seeky_busy_in_flight_queues++; -+ } -+ -+ if (reason == BFQ_BFQQ_TOO_IDLE && -+ bfqq->entity.service <= 2 * bfqq->entity.budget / 10 ) -+ bfq_clear_bfqq_IO_bound(bfqq); -+ -+ if (bfqd->low_latency && bfqq->wr_coeff == 1) -+ bfqq->last_wr_start_finish = jiffies; -+ -+ if (bfqd->low_latency && bfqd->bfq_wr_max_softrt_rate > 0 && -+ RB_EMPTY_ROOT(&bfqq->sort_list)) { -+ /* -+ * If we get here, and there are no outstanding requests, -+ * then the request pattern is isochronous (see the comments -+ * to the function bfq_bfqq_softrt_next_start()). Hence we -+ * can compute soft_rt_next_start. If, instead, the queue -+ * still has outstanding requests, then we have to wait -+ * for the completion of all the outstanding requests to -+ * discover whether the request pattern is actually -+ * isochronous. -+ */ -+ if (bfqq->dispatched == 0) -+ bfqq->soft_rt_next_start = -+ bfq_bfqq_softrt_next_start(bfqd, bfqq); -+ else { -+ /* -+ * The application is still waiting for the -+ * completion of one or more requests: -+ * prevent it from possibly being incorrectly -+ * deemed as soft real-time by setting its -+ * soft_rt_next_start to infinity. In fact, -+ * without this assignment, the application -+ * would be incorrectly deemed as soft -+ * real-time if: -+ * 1) it issued a new request before the -+ * completion of all its in-flight -+ * requests, and -+ * 2) at that time, its soft_rt_next_start -+ * happened to be in the past. -+ */ -+ bfqq->soft_rt_next_start = -+ bfq_infinity_from_now(jiffies); -+ /* -+ * Schedule an update of soft_rt_next_start to when -+ * the task may be discovered to be isochronous. -+ */ -+ bfq_mark_bfqq_softrt_update(bfqq); -+ } -+ } -+ -+ bfq_log_bfqq(bfqd, bfqq, -+ "expire (%d, slow %d, num_disp %d, idle_win %d)", reason, -+ slow, bfqq->dispatched, bfq_bfqq_idle_window(bfqq)); -+ -+ /* -+ * Increase, decrease or leave budget unchanged according to -+ * reason. -+ */ -+ __bfq_bfqq_recalc_budget(bfqd, bfqq, reason); -+ __bfq_bfqq_expire(bfqd, bfqq); -+} -+ -+/* -+ * Budget timeout is not implemented through a dedicated timer, but -+ * just checked on request arrivals and completions, as well as on -+ * idle timer expirations. -+ */ -+static int bfq_bfqq_budget_timeout(struct bfq_queue *bfqq) -+{ -+ if (bfq_bfqq_budget_new(bfqq) || -+ time_before(jiffies, bfqq->budget_timeout)) -+ return 0; -+ return 1; -+} -+ -+/* -+ * If we expire a queue that is waiting for the arrival of a new -+ * request, we may prevent the fictitious timestamp back-shifting that -+ * allows the guarantees of the queue to be preserved (see [1] for -+ * this tricky aspect). Hence we return true only if this condition -+ * does not hold, or if the queue is slow enough to deserve only to be -+ * kicked off for preserving a high throughput. -+*/ -+static inline int bfq_may_expire_for_budg_timeout(struct bfq_queue *bfqq) -+{ -+ bfq_log_bfqq(bfqq->bfqd, bfqq, -+ "may_budget_timeout: wait_request %d left %d timeout %d", -+ bfq_bfqq_wait_request(bfqq), -+ bfq_bfqq_budget_left(bfqq) >= bfqq->entity.budget / 3, -+ bfq_bfqq_budget_timeout(bfqq)); -+ -+ return (!bfq_bfqq_wait_request(bfqq) || -+ bfq_bfqq_budget_left(bfqq) >= bfqq->entity.budget / 3) -+ && -+ bfq_bfqq_budget_timeout(bfqq); -+} -+ -+/* -+ * Device idling is allowed only for the queues for which this function -+ * returns true. For this reason, the return value of this function plays a -+ * critical role for both throughput boosting and service guarantees. The -+ * return value is computed through a logical expression. In this rather -+ * long comment, we try to briefly describe all the details and motivations -+ * behind the components of this logical expression. -+ * -+ * First, the expression is false if bfqq is not sync, or if: bfqq happened -+ * to become active during a large burst of queue activations, and the -+ * pattern of requests bfqq contains boosts the throughput if bfqq is -+ * expired. In fact, queues that became active during a large burst benefit -+ * only from throughput, as discussed in the comments to bfq_handle_burst. -+ * In this respect, expiring bfqq certainly boosts the throughput on NCQ- -+ * capable flash-based devices, whereas, on rotational devices, it boosts -+ * the throughput only if bfqq contains random requests. -+ * -+ * On the opposite end, if (a) bfqq is sync, (b) the above burst-related -+ * condition does not hold, and (c) bfqq is being weight-raised, then the -+ * expression always evaluates to true, as device idling is instrumental -+ * for preserving low-latency guarantees (see [1]). If, instead, conditions -+ * (a) and (b) do hold, but (c) does not, then the expression evaluates to -+ * true only if: (1) bfqq is I/O-bound and has a non-null idle window, and -+ * (2) at least one of the following two conditions holds. -+ * The first condition is that the device is not performing NCQ, because -+ * idling the device most certainly boosts the throughput if this condition -+ * holds and bfqq is I/O-bound and has been granted a non-null idle window. -+ * The second compound condition is made of the logical AND of two components. -+ * -+ * The first component is true only if there is no weight-raised busy -+ * queue. This guarantees that the device is not idled for a sync non- -+ * weight-raised queue when there are busy weight-raised queues. The former -+ * is then expired immediately if empty. Combined with the timestamping -+ * rules of BFQ (see [1] for details), this causes sync non-weight-raised -+ * queues to get a lower number of requests served, and hence to ask for a -+ * lower number of requests from the request pool, before the busy weight- -+ * raised queues get served again. -+ * -+ * This is beneficial for the processes associated with weight-raised -+ * queues, when the request pool is saturated (e.g., in the presence of -+ * write hogs). In fact, if the processes associated with the other queues -+ * ask for requests at a lower rate, then weight-raised processes have a -+ * higher probability to get a request from the pool immediately (or at -+ * least soon) when they need one. Hence they have a higher probability to -+ * actually get a fraction of the disk throughput proportional to their -+ * high weight. This is especially true with NCQ-capable drives, which -+ * enqueue several requests in advance and further reorder internally- -+ * queued requests. -+ * -+ * In the end, mistreating non-weight-raised queues when there are busy -+ * weight-raised queues seems to mitigate starvation problems in the -+ * presence of heavy write workloads and NCQ, and hence to guarantee a -+ * higher application and system responsiveness in these hostile scenarios. -+ * -+ * If the first component of the compound condition is instead true, i.e., -+ * there is no weight-raised busy queue, then the second component of the -+ * compound condition takes into account service-guarantee and throughput -+ * issues related to NCQ (recall that the compound condition is evaluated -+ * only if the device is detected as supporting NCQ). -+ * -+ * As for service guarantees, allowing the drive to enqueue more than one -+ * request at a time, and hence delegating de facto final scheduling -+ * decisions to the drive's internal scheduler, causes loss of control on -+ * the actual request service order. In this respect, when the drive is -+ * allowed to enqueue more than one request at a time, the service -+ * distribution enforced by the drive's internal scheduler is likely to -+ * coincide with the desired device-throughput distribution only in the -+ * following, perfectly symmetric, scenario: -+ * 1) all active queues have the same weight, -+ * 2) all active groups at the same level in the groups tree have the same -+ * weight, -+ * 3) all active groups at the same level in the groups tree have the same -+ * number of children. -+ * -+ * Even in such a scenario, sequential I/O may still receive a preferential -+ * treatment, but this is not likely to be a big issue with flash-based -+ * devices, because of their non-dramatic loss of throughput with random -+ * I/O. Things do differ with HDDs, for which additional care is taken, as -+ * explained after completing the discussion for flash-based devices. -+ * -+ * Unfortunately, keeping the necessary state for evaluating exactly the -+ * above symmetry conditions would be quite complex and time-consuming. -+ * Therefore BFQ evaluates instead the following stronger sub-conditions, -+ * for which it is much easier to maintain the needed state: -+ * 1) all active queues have the same weight, -+ * 2) all active groups have the same weight, -+ * 3) all active groups have at most one active child each. -+ * In particular, the last two conditions are always true if hierarchical -+ * support and the cgroups interface are not enabled, hence no state needs -+ * to be maintained in this case. -+ * -+ * According to the above considerations, the second component of the -+ * compound condition evaluates to true if any of the above symmetry -+ * sub-condition does not hold, or the device is not flash-based. Therefore, -+ * if also the first component is true, then idling is allowed for a sync -+ * queue. These are the only sub-conditions considered if the device is -+ * flash-based, as, for such a device, it is sensible to force idling only -+ * for service-guarantee issues. In fact, as for throughput, idling -+ * NCQ-capable flash-based devices would not boost the throughput even -+ * with sequential I/O; rather it would lower the throughput in proportion -+ * to how fast the device is. In the end, (only) if all the three -+ * sub-conditions hold and the device is flash-based, the compound -+ * condition evaluates to false and therefore no idling is performed. -+ * -+ * As already said, things change with a rotational device, where idling -+ * boosts the throughput with sequential I/O (even with NCQ). Hence, for -+ * such a device the second component of the compound condition evaluates -+ * to true also if the following additional sub-condition does not hold: -+ * the queue is constantly seeky. Unfortunately, this different behavior -+ * with respect to flash-based devices causes an additional asymmetry: if -+ * some sync queues enjoy idling and some other sync queues do not, then -+ * the latter get a low share of the device throughput, simply because the -+ * former get many requests served after being set as in service, whereas -+ * the latter do not. As a consequence, to guarantee the desired throughput -+ * distribution, on HDDs the compound expression evaluates to true (and -+ * hence device idling is performed) also if the following last symmetry -+ * condition does not hold: no other queue is benefiting from idling. Also -+ * this last condition is actually replaced with a simpler-to-maintain and -+ * stronger condition: there is no busy queue which is not constantly seeky -+ * (and hence may also benefit from idling). -+ * -+ * To sum up, when all the required symmetry and throughput-boosting -+ * sub-conditions hold, the second component of the compound condition -+ * evaluates to false, and hence no idling is performed. This helps to -+ * keep the drives' internal queues full on NCQ-capable devices, and hence -+ * to boost the throughput, without causing 'almost' any loss of service -+ * guarantees. The 'almost' follows from the fact that, if the internal -+ * queue of one such device is filled while all the sub-conditions hold, -+ * but at some point in time some sub-condition stops to hold, then it may -+ * become impossible to let requests be served in the new desired order -+ * until all the requests already queued in the device have been served. -+ */ -+static inline bool bfq_bfqq_must_not_expire(struct bfq_queue *bfqq) -+{ -+ struct bfq_data *bfqd = bfqq->bfqd; -+#ifdef CONFIG_CGROUP_BFQIO -+#define symmetric_scenario (!bfqd->active_numerous_groups && \ -+ !bfq_differentiated_weights(bfqd)) -+#else -+#define symmetric_scenario (!bfq_differentiated_weights(bfqd)) -+#endif -+#define cond_for_seeky_on_ncq_hdd (bfq_bfqq_constantly_seeky(bfqq) && \ -+ bfqd->busy_in_flight_queues == \ -+ bfqd->const_seeky_busy_in_flight_queues) -+ -+#define cond_for_expiring_in_burst (bfq_bfqq_in_large_burst(bfqq) && \ -+ bfqd->hw_tag && \ -+ (blk_queue_nonrot(bfqd->queue) || \ -+ bfq_bfqq_constantly_seeky(bfqq))) -+ -+/* -+ * Condition for expiring a non-weight-raised queue (and hence not idling -+ * the device). -+ */ -+#define cond_for_expiring_non_wr (bfqd->hw_tag && \ -+ (bfqd->wr_busy_queues > 0 || \ -+ (symmetric_scenario && \ -+ (blk_queue_nonrot(bfqd->queue) || \ -+ cond_for_seeky_on_ncq_hdd)))) -+ -+ return bfq_bfqq_sync(bfqq) && -+ !cond_for_expiring_in_burst && -+ (bfqq->wr_coeff > 1 || -+ (bfq_bfqq_IO_bound(bfqq) && bfq_bfqq_idle_window(bfqq) && -+ !cond_for_expiring_non_wr) -+ ); -+} -+ -+/* -+ * If the in-service queue is empty but sync, and the function -+ * bfq_bfqq_must_not_expire returns true, then: -+ * 1) the queue must remain in service and cannot be expired, and -+ * 2) the disk must be idled to wait for the possible arrival of a new -+ * request for the queue. -+ * See the comments to the function bfq_bfqq_must_not_expire for the reasons -+ * why performing device idling is the best choice to boost the throughput -+ * and preserve service guarantees when bfq_bfqq_must_not_expire itself -+ * returns true. -+ */ -+static inline bool bfq_bfqq_must_idle(struct bfq_queue *bfqq) -+{ -+ struct bfq_data *bfqd = bfqq->bfqd; -+ -+ return RB_EMPTY_ROOT(&bfqq->sort_list) && bfqd->bfq_slice_idle != 0 && -+ bfq_bfqq_must_not_expire(bfqq); -+} -+ -+/* -+ * Select a queue for service. If we have a current queue in service, -+ * check whether to continue servicing it, or retrieve and set a new one. -+ */ -+static struct bfq_queue *bfq_select_queue(struct bfq_data *bfqd) -+{ -+ struct bfq_queue *bfqq, *new_bfqq = NULL; -+ struct request *next_rq; -+ enum bfqq_expiration reason = BFQ_BFQQ_BUDGET_TIMEOUT; -+ -+ bfqq = bfqd->in_service_queue; -+ if (bfqq == NULL) -+ goto new_queue; -+ -+ bfq_log_bfqq(bfqd, bfqq, "select_queue: already in-service queue"); -+ -+ /* -+ * If another queue has a request waiting within our mean seek -+ * distance, let it run. The expire code will check for close -+ * cooperators and put the close queue at the front of the -+ * service tree. If possible, merge the expiring queue with the -+ * new bfqq. -+ */ -+ new_bfqq = bfq_close_cooperator(bfqd, bfqq); -+ if (new_bfqq != NULL && bfqq->new_bfqq == NULL) -+ bfq_setup_merge(bfqq, new_bfqq); -+ -+ if (bfq_may_expire_for_budg_timeout(bfqq) && -+ !timer_pending(&bfqd->idle_slice_timer) && -+ !bfq_bfqq_must_idle(bfqq)) -+ goto expire; -+ -+ next_rq = bfqq->next_rq; -+ /* -+ * If bfqq has requests queued and it has enough budget left to -+ * serve them, keep the queue, otherwise expire it. -+ */ -+ if (next_rq != NULL) { -+ if (bfq_serv_to_charge(next_rq, bfqq) > -+ bfq_bfqq_budget_left(bfqq)) { -+ reason = BFQ_BFQQ_BUDGET_EXHAUSTED; -+ goto expire; -+ } else { -+ /* -+ * The idle timer may be pending because we may -+ * not disable disk idling even when a new request -+ * arrives. -+ */ -+ if (timer_pending(&bfqd->idle_slice_timer)) { -+ /* -+ * If we get here: 1) at least a new request -+ * has arrived but we have not disabled the -+ * timer because the request was too small, -+ * 2) then the block layer has unplugged -+ * the device, causing the dispatch to be -+ * invoked. -+ * -+ * Since the device is unplugged, now the -+ * requests are probably large enough to -+ * provide a reasonable throughput. -+ * So we disable idling. -+ */ -+ bfq_clear_bfqq_wait_request(bfqq); -+ del_timer(&bfqd->idle_slice_timer); -+ } -+ if (new_bfqq == NULL) -+ goto keep_queue; -+ else -+ goto expire; -+ } -+ } -+ -+ /* -+ * No requests pending. If the in-service queue still has requests -+ * in flight (possibly waiting for a completion) or is idling for a -+ * new request, then keep it. -+ */ -+ if (new_bfqq == NULL && (timer_pending(&bfqd->idle_slice_timer) || -+ (bfqq->dispatched != 0 && bfq_bfqq_must_not_expire(bfqq)))) { -+ bfqq = NULL; -+ goto keep_queue; -+ } else if (new_bfqq != NULL && timer_pending(&bfqd->idle_slice_timer)) { -+ /* -+ * Expiring the queue because there is a close cooperator, -+ * cancel timer. -+ */ -+ bfq_clear_bfqq_wait_request(bfqq); -+ del_timer(&bfqd->idle_slice_timer); -+ } -+ -+ reason = BFQ_BFQQ_NO_MORE_REQUESTS; -+expire: -+ bfq_bfqq_expire(bfqd, bfqq, 0, reason); -+new_queue: -+ bfqq = bfq_set_in_service_queue(bfqd, new_bfqq); -+ bfq_log(bfqd, "select_queue: new queue %d returned", -+ bfqq != NULL ? bfqq->pid : 0); -+keep_queue: -+ return bfqq; -+} -+ -+static void bfq_update_wr_data(struct bfq_data *bfqd, -+ struct bfq_queue *bfqq) -+{ -+ if (bfqq->wr_coeff > 1) { /* queue is being boosted */ -+ struct bfq_entity *entity = &bfqq->entity; -+ -+ bfq_log_bfqq(bfqd, bfqq, -+ "raising period dur %u/%u msec, old coeff %u, w %d(%d)", -+ jiffies_to_msecs(jiffies - -+ bfqq->last_wr_start_finish), -+ jiffies_to_msecs(bfqq->wr_cur_max_time), -+ bfqq->wr_coeff, -+ bfqq->entity.weight, bfqq->entity.orig_weight); -+ -+ BUG_ON(bfqq != bfqd->in_service_queue && entity->weight != -+ entity->orig_weight * bfqq->wr_coeff); -+ if (entity->ioprio_changed) -+ bfq_log_bfqq(bfqd, bfqq, "WARN: pending prio change"); -+ /* -+ * If the queue was activated in a burst, or -+ * too much time has elapsed from the beginning -+ * of this weight-raising, then end weight raising. -+ */ -+ if (bfq_bfqq_in_large_burst(bfqq) || -+ time_is_before_jiffies(bfqq->last_wr_start_finish + -+ bfqq->wr_cur_max_time)) { -+ bfqq->last_wr_start_finish = jiffies; -+ bfq_log_bfqq(bfqd, bfqq, -+ "wrais ending at %lu, rais_max_time %u", -+ bfqq->last_wr_start_finish, -+ jiffies_to_msecs(bfqq->wr_cur_max_time)); -+ bfq_bfqq_end_wr(bfqq); -+ __bfq_entity_update_weight_prio( -+ bfq_entity_service_tree(entity), -+ entity); -+ } -+ } -+} -+ -+/* -+ * Dispatch one request from bfqq, moving it to the request queue -+ * dispatch list. -+ */ -+static int bfq_dispatch_request(struct bfq_data *bfqd, -+ struct bfq_queue *bfqq) -+{ -+ int dispatched = 0; -+ struct request *rq; -+ unsigned long service_to_charge; -+ -+ BUG_ON(RB_EMPTY_ROOT(&bfqq->sort_list)); -+ -+ /* Follow expired path, else get first next available. */ -+ rq = bfq_check_fifo(bfqq); -+ if (rq == NULL) -+ rq = bfqq->next_rq; -+ service_to_charge = bfq_serv_to_charge(rq, bfqq); -+ -+ if (service_to_charge > bfq_bfqq_budget_left(bfqq)) { -+ /* -+ * This may happen if the next rq is chosen in fifo order -+ * instead of sector order. The budget is properly -+ * dimensioned to be always sufficient to serve the next -+ * request only if it is chosen in sector order. The reason -+ * is that it would be quite inefficient and little useful -+ * to always make sure that the budget is large enough to -+ * serve even the possible next rq in fifo order. -+ * In fact, requests are seldom served in fifo order. -+ * -+ * Expire the queue for budget exhaustion, and make sure -+ * that the next act_budget is enough to serve the next -+ * request, even if it comes from the fifo expired path. -+ */ -+ bfqq->next_rq = rq; -+ /* -+ * Since this dispatch is failed, make sure that -+ * a new one will be performed -+ */ -+ if (!bfqd->rq_in_driver) -+ bfq_schedule_dispatch(bfqd); -+ goto expire; -+ } -+ -+ /* Finally, insert request into driver dispatch list. */ -+ bfq_bfqq_served(bfqq, service_to_charge); -+ bfq_dispatch_insert(bfqd->queue, rq); -+ -+ bfq_update_wr_data(bfqd, bfqq); -+ -+ bfq_log_bfqq(bfqd, bfqq, -+ "dispatched %u sec req (%llu), budg left %lu", -+ blk_rq_sectors(rq), -+ (long long unsigned)blk_rq_pos(rq), -+ bfq_bfqq_budget_left(bfqq)); -+ -+ dispatched++; -+ -+ if (bfqd->in_service_bic == NULL) { -+ atomic_long_inc(&RQ_BIC(rq)->icq.ioc->refcount); -+ bfqd->in_service_bic = RQ_BIC(rq); -+ } -+ -+ if (bfqd->busy_queues > 1 && ((!bfq_bfqq_sync(bfqq) && -+ dispatched >= bfqd->bfq_max_budget_async_rq) || -+ bfq_class_idle(bfqq))) -+ goto expire; -+ -+ return dispatched; -+ -+expire: -+ bfq_bfqq_expire(bfqd, bfqq, 0, BFQ_BFQQ_BUDGET_EXHAUSTED); -+ return dispatched; -+} -+ -+static int __bfq_forced_dispatch_bfqq(struct bfq_queue *bfqq) -+{ -+ int dispatched = 0; -+ -+ while (bfqq->next_rq != NULL) { -+ bfq_dispatch_insert(bfqq->bfqd->queue, bfqq->next_rq); -+ dispatched++; -+ } -+ -+ BUG_ON(!list_empty(&bfqq->fifo)); -+ return dispatched; -+} -+ -+/* -+ * Drain our current requests. -+ * Used for barriers and when switching io schedulers on-the-fly. -+ */ -+static int bfq_forced_dispatch(struct bfq_data *bfqd) -+{ -+ struct bfq_queue *bfqq, *n; -+ struct bfq_service_tree *st; -+ int dispatched = 0; -+ -+ bfqq = bfqd->in_service_queue; -+ if (bfqq != NULL) -+ __bfq_bfqq_expire(bfqd, bfqq); -+ -+ /* -+ * Loop through classes, and be careful to leave the scheduler -+ * in a consistent state, as feedback mechanisms and vtime -+ * updates cannot be disabled during the process. -+ */ -+ list_for_each_entry_safe(bfqq, n, &bfqd->active_list, bfqq_list) { -+ st = bfq_entity_service_tree(&bfqq->entity); -+ -+ dispatched += __bfq_forced_dispatch_bfqq(bfqq); -+ bfqq->max_budget = bfq_max_budget(bfqd); -+ -+ bfq_forget_idle(st); -+ } -+ -+ BUG_ON(bfqd->busy_queues != 0); -+ -+ return dispatched; -+} -+ -+static int bfq_dispatch_requests(struct request_queue *q, int force) -+{ -+ struct bfq_data *bfqd = q->elevator->elevator_data; -+ struct bfq_queue *bfqq; -+ int max_dispatch; -+ -+ bfq_log(bfqd, "dispatch requests: %d busy queues", bfqd->busy_queues); -+ if (bfqd->busy_queues == 0) -+ return 0; -+ -+ if (unlikely(force)) -+ return bfq_forced_dispatch(bfqd); -+ -+ bfqq = bfq_select_queue(bfqd); -+ if (bfqq == NULL) -+ return 0; -+ -+ max_dispatch = bfqd->bfq_quantum; -+ if (bfq_class_idle(bfqq)) -+ max_dispatch = 1; -+ -+ if (!bfq_bfqq_sync(bfqq)) -+ max_dispatch = bfqd->bfq_max_budget_async_rq; -+ -+ if (bfqq->dispatched >= max_dispatch) { -+ if (bfqd->busy_queues > 1) -+ return 0; -+ if (bfqq->dispatched >= 4 * max_dispatch) -+ return 0; -+ } -+ -+ if (bfqd->sync_flight != 0 && !bfq_bfqq_sync(bfqq)) -+ return 0; -+ -+ bfq_clear_bfqq_wait_request(bfqq); -+ BUG_ON(timer_pending(&bfqd->idle_slice_timer)); -+ -+ if (!bfq_dispatch_request(bfqd, bfqq)) -+ return 0; -+ -+ bfq_log_bfqq(bfqd, bfqq, "dispatched one request of %d (max_disp %d)", -+ bfqq->pid, max_dispatch); -+ -+ return 1; -+} -+ -+/* -+ * Task holds one reference to the queue, dropped when task exits. Each rq -+ * in-flight on this queue also holds a reference, dropped when rq is freed. -+ * -+ * Queue lock must be held here. -+ */ -+static void bfq_put_queue(struct bfq_queue *bfqq) -+{ -+ struct bfq_data *bfqd = bfqq->bfqd; -+ -+ BUG_ON(atomic_read(&bfqq->ref) <= 0); -+ -+ bfq_log_bfqq(bfqd, bfqq, "put_queue: %p %d", bfqq, -+ atomic_read(&bfqq->ref)); -+ if (!atomic_dec_and_test(&bfqq->ref)) -+ return; -+ -+ BUG_ON(rb_first(&bfqq->sort_list) != NULL); -+ BUG_ON(bfqq->allocated[READ] + bfqq->allocated[WRITE] != 0); -+ BUG_ON(bfqq->entity.tree != NULL); -+ BUG_ON(bfq_bfqq_busy(bfqq)); -+ BUG_ON(bfqd->in_service_queue == bfqq); -+ -+ if (bfq_bfqq_sync(bfqq)) -+ /* -+ * The fact that this queue is being destroyed does not -+ * invalidate the fact that this queue may have been -+ * activated during the current burst. As a consequence, -+ * although the queue does not exist anymore, and hence -+ * needs to be removed from the burst list if there, -+ * the burst size has not to be decremented. -+ */ -+ hlist_del_init(&bfqq->burst_list_node); -+ -+ bfq_log_bfqq(bfqd, bfqq, "put_queue: %p freed", bfqq); -+ -+ kmem_cache_free(bfq_pool, bfqq); -+} -+ -+static void bfq_put_cooperator(struct bfq_queue *bfqq) -+{ -+ struct bfq_queue *__bfqq, *next; -+ -+ /* -+ * If this queue was scheduled to merge with another queue, be -+ * sure to drop the reference taken on that queue (and others in -+ * the merge chain). See bfq_setup_merge and bfq_merge_bfqqs. -+ */ -+ __bfqq = bfqq->new_bfqq; -+ while (__bfqq) { -+ if (__bfqq == bfqq) -+ break; -+ next = __bfqq->new_bfqq; -+ bfq_put_queue(__bfqq); -+ __bfqq = next; -+ } -+} -+ -+static void bfq_exit_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq) -+{ -+ if (bfqq == bfqd->in_service_queue) { -+ __bfq_bfqq_expire(bfqd, bfqq); -+ bfq_schedule_dispatch(bfqd); -+ } -+ -+ bfq_log_bfqq(bfqd, bfqq, "exit_bfqq: %p, %d", bfqq, -+ atomic_read(&bfqq->ref)); -+ -+ bfq_put_cooperator(bfqq); -+ -+ bfq_put_queue(bfqq); -+} -+ -+static inline void bfq_init_icq(struct io_cq *icq) -+{ -+ struct bfq_io_cq *bic = icq_to_bic(icq); -+ -+ bic->ttime.last_end_request = jiffies; -+} -+ -+static void bfq_exit_icq(struct io_cq *icq) -+{ -+ struct bfq_io_cq *bic = icq_to_bic(icq); -+ struct bfq_data *bfqd = bic_to_bfqd(bic); -+ -+ if (bic->bfqq[BLK_RW_ASYNC]) { -+ bfq_exit_bfqq(bfqd, bic->bfqq[BLK_RW_ASYNC]); -+ bic->bfqq[BLK_RW_ASYNC] = NULL; -+ } -+ -+ if (bic->bfqq[BLK_RW_SYNC]) { -+ bfq_exit_bfqq(bfqd, bic->bfqq[BLK_RW_SYNC]); -+ bic->bfqq[BLK_RW_SYNC] = NULL; -+ } -+} -+ -+/* -+ * Update the entity prio values; note that the new values will not -+ * be used until the next (re)activation. -+ */ -+static void bfq_init_prio_data(struct bfq_queue *bfqq, struct bfq_io_cq *bic) -+{ -+ struct task_struct *tsk = current; -+ int ioprio_class; -+ -+ if (!bfq_bfqq_prio_changed(bfqq)) -+ return; -+ -+ ioprio_class = IOPRIO_PRIO_CLASS(bic->ioprio); -+ switch (ioprio_class) { -+ default: -+ dev_err(bfqq->bfqd->queue->backing_dev_info.dev, -+ "bfq: bad prio class %d\n", ioprio_class); -+ case IOPRIO_CLASS_NONE: -+ /* -+ * No prio set, inherit CPU scheduling settings. -+ */ -+ bfqq->entity.new_ioprio = task_nice_ioprio(tsk); -+ bfqq->entity.new_ioprio_class = task_nice_ioclass(tsk); -+ break; -+ case IOPRIO_CLASS_RT: -+ bfqq->entity.new_ioprio = IOPRIO_PRIO_DATA(bic->ioprio); -+ bfqq->entity.new_ioprio_class = IOPRIO_CLASS_RT; -+ break; -+ case IOPRIO_CLASS_BE: -+ bfqq->entity.new_ioprio = IOPRIO_PRIO_DATA(bic->ioprio); -+ bfqq->entity.new_ioprio_class = IOPRIO_CLASS_BE; -+ break; -+ case IOPRIO_CLASS_IDLE: -+ bfqq->entity.new_ioprio_class = IOPRIO_CLASS_IDLE; -+ bfqq->entity.new_ioprio = 7; -+ bfq_clear_bfqq_idle_window(bfqq); -+ break; -+ } -+ -+ if (bfqq->entity.new_ioprio < 0 || -+ bfqq->entity.new_ioprio >= IOPRIO_BE_NR) { -+ printk(KERN_CRIT "bfq_init_prio_data: new_ioprio %d\n", -+ bfqq->entity.new_ioprio); -+ BUG(); -+ } -+ -+ bfqq->entity.ioprio_changed = 1; -+ -+ bfq_clear_bfqq_prio_changed(bfqq); -+} -+ -+static void bfq_changed_ioprio(struct bfq_io_cq *bic) -+{ -+ struct bfq_data *bfqd; -+ struct bfq_queue *bfqq, *new_bfqq; -+ struct bfq_group *bfqg; -+ unsigned long uninitialized_var(flags); -+ int ioprio = bic->icq.ioc->ioprio; -+ -+ bfqd = bfq_get_bfqd_locked(&(bic->icq.q->elevator->elevator_data), -+ &flags); -+ /* -+ * This condition may trigger on a newly created bic, be sure to -+ * drop the lock before returning. -+ */ -+ if (unlikely(bfqd == NULL) || likely(bic->ioprio == ioprio)) -+ goto out; -+ -+ bfqq = bic->bfqq[BLK_RW_ASYNC]; -+ if (bfqq != NULL) { -+ bfqg = container_of(bfqq->entity.sched_data, struct bfq_group, -+ sched_data); -+ new_bfqq = bfq_get_queue(bfqd, bfqg, BLK_RW_ASYNC, bic, -+ GFP_ATOMIC); -+ if (new_bfqq != NULL) { -+ bic->bfqq[BLK_RW_ASYNC] = new_bfqq; -+ bfq_log_bfqq(bfqd, bfqq, -+ "changed_ioprio: bfqq %p %d", -+ bfqq, atomic_read(&bfqq->ref)); -+ bfq_put_queue(bfqq); -+ } -+ } -+ -+ bfqq = bic->bfqq[BLK_RW_SYNC]; -+ if (bfqq != NULL) -+ bfq_mark_bfqq_prio_changed(bfqq); -+ -+ bic->ioprio = ioprio; -+ -+out: -+ bfq_put_bfqd_unlock(bfqd, &flags); -+} -+ -+static void bfq_init_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq, -+ pid_t pid, int is_sync) -+{ -+ RB_CLEAR_NODE(&bfqq->entity.rb_node); -+ INIT_LIST_HEAD(&bfqq->fifo); -+ INIT_HLIST_NODE(&bfqq->burst_list_node); -+ -+ atomic_set(&bfqq->ref, 0); -+ bfqq->bfqd = bfqd; -+ -+ bfq_mark_bfqq_prio_changed(bfqq); -+ -+ if (is_sync) { -+ if (!bfq_class_idle(bfqq)) -+ bfq_mark_bfqq_idle_window(bfqq); -+ bfq_mark_bfqq_sync(bfqq); -+ } -+ bfq_mark_bfqq_IO_bound(bfqq); -+ -+ /* Tentative initial value to trade off between thr and lat */ -+ bfqq->max_budget = (2 * bfq_max_budget(bfqd)) / 3; -+ bfqq->pid = pid; -+ -+ bfqq->wr_coeff = 1; -+ bfqq->last_wr_start_finish = 0; -+ /* -+ * Set to the value for which bfqq will not be deemed as -+ * soft rt when it becomes backlogged. -+ */ -+ bfqq->soft_rt_next_start = bfq_infinity_from_now(jiffies); -+} -+ -+static struct bfq_queue *bfq_find_alloc_queue(struct bfq_data *bfqd, -+ struct bfq_group *bfqg, -+ int is_sync, -+ struct bfq_io_cq *bic, -+ gfp_t gfp_mask) -+{ -+ struct bfq_queue *bfqq, *new_bfqq = NULL; -+ -+retry: -+ /* bic always exists here */ -+ bfqq = bic_to_bfqq(bic, is_sync); -+ -+ /* -+ * Always try a new alloc if we fall back to the OOM bfqq -+ * originally, since it should just be a temporary situation. -+ */ -+ if (bfqq == NULL || bfqq == &bfqd->oom_bfqq) { -+ bfqq = NULL; -+ if (new_bfqq != NULL) { -+ bfqq = new_bfqq; -+ new_bfqq = NULL; -+ } else if (gfp_mask & __GFP_WAIT) { -+ spin_unlock_irq(bfqd->queue->queue_lock); -+ new_bfqq = kmem_cache_alloc_node(bfq_pool, -+ gfp_mask | __GFP_ZERO, -+ bfqd->queue->node); -+ spin_lock_irq(bfqd->queue->queue_lock); -+ if (new_bfqq != NULL) -+ goto retry; -+ } else { -+ bfqq = kmem_cache_alloc_node(bfq_pool, -+ gfp_mask | __GFP_ZERO, -+ bfqd->queue->node); -+ } -+ -+ if (bfqq != NULL) { -+ bfq_init_bfqq(bfqd, bfqq, current->pid, is_sync); -+ bfq_init_prio_data(bfqq, bic); -+ bfq_init_entity(&bfqq->entity, bfqg); -+ bfq_log_bfqq(bfqd, bfqq, "allocated"); -+ } else { -+ bfqq = &bfqd->oom_bfqq; -+ bfq_log_bfqq(bfqd, bfqq, "using oom bfqq"); -+ } -+ } -+ -+ if (new_bfqq != NULL) -+ kmem_cache_free(bfq_pool, new_bfqq); -+ -+ return bfqq; -+} -+ -+static struct bfq_queue **bfq_async_queue_prio(struct bfq_data *bfqd, -+ struct bfq_group *bfqg, -+ int ioprio_class, int ioprio) -+{ -+ switch (ioprio_class) { -+ case IOPRIO_CLASS_RT: -+ return &bfqg->async_bfqq[0][ioprio]; -+ case IOPRIO_CLASS_NONE: -+ ioprio = IOPRIO_NORM; -+ /* fall through */ -+ case IOPRIO_CLASS_BE: -+ return &bfqg->async_bfqq[1][ioprio]; -+ case IOPRIO_CLASS_IDLE: -+ return &bfqg->async_idle_bfqq; -+ default: -+ BUG(); -+ } -+} -+ -+static struct bfq_queue *bfq_get_queue(struct bfq_data *bfqd, -+ struct bfq_group *bfqg, int is_sync, -+ struct bfq_io_cq *bic, gfp_t gfp_mask) -+{ -+ const int ioprio = IOPRIO_PRIO_DATA(bic->ioprio); -+ const int ioprio_class = IOPRIO_PRIO_CLASS(bic->ioprio); -+ struct bfq_queue **async_bfqq = NULL; -+ struct bfq_queue *bfqq = NULL; -+ -+ if (!is_sync) { -+ async_bfqq = bfq_async_queue_prio(bfqd, bfqg, ioprio_class, -+ ioprio); -+ bfqq = *async_bfqq; -+ } -+ -+ if (bfqq == NULL) -+ bfqq = bfq_find_alloc_queue(bfqd, bfqg, is_sync, bic, gfp_mask); -+ -+ /* -+ * Pin the queue now that it's allocated, scheduler exit will -+ * prune it. -+ */ -+ if (!is_sync && *async_bfqq == NULL) { -+ atomic_inc(&bfqq->ref); -+ bfq_log_bfqq(bfqd, bfqq, "get_queue, bfqq not in async: %p, %d", -+ bfqq, atomic_read(&bfqq->ref)); -+ *async_bfqq = bfqq; -+ } -+ -+ atomic_inc(&bfqq->ref); -+ bfq_log_bfqq(bfqd, bfqq, "get_queue, at end: %p, %d", bfqq, -+ atomic_read(&bfqq->ref)); -+ return bfqq; -+} -+ -+static void bfq_update_io_thinktime(struct bfq_data *bfqd, -+ struct bfq_io_cq *bic) -+{ -+ unsigned long elapsed = jiffies - bic->ttime.last_end_request; -+ unsigned long ttime = min(elapsed, 2UL * bfqd->bfq_slice_idle); -+ -+ bic->ttime.ttime_samples = (7*bic->ttime.ttime_samples + 256) / 8; -+ bic->ttime.ttime_total = (7*bic->ttime.ttime_total + 256*ttime) / 8; -+ bic->ttime.ttime_mean = (bic->ttime.ttime_total + 128) / -+ bic->ttime.ttime_samples; -+} -+ -+static void bfq_update_io_seektime(struct bfq_data *bfqd, -+ struct bfq_queue *bfqq, -+ struct request *rq) -+{ -+ sector_t sdist; -+ u64 total; -+ -+ if (bfqq->last_request_pos < blk_rq_pos(rq)) -+ sdist = blk_rq_pos(rq) - bfqq->last_request_pos; -+ else -+ sdist = bfqq->last_request_pos - blk_rq_pos(rq); -+ -+ /* -+ * Don't allow the seek distance to get too large from the -+ * odd fragment, pagein, etc. -+ */ -+ if (bfqq->seek_samples == 0) /* first request, not really a seek */ -+ sdist = 0; -+ else if (bfqq->seek_samples <= 60) /* second & third seek */ -+ sdist = min(sdist, (bfqq->seek_mean * 4) + 2*1024*1024); -+ else -+ sdist = min(sdist, (bfqq->seek_mean * 4) + 2*1024*64); -+ -+ bfqq->seek_samples = (7*bfqq->seek_samples + 256) / 8; -+ bfqq->seek_total = (7*bfqq->seek_total + (u64)256*sdist) / 8; -+ total = bfqq->seek_total + (bfqq->seek_samples/2); -+ do_div(total, bfqq->seek_samples); -+ bfqq->seek_mean = (sector_t)total; -+ -+ bfq_log_bfqq(bfqd, bfqq, "dist=%llu mean=%llu", (u64)sdist, -+ (u64)bfqq->seek_mean); -+} -+ -+/* -+ * Disable idle window if the process thinks too long or seeks so much that -+ * it doesn't matter. -+ */ -+static void bfq_update_idle_window(struct bfq_data *bfqd, -+ struct bfq_queue *bfqq, -+ struct bfq_io_cq *bic) -+{ -+ int enable_idle; -+ -+ /* Don't idle for async or idle io prio class. */ -+ if (!bfq_bfqq_sync(bfqq) || bfq_class_idle(bfqq)) -+ return; -+ -+ enable_idle = bfq_bfqq_idle_window(bfqq); -+ -+ if (atomic_read(&bic->icq.ioc->active_ref) == 0 || -+ bfqd->bfq_slice_idle == 0 || -+ (bfqd->hw_tag && BFQQ_SEEKY(bfqq) && -+ bfqq->wr_coeff == 1)) -+ enable_idle = 0; -+ else if (bfq_sample_valid(bic->ttime.ttime_samples)) { -+ if (bic->ttime.ttime_mean > bfqd->bfq_slice_idle && -+ bfqq->wr_coeff == 1) -+ enable_idle = 0; -+ else -+ enable_idle = 1; -+ } -+ bfq_log_bfqq(bfqd, bfqq, "update_idle_window: enable_idle %d", -+ enable_idle); -+ -+ if (enable_idle) -+ bfq_mark_bfqq_idle_window(bfqq); -+ else -+ bfq_clear_bfqq_idle_window(bfqq); -+} -+ -+/* -+ * Called when a new fs request (rq) is added to bfqq. Check if there's -+ * something we should do about it. -+ */ -+static void bfq_rq_enqueued(struct bfq_data *bfqd, struct bfq_queue *bfqq, -+ struct request *rq) -+{ -+ struct bfq_io_cq *bic = RQ_BIC(rq); -+ -+ if (rq->cmd_flags & REQ_META) -+ bfqq->meta_pending++; -+ -+ bfq_update_io_thinktime(bfqd, bic); -+ bfq_update_io_seektime(bfqd, bfqq, rq); -+ if (!BFQQ_SEEKY(bfqq) && bfq_bfqq_constantly_seeky(bfqq)) { -+ bfq_clear_bfqq_constantly_seeky(bfqq); -+ if (!blk_queue_nonrot(bfqd->queue)) { -+ BUG_ON(!bfqd->const_seeky_busy_in_flight_queues); -+ bfqd->const_seeky_busy_in_flight_queues--; -+ } -+ } -+ if (bfqq->entity.service > bfq_max_budget(bfqd) / 8 || -+ !BFQQ_SEEKY(bfqq)) -+ bfq_update_idle_window(bfqd, bfqq, bic); -+ -+ bfq_log_bfqq(bfqd, bfqq, -+ "rq_enqueued: idle_window=%d (seeky %d, mean %llu)", -+ bfq_bfqq_idle_window(bfqq), BFQQ_SEEKY(bfqq), -+ (long long unsigned)bfqq->seek_mean); -+ -+ bfqq->last_request_pos = blk_rq_pos(rq) + blk_rq_sectors(rq); -+ -+ if (bfqq == bfqd->in_service_queue && bfq_bfqq_wait_request(bfqq)) { -+ int small_req = bfqq->queued[rq_is_sync(rq)] == 1 && -+ blk_rq_sectors(rq) < 32; -+ int budget_timeout = bfq_bfqq_budget_timeout(bfqq); -+ -+ /* -+ * There is just this request queued: if the request -+ * is small and the queue is not to be expired, then -+ * just exit. -+ * -+ * In this way, if the disk is being idled to wait for -+ * a new request from the in-service queue, we avoid -+ * unplugging the device and committing the disk to serve -+ * just a small request. On the contrary, we wait for -+ * the block layer to decide when to unplug the device: -+ * hopefully, new requests will be merged to this one -+ * quickly, then the device will be unplugged and -+ * larger requests will be dispatched. -+ */ -+ if (small_req && !budget_timeout) -+ return; -+ -+ /* -+ * A large enough request arrived, or the queue is to -+ * be expired: in both cases disk idling is to be -+ * stopped, so clear wait_request flag and reset -+ * timer. -+ */ -+ bfq_clear_bfqq_wait_request(bfqq); -+ del_timer(&bfqd->idle_slice_timer); -+ -+ /* -+ * The queue is not empty, because a new request just -+ * arrived. Hence we can safely expire the queue, in -+ * case of budget timeout, without risking that the -+ * timestamps of the queue are not updated correctly. -+ * See [1] for more details. -+ */ -+ if (budget_timeout) -+ bfq_bfqq_expire(bfqd, bfqq, 0, BFQ_BFQQ_BUDGET_TIMEOUT); -+ -+ /* -+ * Let the request rip immediately, or let a new queue be -+ * selected if bfqq has just been expired. -+ */ -+ __blk_run_queue(bfqd->queue); -+ } -+} -+ -+static void bfq_insert_request(struct request_queue *q, struct request *rq) -+{ -+ struct bfq_data *bfqd = q->elevator->elevator_data; -+ struct bfq_queue *bfqq = RQ_BFQQ(rq); -+ -+ assert_spin_locked(bfqd->queue->queue_lock); -+ bfq_init_prio_data(bfqq, RQ_BIC(rq)); -+ -+ bfq_add_request(rq); -+ -+ rq->fifo_time = jiffies + bfqd->bfq_fifo_expire[rq_is_sync(rq)]; -+ list_add_tail(&rq->queuelist, &bfqq->fifo); -+ -+ bfq_rq_enqueued(bfqd, bfqq, rq); -+} -+ -+static void bfq_update_hw_tag(struct bfq_data *bfqd) -+{ -+ bfqd->max_rq_in_driver = max(bfqd->max_rq_in_driver, -+ bfqd->rq_in_driver); -+ -+ if (bfqd->hw_tag == 1) -+ return; -+ -+ /* -+ * This sample is valid if the number of outstanding requests -+ * is large enough to allow a queueing behavior. Note that the -+ * sum is not exact, as it's not taking into account deactivated -+ * requests. -+ */ -+ if (bfqd->rq_in_driver + bfqd->queued < BFQ_HW_QUEUE_THRESHOLD) -+ return; -+ -+ if (bfqd->hw_tag_samples++ < BFQ_HW_QUEUE_SAMPLES) -+ return; -+ -+ bfqd->hw_tag = bfqd->max_rq_in_driver > BFQ_HW_QUEUE_THRESHOLD; -+ bfqd->max_rq_in_driver = 0; -+ bfqd->hw_tag_samples = 0; -+} -+ -+static void bfq_completed_request(struct request_queue *q, struct request *rq) -+{ -+ struct bfq_queue *bfqq = RQ_BFQQ(rq); -+ struct bfq_data *bfqd = bfqq->bfqd; -+ bool sync = bfq_bfqq_sync(bfqq); -+ -+ bfq_log_bfqq(bfqd, bfqq, "completed one req with %u sects left (%d)", -+ blk_rq_sectors(rq), sync); -+ -+ bfq_update_hw_tag(bfqd); -+ -+ BUG_ON(!bfqd->rq_in_driver); -+ BUG_ON(!bfqq->dispatched); -+ bfqd->rq_in_driver--; -+ bfqq->dispatched--; -+ -+ if (!bfqq->dispatched && !bfq_bfqq_busy(bfqq)) { -+ bfq_weights_tree_remove(bfqd, &bfqq->entity, -+ &bfqd->queue_weights_tree); -+ if (!blk_queue_nonrot(bfqd->queue)) { -+ BUG_ON(!bfqd->busy_in_flight_queues); -+ bfqd->busy_in_flight_queues--; -+ if (bfq_bfqq_constantly_seeky(bfqq)) { -+ BUG_ON(!bfqd-> -+ const_seeky_busy_in_flight_queues); -+ bfqd->const_seeky_busy_in_flight_queues--; -+ } -+ } -+ } -+ -+ if (sync) { -+ bfqd->sync_flight--; -+ RQ_BIC(rq)->ttime.last_end_request = jiffies; -+ } -+ -+ /* -+ * If we are waiting to discover whether the request pattern of the -+ * task associated with the queue is actually isochronous, and -+ * both requisites for this condition to hold are satisfied, then -+ * compute soft_rt_next_start (see the comments to the function -+ * bfq_bfqq_softrt_next_start()). -+ */ -+ if (bfq_bfqq_softrt_update(bfqq) && bfqq->dispatched == 0 && -+ RB_EMPTY_ROOT(&bfqq->sort_list)) -+ bfqq->soft_rt_next_start = -+ bfq_bfqq_softrt_next_start(bfqd, bfqq); -+ -+ /* -+ * If this is the in-service queue, check if it needs to be expired, -+ * or if we want to idle in case it has no pending requests. -+ */ -+ if (bfqd->in_service_queue == bfqq) { -+ if (bfq_bfqq_budget_new(bfqq)) -+ bfq_set_budget_timeout(bfqd); -+ -+ if (bfq_bfqq_must_idle(bfqq)) { -+ bfq_arm_slice_timer(bfqd); -+ goto out; -+ } else if (bfq_may_expire_for_budg_timeout(bfqq)) -+ bfq_bfqq_expire(bfqd, bfqq, 0, BFQ_BFQQ_BUDGET_TIMEOUT); -+ else if (RB_EMPTY_ROOT(&bfqq->sort_list) && -+ (bfqq->dispatched == 0 || -+ !bfq_bfqq_must_not_expire(bfqq))) -+ bfq_bfqq_expire(bfqd, bfqq, 0, -+ BFQ_BFQQ_NO_MORE_REQUESTS); -+ } -+ -+ if (!bfqd->rq_in_driver) -+ bfq_schedule_dispatch(bfqd); -+ -+out: -+ return; -+} -+ -+static inline int __bfq_may_queue(struct bfq_queue *bfqq) -+{ -+ if (bfq_bfqq_wait_request(bfqq) && bfq_bfqq_must_alloc(bfqq)) { -+ bfq_clear_bfqq_must_alloc(bfqq); -+ return ELV_MQUEUE_MUST; -+ } -+ -+ return ELV_MQUEUE_MAY; -+} -+ -+static int bfq_may_queue(struct request_queue *q, int rw) -+{ -+ struct bfq_data *bfqd = q->elevator->elevator_data; -+ struct task_struct *tsk = current; -+ struct bfq_io_cq *bic; -+ struct bfq_queue *bfqq; -+ -+ /* -+ * Don't force setup of a queue from here, as a call to may_queue -+ * does not necessarily imply that a request actually will be -+ * queued. So just lookup a possibly existing queue, or return -+ * 'may queue' if that fails. -+ */ -+ bic = bfq_bic_lookup(bfqd, tsk->io_context); -+ if (bic == NULL) -+ return ELV_MQUEUE_MAY; -+ -+ bfqq = bic_to_bfqq(bic, rw_is_sync(rw)); -+ if (bfqq != NULL) { -+ bfq_init_prio_data(bfqq, bic); -+ -+ return __bfq_may_queue(bfqq); -+ } -+ -+ return ELV_MQUEUE_MAY; -+} -+ -+/* -+ * Queue lock held here. -+ */ -+static void bfq_put_request(struct request *rq) -+{ -+ struct bfq_queue *bfqq = RQ_BFQQ(rq); -+ -+ if (bfqq != NULL) { -+ const int rw = rq_data_dir(rq); -+ -+ BUG_ON(!bfqq->allocated[rw]); -+ bfqq->allocated[rw]--; -+ -+ rq->elv.priv[0] = NULL; -+ rq->elv.priv[1] = NULL; -+ -+ bfq_log_bfqq(bfqq->bfqd, bfqq, "put_request %p, %d", -+ bfqq, atomic_read(&bfqq->ref)); -+ bfq_put_queue(bfqq); -+ } -+} -+ -+static struct bfq_queue * -+bfq_merge_bfqqs(struct bfq_data *bfqd, struct bfq_io_cq *bic, -+ struct bfq_queue *bfqq) -+{ -+ bfq_log_bfqq(bfqd, bfqq, "merging with queue %lu", -+ (long unsigned)bfqq->new_bfqq->pid); -+ bic_set_bfqq(bic, bfqq->new_bfqq, 1); -+ bfq_mark_bfqq_coop(bfqq->new_bfqq); -+ bfq_put_queue(bfqq); -+ return bic_to_bfqq(bic, 1); -+} -+ -+/* -+ * Returns NULL if a new bfqq should be allocated, or the old bfqq if this -+ * was the last process referring to said bfqq. -+ */ -+static struct bfq_queue * -+bfq_split_bfqq(struct bfq_io_cq *bic, struct bfq_queue *bfqq) -+{ -+ bfq_log_bfqq(bfqq->bfqd, bfqq, "splitting queue"); -+ if (bfqq_process_refs(bfqq) == 1) { -+ bfqq->pid = current->pid; -+ bfq_clear_bfqq_coop(bfqq); -+ bfq_clear_bfqq_split_coop(bfqq); -+ return bfqq; -+ } -+ -+ bic_set_bfqq(bic, NULL, 1); -+ -+ bfq_put_cooperator(bfqq); -+ -+ bfq_put_queue(bfqq); -+ return NULL; -+} -+ -+/* -+ * Allocate bfq data structures associated with this request. -+ */ -+static int bfq_set_request(struct request_queue *q, struct request *rq, -+ struct bio *bio, gfp_t gfp_mask) -+{ -+ struct bfq_data *bfqd = q->elevator->elevator_data; -+ struct bfq_io_cq *bic = icq_to_bic(rq->elv.icq); -+ const int rw = rq_data_dir(rq); -+ const int is_sync = rq_is_sync(rq); -+ struct bfq_queue *bfqq; -+ struct bfq_group *bfqg; -+ unsigned long flags; -+ -+ might_sleep_if(gfp_mask & __GFP_WAIT); -+ -+ bfq_changed_ioprio(bic); -+ -+ spin_lock_irqsave(q->queue_lock, flags); -+ -+ if (bic == NULL) -+ goto queue_fail; -+ -+ bfqg = bfq_bic_update_cgroup(bic); -+ -+new_queue: -+ bfqq = bic_to_bfqq(bic, is_sync); -+ if (bfqq == NULL || bfqq == &bfqd->oom_bfqq) { -+ bfqq = bfq_get_queue(bfqd, bfqg, is_sync, bic, gfp_mask); -+ bic_set_bfqq(bic, bfqq, is_sync); -+ } else { -+ /* -+ * If the queue was seeky for too long, break it apart. -+ */ -+ if (bfq_bfqq_coop(bfqq) && bfq_bfqq_split_coop(bfqq)) { -+ bfq_log_bfqq(bfqd, bfqq, "breaking apart bfqq"); -+ bfqq = bfq_split_bfqq(bic, bfqq); -+ if (!bfqq) -+ goto new_queue; -+ } -+ -+ /* -+ * Check to see if this queue is scheduled to merge with -+ * another closely cooperating queue. The merging of queues -+ * happens here as it must be done in process context. -+ * The reference on new_bfqq was taken in merge_bfqqs. -+ */ -+ if (bfqq->new_bfqq != NULL) -+ bfqq = bfq_merge_bfqqs(bfqd, bic, bfqq); -+ } -+ -+ bfqq->allocated[rw]++; -+ atomic_inc(&bfqq->ref); -+ bfq_log_bfqq(bfqd, bfqq, "set_request: bfqq %p, %d", bfqq, -+ atomic_read(&bfqq->ref)); -+ -+ rq->elv.priv[0] = bic; -+ rq->elv.priv[1] = bfqq; -+ -+ spin_unlock_irqrestore(q->queue_lock, flags); -+ -+ return 0; -+ -+queue_fail: -+ bfq_schedule_dispatch(bfqd); -+ spin_unlock_irqrestore(q->queue_lock, flags); -+ -+ return 1; -+} -+ -+static void bfq_kick_queue(struct work_struct *work) -+{ -+ struct bfq_data *bfqd = -+ container_of(work, struct bfq_data, unplug_work); -+ struct request_queue *q = bfqd->queue; -+ -+ spin_lock_irq(q->queue_lock); -+ __blk_run_queue(q); -+ spin_unlock_irq(q->queue_lock); -+} -+ -+/* -+ * Handler of the expiration of the timer running if the in-service queue -+ * is idling inside its time slice. -+ */ -+static void bfq_idle_slice_timer(unsigned long data) -+{ -+ struct bfq_data *bfqd = (struct bfq_data *)data; -+ struct bfq_queue *bfqq; -+ unsigned long flags; -+ enum bfqq_expiration reason; -+ -+ spin_lock_irqsave(bfqd->queue->queue_lock, flags); -+ -+ bfqq = bfqd->in_service_queue; -+ /* -+ * Theoretical race here: the in-service queue can be NULL or -+ * different from the queue that was idling if the timer handler -+ * spins on the queue_lock and a new request arrives for the -+ * current queue and there is a full dispatch cycle that changes -+ * the in-service queue. This can hardly happen, but in the worst -+ * case we just expire a queue too early. -+ */ -+ if (bfqq != NULL) { -+ bfq_log_bfqq(bfqd, bfqq, "slice_timer expired"); -+ if (bfq_bfqq_budget_timeout(bfqq)) -+ /* -+ * Also here the queue can be safely expired -+ * for budget timeout without wasting -+ * guarantees -+ */ -+ reason = BFQ_BFQQ_BUDGET_TIMEOUT; -+ else if (bfqq->queued[0] == 0 && bfqq->queued[1] == 0) -+ /* -+ * The queue may not be empty upon timer expiration, -+ * because we may not disable the timer when the -+ * first request of the in-service queue arrives -+ * during disk idling. -+ */ -+ reason = BFQ_BFQQ_TOO_IDLE; -+ else -+ goto schedule_dispatch; -+ -+ bfq_bfqq_expire(bfqd, bfqq, 1, reason); -+ } -+ -+schedule_dispatch: -+ bfq_schedule_dispatch(bfqd); -+ -+ spin_unlock_irqrestore(bfqd->queue->queue_lock, flags); -+} -+ -+static void bfq_shutdown_timer_wq(struct bfq_data *bfqd) -+{ -+ del_timer_sync(&bfqd->idle_slice_timer); -+ cancel_work_sync(&bfqd->unplug_work); -+} -+ -+static inline void __bfq_put_async_bfqq(struct bfq_data *bfqd, -+ struct bfq_queue **bfqq_ptr) -+{ -+ struct bfq_group *root_group = bfqd->root_group; -+ struct bfq_queue *bfqq = *bfqq_ptr; -+ -+ bfq_log(bfqd, "put_async_bfqq: %p", bfqq); -+ if (bfqq != NULL) { -+ bfq_bfqq_move(bfqd, bfqq, &bfqq->entity, root_group); -+ bfq_log_bfqq(bfqd, bfqq, "put_async_bfqq: putting %p, %d", -+ bfqq, atomic_read(&bfqq->ref)); -+ bfq_put_queue(bfqq); -+ *bfqq_ptr = NULL; -+ } -+} -+ -+/* -+ * Release all the bfqg references to its async queues. If we are -+ * deallocating the group these queues may still contain requests, so -+ * we reparent them to the root cgroup (i.e., the only one that will -+ * exist for sure until all the requests on a device are gone). -+ */ -+static void bfq_put_async_queues(struct bfq_data *bfqd, struct bfq_group *bfqg) -+{ -+ int i, j; -+ -+ for (i = 0; i < 2; i++) -+ for (j = 0; j < IOPRIO_BE_NR; j++) -+ __bfq_put_async_bfqq(bfqd, &bfqg->async_bfqq[i][j]); -+ -+ __bfq_put_async_bfqq(bfqd, &bfqg->async_idle_bfqq); -+} -+ -+static void bfq_exit_queue(struct elevator_queue *e) -+{ -+ struct bfq_data *bfqd = e->elevator_data; -+ struct request_queue *q = bfqd->queue; -+ struct bfq_queue *bfqq, *n; -+ -+ bfq_shutdown_timer_wq(bfqd); -+ -+ spin_lock_irq(q->queue_lock); -+ -+ BUG_ON(bfqd->in_service_queue != NULL); -+ list_for_each_entry_safe(bfqq, n, &bfqd->idle_list, bfqq_list) -+ bfq_deactivate_bfqq(bfqd, bfqq, 0); -+ -+ bfq_disconnect_groups(bfqd); -+ spin_unlock_irq(q->queue_lock); -+ -+ bfq_shutdown_timer_wq(bfqd); -+ -+ synchronize_rcu(); -+ -+ BUG_ON(timer_pending(&bfqd->idle_slice_timer)); -+ -+ bfq_free_root_group(bfqd); -+ kfree(bfqd); -+} -+ -+static int bfq_init_queue(struct request_queue *q, struct elevator_type *e) -+{ -+ struct bfq_group *bfqg; -+ struct bfq_data *bfqd; -+ struct elevator_queue *eq; -+ -+ eq = elevator_alloc(q, e); -+ if (eq == NULL) -+ return -ENOMEM; -+ -+ bfqd = kzalloc_node(sizeof(*bfqd), GFP_KERNEL, q->node); -+ if (bfqd == NULL) { -+ kobject_put(&eq->kobj); -+ return -ENOMEM; -+ } -+ eq->elevator_data = bfqd; -+ -+ /* -+ * Our fallback bfqq if bfq_find_alloc_queue() runs into OOM issues. -+ * Grab a permanent reference to it, so that the normal code flow -+ * will not attempt to free it. -+ */ -+ bfq_init_bfqq(bfqd, &bfqd->oom_bfqq, 1, 0); -+ atomic_inc(&bfqd->oom_bfqq.ref); -+ bfqd->oom_bfqq.entity.new_ioprio = BFQ_DEFAULT_QUEUE_IOPRIO; -+ bfqd->oom_bfqq.entity.new_ioprio_class = IOPRIO_CLASS_BE; -+ /* -+ * Trigger weight initialization, according to ioprio, at the -+ * oom_bfqq's first activation. The oom_bfqq's ioprio and ioprio -+ * class won't be changed any more. -+ */ -+ bfqd->oom_bfqq.entity.ioprio_changed = 1; -+ -+ bfqd->queue = q; -+ -+ spin_lock_irq(q->queue_lock); -+ q->elevator = eq; -+ spin_unlock_irq(q->queue_lock); -+ -+ bfqg = bfq_alloc_root_group(bfqd, q->node); -+ if (bfqg == NULL) { -+ kfree(bfqd); -+ kobject_put(&eq->kobj); -+ return -ENOMEM; -+ } -+ -+ bfqd->root_group = bfqg; -+ bfq_init_entity(&bfqd->oom_bfqq.entity, bfqd->root_group); -+#ifdef CONFIG_CGROUP_BFQIO -+ bfqd->active_numerous_groups = 0; -+#endif -+ -+ init_timer(&bfqd->idle_slice_timer); -+ bfqd->idle_slice_timer.function = bfq_idle_slice_timer; -+ bfqd->idle_slice_timer.data = (unsigned long)bfqd; -+ -+ bfqd->rq_pos_tree = RB_ROOT; -+ bfqd->queue_weights_tree = RB_ROOT; -+ bfqd->group_weights_tree = RB_ROOT; -+ -+ INIT_WORK(&bfqd->unplug_work, bfq_kick_queue); -+ -+ INIT_LIST_HEAD(&bfqd->active_list); -+ INIT_LIST_HEAD(&bfqd->idle_list); -+ INIT_HLIST_HEAD(&bfqd->burst_list); -+ -+ bfqd->hw_tag = -1; -+ -+ bfqd->bfq_max_budget = bfq_default_max_budget; -+ -+ bfqd->bfq_quantum = bfq_quantum; -+ bfqd->bfq_fifo_expire[0] = bfq_fifo_expire[0]; -+ bfqd->bfq_fifo_expire[1] = bfq_fifo_expire[1]; -+ bfqd->bfq_back_max = bfq_back_max; -+ bfqd->bfq_back_penalty = bfq_back_penalty; -+ bfqd->bfq_slice_idle = bfq_slice_idle; -+ bfqd->bfq_class_idle_last_service = 0; -+ bfqd->bfq_max_budget_async_rq = bfq_max_budget_async_rq; -+ bfqd->bfq_timeout[BLK_RW_ASYNC] = bfq_timeout_async; -+ bfqd->bfq_timeout[BLK_RW_SYNC] = bfq_timeout_sync; -+ -+ bfqd->bfq_coop_thresh = 2; -+ bfqd->bfq_failed_cooperations = 7000; -+ bfqd->bfq_requests_within_timer = 120; -+ -+ bfqd->bfq_large_burst_thresh = 11; -+ bfqd->bfq_burst_interval = msecs_to_jiffies(500); -+ -+ bfqd->low_latency = true; -+ -+ bfqd->bfq_wr_coeff = 20; -+ bfqd->bfq_wr_rt_max_time = msecs_to_jiffies(300); -+ bfqd->bfq_wr_max_time = 0; -+ bfqd->bfq_wr_min_idle_time = msecs_to_jiffies(2000); -+ bfqd->bfq_wr_min_inter_arr_async = msecs_to_jiffies(500); -+ bfqd->bfq_wr_max_softrt_rate = 7000; /* -+ * Approximate rate required -+ * to playback or record a -+ * high-definition compressed -+ * video. -+ */ -+ bfqd->wr_busy_queues = 0; -+ bfqd->busy_in_flight_queues = 0; -+ bfqd->const_seeky_busy_in_flight_queues = 0; -+ -+ /* -+ * Begin by assuming, optimistically, that the device peak rate is -+ * equal to the highest reference rate. -+ */ -+ bfqd->RT_prod = R_fast[blk_queue_nonrot(bfqd->queue)] * -+ T_fast[blk_queue_nonrot(bfqd->queue)]; -+ bfqd->peak_rate = R_fast[blk_queue_nonrot(bfqd->queue)]; -+ bfqd->device_speed = BFQ_BFQD_FAST; -+ -+ return 0; -+} -+ -+static void bfq_slab_kill(void) -+{ -+ if (bfq_pool != NULL) -+ kmem_cache_destroy(bfq_pool); -+} -+ -+static int __init bfq_slab_setup(void) -+{ -+ bfq_pool = KMEM_CACHE(bfq_queue, 0); -+ if (bfq_pool == NULL) -+ return -ENOMEM; -+ return 0; -+} -+ -+static ssize_t bfq_var_show(unsigned int var, char *page) -+{ -+ return sprintf(page, "%d\n", var); -+} -+ -+static ssize_t bfq_var_store(unsigned long *var, const char *page, -+ size_t count) -+{ -+ unsigned long new_val; -+ int ret = kstrtoul(page, 10, &new_val); -+ -+ if (ret == 0) -+ *var = new_val; -+ -+ return count; -+} -+ -+static ssize_t bfq_wr_max_time_show(struct elevator_queue *e, char *page) -+{ -+ struct bfq_data *bfqd = e->elevator_data; -+ return sprintf(page, "%d\n", bfqd->bfq_wr_max_time > 0 ? -+ jiffies_to_msecs(bfqd->bfq_wr_max_time) : -+ jiffies_to_msecs(bfq_wr_duration(bfqd))); -+} -+ -+static ssize_t bfq_weights_show(struct elevator_queue *e, char *page) -+{ -+ struct bfq_queue *bfqq; -+ struct bfq_data *bfqd = e->elevator_data; -+ ssize_t num_char = 0; -+ -+ num_char += sprintf(page + num_char, "Tot reqs queued %d\n\n", -+ bfqd->queued); -+ -+ spin_lock_irq(bfqd->queue->queue_lock); -+ -+ num_char += sprintf(page + num_char, "Active:\n"); -+ list_for_each_entry(bfqq, &bfqd->active_list, bfqq_list) { -+ num_char += sprintf(page + num_char, -+ "pid%d: weight %hu, nr_queued %d %d, dur %d/%u\n", -+ bfqq->pid, -+ bfqq->entity.weight, -+ bfqq->queued[0], -+ bfqq->queued[1], -+ jiffies_to_msecs(jiffies - bfqq->last_wr_start_finish), -+ jiffies_to_msecs(bfqq->wr_cur_max_time)); -+ } -+ -+ num_char += sprintf(page + num_char, "Idle:\n"); -+ list_for_each_entry(bfqq, &bfqd->idle_list, bfqq_list) { -+ num_char += sprintf(page + num_char, -+ "pid%d: weight %hu, dur %d/%u\n", -+ bfqq->pid, -+ bfqq->entity.weight, -+ jiffies_to_msecs(jiffies - -+ bfqq->last_wr_start_finish), -+ jiffies_to_msecs(bfqq->wr_cur_max_time)); -+ } -+ -+ spin_unlock_irq(bfqd->queue->queue_lock); -+ -+ return num_char; -+} -+ -+#define SHOW_FUNCTION(__FUNC, __VAR, __CONV) \ -+static ssize_t __FUNC(struct elevator_queue *e, char *page) \ -+{ \ -+ struct bfq_data *bfqd = e->elevator_data; \ -+ unsigned int __data = __VAR; \ -+ if (__CONV) \ -+ __data = jiffies_to_msecs(__data); \ -+ return bfq_var_show(__data, (page)); \ -+} -+SHOW_FUNCTION(bfq_quantum_show, bfqd->bfq_quantum, 0); -+SHOW_FUNCTION(bfq_fifo_expire_sync_show, bfqd->bfq_fifo_expire[1], 1); -+SHOW_FUNCTION(bfq_fifo_expire_async_show, bfqd->bfq_fifo_expire[0], 1); -+SHOW_FUNCTION(bfq_back_seek_max_show, bfqd->bfq_back_max, 0); -+SHOW_FUNCTION(bfq_back_seek_penalty_show, bfqd->bfq_back_penalty, 0); -+SHOW_FUNCTION(bfq_slice_idle_show, bfqd->bfq_slice_idle, 1); -+SHOW_FUNCTION(bfq_max_budget_show, bfqd->bfq_user_max_budget, 0); -+SHOW_FUNCTION(bfq_max_budget_async_rq_show, -+ bfqd->bfq_max_budget_async_rq, 0); -+SHOW_FUNCTION(bfq_timeout_sync_show, bfqd->bfq_timeout[BLK_RW_SYNC], 1); -+SHOW_FUNCTION(bfq_timeout_async_show, bfqd->bfq_timeout[BLK_RW_ASYNC], 1); -+SHOW_FUNCTION(bfq_low_latency_show, bfqd->low_latency, 0); -+SHOW_FUNCTION(bfq_wr_coeff_show, bfqd->bfq_wr_coeff, 0); -+SHOW_FUNCTION(bfq_wr_rt_max_time_show, bfqd->bfq_wr_rt_max_time, 1); -+SHOW_FUNCTION(bfq_wr_min_idle_time_show, bfqd->bfq_wr_min_idle_time, 1); -+SHOW_FUNCTION(bfq_wr_min_inter_arr_async_show, bfqd->bfq_wr_min_inter_arr_async, -+ 1); -+SHOW_FUNCTION(bfq_wr_max_softrt_rate_show, bfqd->bfq_wr_max_softrt_rate, 0); -+#undef SHOW_FUNCTION -+ -+#define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV) \ -+static ssize_t \ -+__FUNC(struct elevator_queue *e, const char *page, size_t count) \ -+{ \ -+ struct bfq_data *bfqd = e->elevator_data; \ -+ unsigned long uninitialized_var(__data); \ -+ int ret = bfq_var_store(&__data, (page), count); \ -+ if (__data < (MIN)) \ -+ __data = (MIN); \ -+ else if (__data > (MAX)) \ -+ __data = (MAX); \ -+ if (__CONV) \ -+ *(__PTR) = msecs_to_jiffies(__data); \ -+ else \ -+ *(__PTR) = __data; \ -+ return ret; \ -+} -+STORE_FUNCTION(bfq_quantum_store, &bfqd->bfq_quantum, 1, INT_MAX, 0); -+STORE_FUNCTION(bfq_fifo_expire_sync_store, &bfqd->bfq_fifo_expire[1], 1, -+ INT_MAX, 1); -+STORE_FUNCTION(bfq_fifo_expire_async_store, &bfqd->bfq_fifo_expire[0], 1, -+ INT_MAX, 1); -+STORE_FUNCTION(bfq_back_seek_max_store, &bfqd->bfq_back_max, 0, INT_MAX, 0); -+STORE_FUNCTION(bfq_back_seek_penalty_store, &bfqd->bfq_back_penalty, 1, -+ INT_MAX, 0); -+STORE_FUNCTION(bfq_slice_idle_store, &bfqd->bfq_slice_idle, 0, INT_MAX, 1); -+STORE_FUNCTION(bfq_max_budget_async_rq_store, &bfqd->bfq_max_budget_async_rq, -+ 1, INT_MAX, 0); -+STORE_FUNCTION(bfq_timeout_async_store, &bfqd->bfq_timeout[BLK_RW_ASYNC], 0, -+ INT_MAX, 1); -+STORE_FUNCTION(bfq_wr_coeff_store, &bfqd->bfq_wr_coeff, 1, INT_MAX, 0); -+STORE_FUNCTION(bfq_wr_max_time_store, &bfqd->bfq_wr_max_time, 0, INT_MAX, 1); -+STORE_FUNCTION(bfq_wr_rt_max_time_store, &bfqd->bfq_wr_rt_max_time, 0, INT_MAX, -+ 1); -+STORE_FUNCTION(bfq_wr_min_idle_time_store, &bfqd->bfq_wr_min_idle_time, 0, -+ INT_MAX, 1); -+STORE_FUNCTION(bfq_wr_min_inter_arr_async_store, -+ &bfqd->bfq_wr_min_inter_arr_async, 0, INT_MAX, 1); -+STORE_FUNCTION(bfq_wr_max_softrt_rate_store, &bfqd->bfq_wr_max_softrt_rate, 0, -+ INT_MAX, 0); -+#undef STORE_FUNCTION -+ -+/* do nothing for the moment */ -+static ssize_t bfq_weights_store(struct elevator_queue *e, -+ const char *page, size_t count) -+{ -+ return count; -+} -+ -+static inline unsigned long bfq_estimated_max_budget(struct bfq_data *bfqd) -+{ -+ u64 timeout = jiffies_to_msecs(bfqd->bfq_timeout[BLK_RW_SYNC]); -+ -+ if (bfqd->peak_rate_samples >= BFQ_PEAK_RATE_SAMPLES) -+ return bfq_calc_max_budget(bfqd->peak_rate, timeout); -+ else -+ return bfq_default_max_budget; -+} -+ -+static ssize_t bfq_max_budget_store(struct elevator_queue *e, -+ const char *page, size_t count) -+{ -+ struct bfq_data *bfqd = e->elevator_data; -+ unsigned long uninitialized_var(__data); -+ int ret = bfq_var_store(&__data, (page), count); -+ -+ if (__data == 0) -+ bfqd->bfq_max_budget = bfq_estimated_max_budget(bfqd); -+ else { -+ if (__data > INT_MAX) -+ __data = INT_MAX; -+ bfqd->bfq_max_budget = __data; -+ } -+ -+ bfqd->bfq_user_max_budget = __data; -+ -+ return ret; -+} -+ -+static ssize_t bfq_timeout_sync_store(struct elevator_queue *e, -+ const char *page, size_t count) -+{ -+ struct bfq_data *bfqd = e->elevator_data; -+ unsigned long uninitialized_var(__data); -+ int ret = bfq_var_store(&__data, (page), count); -+ -+ if (__data < 1) -+ __data = 1; -+ else if (__data > INT_MAX) -+ __data = INT_MAX; -+ -+ bfqd->bfq_timeout[BLK_RW_SYNC] = msecs_to_jiffies(__data); -+ if (bfqd->bfq_user_max_budget == 0) -+ bfqd->bfq_max_budget = bfq_estimated_max_budget(bfqd); -+ -+ return ret; -+} -+ -+static ssize_t bfq_low_latency_store(struct elevator_queue *e, -+ const char *page, size_t count) -+{ -+ struct bfq_data *bfqd = e->elevator_data; -+ unsigned long uninitialized_var(__data); -+ int ret = bfq_var_store(&__data, (page), count); -+ -+ if (__data > 1) -+ __data = 1; -+ if (__data == 0 && bfqd->low_latency != 0) -+ bfq_end_wr(bfqd); -+ bfqd->low_latency = __data; -+ -+ return ret; -+} -+ -+#define BFQ_ATTR(name) \ -+ __ATTR(name, S_IRUGO|S_IWUSR, bfq_##name##_show, bfq_##name##_store) -+ -+static struct elv_fs_entry bfq_attrs[] = { -+ BFQ_ATTR(quantum), -+ BFQ_ATTR(fifo_expire_sync), -+ BFQ_ATTR(fifo_expire_async), -+ BFQ_ATTR(back_seek_max), -+ BFQ_ATTR(back_seek_penalty), -+ BFQ_ATTR(slice_idle), -+ BFQ_ATTR(max_budget), -+ BFQ_ATTR(max_budget_async_rq), -+ BFQ_ATTR(timeout_sync), -+ BFQ_ATTR(timeout_async), -+ BFQ_ATTR(low_latency), -+ BFQ_ATTR(wr_coeff), -+ BFQ_ATTR(wr_max_time), -+ BFQ_ATTR(wr_rt_max_time), -+ BFQ_ATTR(wr_min_idle_time), -+ BFQ_ATTR(wr_min_inter_arr_async), -+ BFQ_ATTR(wr_max_softrt_rate), -+ BFQ_ATTR(weights), -+ __ATTR_NULL -+}; -+ -+static struct elevator_type iosched_bfq = { -+ .ops = { -+ .elevator_merge_fn = bfq_merge, -+ .elevator_merged_fn = bfq_merged_request, -+ .elevator_merge_req_fn = bfq_merged_requests, -+ .elevator_allow_merge_fn = bfq_allow_merge, -+ .elevator_dispatch_fn = bfq_dispatch_requests, -+ .elevator_add_req_fn = bfq_insert_request, -+ .elevator_activate_req_fn = bfq_activate_request, -+ .elevator_deactivate_req_fn = bfq_deactivate_request, -+ .elevator_completed_req_fn = bfq_completed_request, -+ .elevator_former_req_fn = elv_rb_former_request, -+ .elevator_latter_req_fn = elv_rb_latter_request, -+ .elevator_init_icq_fn = bfq_init_icq, -+ .elevator_exit_icq_fn = bfq_exit_icq, -+ .elevator_set_req_fn = bfq_set_request, -+ .elevator_put_req_fn = bfq_put_request, -+ .elevator_may_queue_fn = bfq_may_queue, -+ .elevator_init_fn = bfq_init_queue, -+ .elevator_exit_fn = bfq_exit_queue, -+ }, -+ .icq_size = sizeof(struct bfq_io_cq), -+ .icq_align = __alignof__(struct bfq_io_cq), -+ .elevator_attrs = bfq_attrs, -+ .elevator_name = "bfq", -+ .elevator_owner = THIS_MODULE, -+}; -+ -+static int __init bfq_init(void) -+{ -+ /* -+ * Can be 0 on HZ < 1000 setups. -+ */ -+ if (bfq_slice_idle == 0) -+ bfq_slice_idle = 1; -+ -+ if (bfq_timeout_async == 0) -+ bfq_timeout_async = 1; -+ -+ if (bfq_slab_setup()) -+ return -ENOMEM; -+ -+ /* -+ * Times to load large popular applications for the typical systems -+ * installed on the reference devices (see the comments before the -+ * definitions of the two arrays). -+ */ -+ T_slow[0] = msecs_to_jiffies(2600); -+ T_slow[1] = msecs_to_jiffies(1000); -+ T_fast[0] = msecs_to_jiffies(5500); -+ T_fast[1] = msecs_to_jiffies(2000); -+ -+ /* -+ * Thresholds that determine the switch between speed classes (see -+ * the comments before the definition of the array). -+ */ -+ device_speed_thresh[0] = (R_fast[0] + R_slow[0]) / 2; -+ device_speed_thresh[1] = (R_fast[1] + R_slow[1]) / 2; -+ -+ elv_register(&iosched_bfq); -+ pr_info("BFQ I/O-scheduler version: v7r7"); -+ -+ return 0; -+} -+ -+static void __exit bfq_exit(void) -+{ -+ elv_unregister(&iosched_bfq); -+ bfq_slab_kill(); -+} -+ -+module_init(bfq_init); -+module_exit(bfq_exit); -+ -+MODULE_AUTHOR("Fabio Checconi, Paolo Valente"); -+MODULE_LICENSE("GPL"); -diff --git a/block/bfq-sched.c b/block/bfq-sched.c -new file mode 100644 -index 0000000..2931563 ---- /dev/null -+++ b/block/bfq-sched.c -@@ -0,0 +1,1214 @@ -+/* -+ * BFQ: Hierarchical B-WF2Q+ scheduler. -+ * -+ * Based on ideas and code from CFQ: -+ * Copyright (C) 2003 Jens Axboe -+ * -+ * Copyright (C) 2008 Fabio Checconi -+ * Paolo Valente -+ * -+ * Copyright (C) 2010 Paolo Valente -+ */ -+ -+#ifdef CONFIG_CGROUP_BFQIO -+#define for_each_entity(entity) \ -+ for (; entity != NULL; entity = entity->parent) -+ -+#define for_each_entity_safe(entity, parent) \ -+ for (; entity && ({ parent = entity->parent; 1; }); entity = parent) -+ -+static struct bfq_entity *bfq_lookup_next_entity(struct bfq_sched_data *sd, -+ int extract, -+ struct bfq_data *bfqd); -+ -+static inline void bfq_update_budget(struct bfq_entity *next_in_service) -+{ -+ struct bfq_entity *bfqg_entity; -+ struct bfq_group *bfqg; -+ struct bfq_sched_data *group_sd; -+ -+ BUG_ON(next_in_service == NULL); -+ -+ group_sd = next_in_service->sched_data; -+ -+ bfqg = container_of(group_sd, struct bfq_group, sched_data); -+ /* -+ * bfq_group's my_entity field is not NULL only if the group -+ * is not the root group. We must not touch the root entity -+ * as it must never become an in-service entity. -+ */ -+ bfqg_entity = bfqg->my_entity; -+ if (bfqg_entity != NULL) -+ bfqg_entity->budget = next_in_service->budget; -+} -+ -+static int bfq_update_next_in_service(struct bfq_sched_data *sd) -+{ -+ struct bfq_entity *next_in_service; -+ -+ if (sd->in_service_entity != NULL) -+ /* will update/requeue at the end of service */ -+ return 0; -+ -+ /* -+ * NOTE: this can be improved in many ways, such as returning -+ * 1 (and thus propagating upwards the update) only when the -+ * budget changes, or caching the bfqq that will be scheduled -+ * next from this subtree. By now we worry more about -+ * correctness than about performance... -+ */ -+ next_in_service = bfq_lookup_next_entity(sd, 0, NULL); -+ sd->next_in_service = next_in_service; -+ -+ if (next_in_service != NULL) -+ bfq_update_budget(next_in_service); -+ -+ return 1; -+} -+ -+static inline void bfq_check_next_in_service(struct bfq_sched_data *sd, -+ struct bfq_entity *entity) -+{ -+ BUG_ON(sd->next_in_service != entity); -+} -+#else -+#define for_each_entity(entity) \ -+ for (; entity != NULL; entity = NULL) -+ -+#define for_each_entity_safe(entity, parent) \ -+ for (parent = NULL; entity != NULL; entity = parent) -+ -+static inline int bfq_update_next_in_service(struct bfq_sched_data *sd) -+{ -+ return 0; -+} -+ -+static inline void bfq_check_next_in_service(struct bfq_sched_data *sd, -+ struct bfq_entity *entity) -+{ -+} -+ -+static inline void bfq_update_budget(struct bfq_entity *next_in_service) -+{ -+} -+#endif -+ -+/* -+ * Shift for timestamp calculations. This actually limits the maximum -+ * service allowed in one timestamp delta (small shift values increase it), -+ * the maximum total weight that can be used for the queues in the system -+ * (big shift values increase it), and the period of virtual time -+ * wraparounds. -+ */ -+#define WFQ_SERVICE_SHIFT 22 -+ -+/** -+ * bfq_gt - compare two timestamps. -+ * @a: first ts. -+ * @b: second ts. -+ * -+ * Return @a > @b, dealing with wrapping correctly. -+ */ -+static inline int bfq_gt(u64 a, u64 b) -+{ -+ return (s64)(a - b) > 0; -+} -+ -+static inline struct bfq_queue *bfq_entity_to_bfqq(struct bfq_entity *entity) -+{ -+ struct bfq_queue *bfqq = NULL; -+ -+ BUG_ON(entity == NULL); -+ -+ if (entity->my_sched_data == NULL) -+ bfqq = container_of(entity, struct bfq_queue, entity); -+ -+ return bfqq; -+} -+ -+ -+/** -+ * bfq_delta - map service into the virtual time domain. -+ * @service: amount of service. -+ * @weight: scale factor (weight of an entity or weight sum). -+ */ -+static inline u64 bfq_delta(unsigned long service, -+ unsigned long weight) -+{ -+ u64 d = (u64)service << WFQ_SERVICE_SHIFT; -+ -+ do_div(d, weight); -+ return d; -+} -+ -+/** -+ * bfq_calc_finish - assign the finish time to an entity. -+ * @entity: the entity to act upon. -+ * @service: the service to be charged to the entity. -+ */ -+static inline void bfq_calc_finish(struct bfq_entity *entity, -+ unsigned long service) -+{ -+ struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); -+ -+ BUG_ON(entity->weight == 0); -+ -+ entity->finish = entity->start + -+ bfq_delta(service, entity->weight); -+ -+ if (bfqq != NULL) { -+ bfq_log_bfqq(bfqq->bfqd, bfqq, -+ "calc_finish: serv %lu, w %d", -+ service, entity->weight); -+ bfq_log_bfqq(bfqq->bfqd, bfqq, -+ "calc_finish: start %llu, finish %llu, delta %llu", -+ entity->start, entity->finish, -+ bfq_delta(service, entity->weight)); -+ } -+} -+ -+/** -+ * bfq_entity_of - get an entity from a node. -+ * @node: the node field of the entity. -+ * -+ * Convert a node pointer to the relative entity. This is used only -+ * to simplify the logic of some functions and not as the generic -+ * conversion mechanism because, e.g., in the tree walking functions, -+ * the check for a %NULL value would be redundant. -+ */ -+static inline struct bfq_entity *bfq_entity_of(struct rb_node *node) -+{ -+ struct bfq_entity *entity = NULL; -+ -+ if (node != NULL) -+ entity = rb_entry(node, struct bfq_entity, rb_node); -+ -+ return entity; -+} -+ -+/** -+ * bfq_extract - remove an entity from a tree. -+ * @root: the tree root. -+ * @entity: the entity to remove. -+ */ -+static inline void bfq_extract(struct rb_root *root, -+ struct bfq_entity *entity) -+{ -+ BUG_ON(entity->tree != root); -+ -+ entity->tree = NULL; -+ rb_erase(&entity->rb_node, root); -+} -+ -+/** -+ * bfq_idle_extract - extract an entity from the idle tree. -+ * @st: the service tree of the owning @entity. -+ * @entity: the entity being removed. -+ */ -+static void bfq_idle_extract(struct bfq_service_tree *st, -+ struct bfq_entity *entity) -+{ -+ struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); -+ struct rb_node *next; -+ -+ BUG_ON(entity->tree != &st->idle); -+ -+ if (entity == st->first_idle) { -+ next = rb_next(&entity->rb_node); -+ st->first_idle = bfq_entity_of(next); -+ } -+ -+ if (entity == st->last_idle) { -+ next = rb_prev(&entity->rb_node); -+ st->last_idle = bfq_entity_of(next); -+ } -+ -+ bfq_extract(&st->idle, entity); -+ -+ if (bfqq != NULL) -+ list_del(&bfqq->bfqq_list); -+} -+ -+/** -+ * bfq_insert - generic tree insertion. -+ * @root: tree root. -+ * @entity: entity to insert. -+ * -+ * This is used for the idle and the active tree, since they are both -+ * ordered by finish time. -+ */ -+static void bfq_insert(struct rb_root *root, struct bfq_entity *entity) -+{ -+ struct bfq_entity *entry; -+ struct rb_node **node = &root->rb_node; -+ struct rb_node *parent = NULL; -+ -+ BUG_ON(entity->tree != NULL); -+ -+ while (*node != NULL) { -+ parent = *node; -+ entry = rb_entry(parent, struct bfq_entity, rb_node); -+ -+ if (bfq_gt(entry->finish, entity->finish)) -+ node = &parent->rb_left; -+ else -+ node = &parent->rb_right; -+ } -+ -+ rb_link_node(&entity->rb_node, parent, node); -+ rb_insert_color(&entity->rb_node, root); -+ -+ entity->tree = root; -+} -+ -+/** -+ * bfq_update_min - update the min_start field of a entity. -+ * @entity: the entity to update. -+ * @node: one of its children. -+ * -+ * This function is called when @entity may store an invalid value for -+ * min_start due to updates to the active tree. The function assumes -+ * that the subtree rooted at @node (which may be its left or its right -+ * child) has a valid min_start value. -+ */ -+static inline void bfq_update_min(struct bfq_entity *entity, -+ struct rb_node *node) -+{ -+ struct bfq_entity *child; -+ -+ if (node != NULL) { -+ child = rb_entry(node, struct bfq_entity, rb_node); -+ if (bfq_gt(entity->min_start, child->min_start)) -+ entity->min_start = child->min_start; -+ } -+} -+ -+/** -+ * bfq_update_active_node - recalculate min_start. -+ * @node: the node to update. -+ * -+ * @node may have changed position or one of its children may have moved, -+ * this function updates its min_start value. The left and right subtrees -+ * are assumed to hold a correct min_start value. -+ */ -+static inline void bfq_update_active_node(struct rb_node *node) -+{ -+ struct bfq_entity *entity = rb_entry(node, struct bfq_entity, rb_node); -+ -+ entity->min_start = entity->start; -+ bfq_update_min(entity, node->rb_right); -+ bfq_update_min(entity, node->rb_left); -+} -+ -+/** -+ * bfq_update_active_tree - update min_start for the whole active tree. -+ * @node: the starting node. -+ * -+ * @node must be the deepest modified node after an update. This function -+ * updates its min_start using the values held by its children, assuming -+ * that they did not change, and then updates all the nodes that may have -+ * changed in the path to the root. The only nodes that may have changed -+ * are the ones in the path or their siblings. -+ */ -+static void bfq_update_active_tree(struct rb_node *node) -+{ -+ struct rb_node *parent; -+ -+up: -+ bfq_update_active_node(node); -+ -+ parent = rb_parent(node); -+ if (parent == NULL) -+ return; -+ -+ if (node == parent->rb_left && parent->rb_right != NULL) -+ bfq_update_active_node(parent->rb_right); -+ else if (parent->rb_left != NULL) -+ bfq_update_active_node(parent->rb_left); -+ -+ node = parent; -+ goto up; -+} -+ -+static void bfq_weights_tree_add(struct bfq_data *bfqd, -+ struct bfq_entity *entity, -+ struct rb_root *root); -+ -+static void bfq_weights_tree_remove(struct bfq_data *bfqd, -+ struct bfq_entity *entity, -+ struct rb_root *root); -+ -+ -+/** -+ * bfq_active_insert - insert an entity in the active tree of its -+ * group/device. -+ * @st: the service tree of the entity. -+ * @entity: the entity being inserted. -+ * -+ * The active tree is ordered by finish time, but an extra key is kept -+ * per each node, containing the minimum value for the start times of -+ * its children (and the node itself), so it's possible to search for -+ * the eligible node with the lowest finish time in logarithmic time. -+ */ -+static void bfq_active_insert(struct bfq_service_tree *st, -+ struct bfq_entity *entity) -+{ -+ struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); -+ struct rb_node *node = &entity->rb_node; -+#ifdef CONFIG_CGROUP_BFQIO -+ struct bfq_sched_data *sd = NULL; -+ struct bfq_group *bfqg = NULL; -+ struct bfq_data *bfqd = NULL; -+#endif -+ -+ bfq_insert(&st->active, entity); -+ -+ if (node->rb_left != NULL) -+ node = node->rb_left; -+ else if (node->rb_right != NULL) -+ node = node->rb_right; -+ -+ bfq_update_active_tree(node); -+ -+#ifdef CONFIG_CGROUP_BFQIO -+ sd = entity->sched_data; -+ bfqg = container_of(sd, struct bfq_group, sched_data); -+ BUG_ON(!bfqg); -+ bfqd = (struct bfq_data *)bfqg->bfqd; -+#endif -+ if (bfqq != NULL) -+ list_add(&bfqq->bfqq_list, &bfqq->bfqd->active_list); -+#ifdef CONFIG_CGROUP_BFQIO -+ else { /* bfq_group */ -+ BUG_ON(!bfqd); -+ bfq_weights_tree_add(bfqd, entity, &bfqd->group_weights_tree); -+ } -+ if (bfqg != bfqd->root_group) { -+ BUG_ON(!bfqg); -+ BUG_ON(!bfqd); -+ bfqg->active_entities++; -+ if (bfqg->active_entities == 2) -+ bfqd->active_numerous_groups++; -+ } -+#endif -+} -+ -+/** -+ * bfq_ioprio_to_weight - calc a weight from an ioprio. -+ * @ioprio: the ioprio value to convert. -+ */ -+static inline unsigned short bfq_ioprio_to_weight(int ioprio) -+{ -+ BUG_ON(ioprio < 0 || ioprio >= IOPRIO_BE_NR); -+ return IOPRIO_BE_NR - ioprio; -+} -+ -+/** -+ * bfq_weight_to_ioprio - calc an ioprio from a weight. -+ * @weight: the weight value to convert. -+ * -+ * To preserve as mush as possible the old only-ioprio user interface, -+ * 0 is used as an escape ioprio value for weights (numerically) equal or -+ * larger than IOPRIO_BE_NR -+ */ -+static inline unsigned short bfq_weight_to_ioprio(int weight) -+{ -+ BUG_ON(weight < BFQ_MIN_WEIGHT || weight > BFQ_MAX_WEIGHT); -+ return IOPRIO_BE_NR - weight < 0 ? 0 : IOPRIO_BE_NR - weight; -+} -+ -+static inline void bfq_get_entity(struct bfq_entity *entity) -+{ -+ struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); -+ -+ if (bfqq != NULL) { -+ atomic_inc(&bfqq->ref); -+ bfq_log_bfqq(bfqq->bfqd, bfqq, "get_entity: %p %d", -+ bfqq, atomic_read(&bfqq->ref)); -+ } -+} -+ -+/** -+ * bfq_find_deepest - find the deepest node that an extraction can modify. -+ * @node: the node being removed. -+ * -+ * Do the first step of an extraction in an rb tree, looking for the -+ * node that will replace @node, and returning the deepest node that -+ * the following modifications to the tree can touch. If @node is the -+ * last node in the tree return %NULL. -+ */ -+static struct rb_node *bfq_find_deepest(struct rb_node *node) -+{ -+ struct rb_node *deepest; -+ -+ if (node->rb_right == NULL && node->rb_left == NULL) -+ deepest = rb_parent(node); -+ else if (node->rb_right == NULL) -+ deepest = node->rb_left; -+ else if (node->rb_left == NULL) -+ deepest = node->rb_right; -+ else { -+ deepest = rb_next(node); -+ if (deepest->rb_right != NULL) -+ deepest = deepest->rb_right; -+ else if (rb_parent(deepest) != node) -+ deepest = rb_parent(deepest); -+ } -+ -+ return deepest; -+} -+ -+/** -+ * bfq_active_extract - remove an entity from the active tree. -+ * @st: the service_tree containing the tree. -+ * @entity: the entity being removed. -+ */ -+static void bfq_active_extract(struct bfq_service_tree *st, -+ struct bfq_entity *entity) -+{ -+ struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); -+ struct rb_node *node; -+#ifdef CONFIG_CGROUP_BFQIO -+ struct bfq_sched_data *sd = NULL; -+ struct bfq_group *bfqg = NULL; -+ struct bfq_data *bfqd = NULL; -+#endif -+ -+ node = bfq_find_deepest(&entity->rb_node); -+ bfq_extract(&st->active, entity); -+ -+ if (node != NULL) -+ bfq_update_active_tree(node); -+ -+#ifdef CONFIG_CGROUP_BFQIO -+ sd = entity->sched_data; -+ bfqg = container_of(sd, struct bfq_group, sched_data); -+ BUG_ON(!bfqg); -+ bfqd = (struct bfq_data *)bfqg->bfqd; -+#endif -+ if (bfqq != NULL) -+ list_del(&bfqq->bfqq_list); -+#ifdef CONFIG_CGROUP_BFQIO -+ else { /* bfq_group */ -+ BUG_ON(!bfqd); -+ bfq_weights_tree_remove(bfqd, entity, -+ &bfqd->group_weights_tree); -+ } -+ if (bfqg != bfqd->root_group) { -+ BUG_ON(!bfqg); -+ BUG_ON(!bfqd); -+ BUG_ON(!bfqg->active_entities); -+ bfqg->active_entities--; -+ if (bfqg->active_entities == 1) { -+ BUG_ON(!bfqd->active_numerous_groups); -+ bfqd->active_numerous_groups--; -+ } -+ } -+#endif -+} -+ -+/** -+ * bfq_idle_insert - insert an entity into the idle tree. -+ * @st: the service tree containing the tree. -+ * @entity: the entity to insert. -+ */ -+static void bfq_idle_insert(struct bfq_service_tree *st, -+ struct bfq_entity *entity) -+{ -+ struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); -+ struct bfq_entity *first_idle = st->first_idle; -+ struct bfq_entity *last_idle = st->last_idle; -+ -+ if (first_idle == NULL || bfq_gt(first_idle->finish, entity->finish)) -+ st->first_idle = entity; -+ if (last_idle == NULL || bfq_gt(entity->finish, last_idle->finish)) -+ st->last_idle = entity; -+ -+ bfq_insert(&st->idle, entity); -+ -+ if (bfqq != NULL) -+ list_add(&bfqq->bfqq_list, &bfqq->bfqd->idle_list); -+} -+ -+/** -+ * bfq_forget_entity - remove an entity from the wfq trees. -+ * @st: the service tree. -+ * @entity: the entity being removed. -+ * -+ * Update the device status and forget everything about @entity, putting -+ * the device reference to it, if it is a queue. Entities belonging to -+ * groups are not refcounted. -+ */ -+static void bfq_forget_entity(struct bfq_service_tree *st, -+ struct bfq_entity *entity) -+{ -+ struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); -+ struct bfq_sched_data *sd; -+ -+ BUG_ON(!entity->on_st); -+ -+ entity->on_st = 0; -+ st->wsum -= entity->weight; -+ if (bfqq != NULL) { -+ sd = entity->sched_data; -+ bfq_log_bfqq(bfqq->bfqd, bfqq, "forget_entity: %p %d", -+ bfqq, atomic_read(&bfqq->ref)); -+ bfq_put_queue(bfqq); -+ } -+} -+ -+/** -+ * bfq_put_idle_entity - release the idle tree ref of an entity. -+ * @st: service tree for the entity. -+ * @entity: the entity being released. -+ */ -+static void bfq_put_idle_entity(struct bfq_service_tree *st, -+ struct bfq_entity *entity) -+{ -+ bfq_idle_extract(st, entity); -+ bfq_forget_entity(st, entity); -+} -+ -+/** -+ * bfq_forget_idle - update the idle tree if necessary. -+ * @st: the service tree to act upon. -+ * -+ * To preserve the global O(log N) complexity we only remove one entry here; -+ * as the idle tree will not grow indefinitely this can be done safely. -+ */ -+static void bfq_forget_idle(struct bfq_service_tree *st) -+{ -+ struct bfq_entity *first_idle = st->first_idle; -+ struct bfq_entity *last_idle = st->last_idle; -+ -+ if (RB_EMPTY_ROOT(&st->active) && last_idle != NULL && -+ !bfq_gt(last_idle->finish, st->vtime)) { -+ /* -+ * Forget the whole idle tree, increasing the vtime past -+ * the last finish time of idle entities. -+ */ -+ st->vtime = last_idle->finish; -+ } -+ -+ if (first_idle != NULL && !bfq_gt(first_idle->finish, st->vtime)) -+ bfq_put_idle_entity(st, first_idle); -+} -+ -+static struct bfq_service_tree * -+__bfq_entity_update_weight_prio(struct bfq_service_tree *old_st, -+ struct bfq_entity *entity) -+{ -+ struct bfq_service_tree *new_st = old_st; -+ -+ if (entity->ioprio_changed) { -+ struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); -+ unsigned short prev_weight, new_weight; -+ struct bfq_data *bfqd = NULL; -+ struct rb_root *root; -+#ifdef CONFIG_CGROUP_BFQIO -+ struct bfq_sched_data *sd; -+ struct bfq_group *bfqg; -+#endif -+ -+ if (bfqq != NULL) -+ bfqd = bfqq->bfqd; -+#ifdef CONFIG_CGROUP_BFQIO -+ else { -+ sd = entity->my_sched_data; -+ bfqg = container_of(sd, struct bfq_group, sched_data); -+ BUG_ON(!bfqg); -+ bfqd = (struct bfq_data *)bfqg->bfqd; -+ BUG_ON(!bfqd); -+ } -+#endif -+ -+ BUG_ON(old_st->wsum < entity->weight); -+ old_st->wsum -= entity->weight; -+ -+ if (entity->new_weight != entity->orig_weight) { -+ if (entity->new_weight < BFQ_MIN_WEIGHT || -+ entity->new_weight > BFQ_MAX_WEIGHT) { -+ printk(KERN_CRIT "update_weight_prio: " -+ "new_weight %d\n", -+ entity->new_weight); -+ BUG(); -+ } -+ entity->orig_weight = entity->new_weight; -+ entity->ioprio = -+ bfq_weight_to_ioprio(entity->orig_weight); -+ } else if (entity->new_ioprio != entity->ioprio) { -+ entity->ioprio = entity->new_ioprio; -+ entity->orig_weight = -+ bfq_ioprio_to_weight(entity->ioprio); -+ } else -+ entity->new_weight = entity->orig_weight = -+ bfq_ioprio_to_weight(entity->ioprio); -+ -+ entity->ioprio_class = entity->new_ioprio_class; -+ entity->ioprio_changed = 0; -+ -+ /* -+ * NOTE: here we may be changing the weight too early, -+ * this will cause unfairness. The correct approach -+ * would have required additional complexity to defer -+ * weight changes to the proper time instants (i.e., -+ * when entity->finish <= old_st->vtime). -+ */ -+ new_st = bfq_entity_service_tree(entity); -+ -+ prev_weight = entity->weight; -+ new_weight = entity->orig_weight * -+ (bfqq != NULL ? bfqq->wr_coeff : 1); -+ /* -+ * If the weight of the entity changes, remove the entity -+ * from its old weight counter (if there is a counter -+ * associated with the entity), and add it to the counter -+ * associated with its new weight. -+ */ -+ if (prev_weight != new_weight) { -+ root = bfqq ? &bfqd->queue_weights_tree : -+ &bfqd->group_weights_tree; -+ bfq_weights_tree_remove(bfqd, entity, root); -+ } -+ entity->weight = new_weight; -+ /* -+ * Add the entity to its weights tree only if it is -+ * not associated with a weight-raised queue. -+ */ -+ if (prev_weight != new_weight && -+ (bfqq ? bfqq->wr_coeff == 1 : 1)) -+ /* If we get here, root has been initialized. */ -+ bfq_weights_tree_add(bfqd, entity, root); -+ -+ new_st->wsum += entity->weight; -+ -+ if (new_st != old_st) -+ entity->start = new_st->vtime; -+ } -+ -+ return new_st; -+} -+ -+/** -+ * bfq_bfqq_served - update the scheduler status after selection for -+ * service. -+ * @bfqq: the queue being served. -+ * @served: bytes to transfer. -+ * -+ * NOTE: this can be optimized, as the timestamps of upper level entities -+ * are synchronized every time a new bfqq is selected for service. By now, -+ * we keep it to better check consistency. -+ */ -+static void bfq_bfqq_served(struct bfq_queue *bfqq, unsigned long served) -+{ -+ struct bfq_entity *entity = &bfqq->entity; -+ struct bfq_service_tree *st; -+ -+ for_each_entity(entity) { -+ st = bfq_entity_service_tree(entity); -+ -+ entity->service += served; -+ BUG_ON(entity->service > entity->budget); -+ BUG_ON(st->wsum == 0); -+ -+ st->vtime += bfq_delta(served, st->wsum); -+ bfq_forget_idle(st); -+ } -+ bfq_log_bfqq(bfqq->bfqd, bfqq, "bfqq_served %lu secs", served); -+} -+ -+/** -+ * bfq_bfqq_charge_full_budget - set the service to the entity budget. -+ * @bfqq: the queue that needs a service update. -+ * -+ * When it's not possible to be fair in the service domain, because -+ * a queue is not consuming its budget fast enough (the meaning of -+ * fast depends on the timeout parameter), we charge it a full -+ * budget. In this way we should obtain a sort of time-domain -+ * fairness among all the seeky/slow queues. -+ */ -+static inline void bfq_bfqq_charge_full_budget(struct bfq_queue *bfqq) -+{ -+ struct bfq_entity *entity = &bfqq->entity; -+ -+ bfq_log_bfqq(bfqq->bfqd, bfqq, "charge_full_budget"); -+ -+ bfq_bfqq_served(bfqq, entity->budget - entity->service); -+} -+ -+/** -+ * __bfq_activate_entity - activate an entity. -+ * @entity: the entity being activated. -+ * -+ * Called whenever an entity is activated, i.e., it is not active and one -+ * of its children receives a new request, or has to be reactivated due to -+ * budget exhaustion. It uses the current budget of the entity (and the -+ * service received if @entity is active) of the queue to calculate its -+ * timestamps. -+ */ -+static void __bfq_activate_entity(struct bfq_entity *entity) -+{ -+ struct bfq_sched_data *sd = entity->sched_data; -+ struct bfq_service_tree *st = bfq_entity_service_tree(entity); -+ -+ if (entity == sd->in_service_entity) { -+ BUG_ON(entity->tree != NULL); -+ /* -+ * If we are requeueing the current entity we have -+ * to take care of not charging to it service it has -+ * not received. -+ */ -+ bfq_calc_finish(entity, entity->service); -+ entity->start = entity->finish; -+ sd->in_service_entity = NULL; -+ } else if (entity->tree == &st->active) { -+ /* -+ * Requeueing an entity due to a change of some -+ * next_in_service entity below it. We reuse the -+ * old start time. -+ */ -+ bfq_active_extract(st, entity); -+ } else if (entity->tree == &st->idle) { -+ /* -+ * Must be on the idle tree, bfq_idle_extract() will -+ * check for that. -+ */ -+ bfq_idle_extract(st, entity); -+ entity->start = bfq_gt(st->vtime, entity->finish) ? -+ st->vtime : entity->finish; -+ } else { -+ /* -+ * The finish time of the entity may be invalid, and -+ * it is in the past for sure, otherwise the queue -+ * would have been on the idle tree. -+ */ -+ entity->start = st->vtime; -+ st->wsum += entity->weight; -+ bfq_get_entity(entity); -+ -+ BUG_ON(entity->on_st); -+ entity->on_st = 1; -+ } -+ -+ st = __bfq_entity_update_weight_prio(st, entity); -+ bfq_calc_finish(entity, entity->budget); -+ bfq_active_insert(st, entity); -+} -+ -+/** -+ * bfq_activate_entity - activate an entity and its ancestors if necessary. -+ * @entity: the entity to activate. -+ * -+ * Activate @entity and all the entities on the path from it to the root. -+ */ -+static void bfq_activate_entity(struct bfq_entity *entity) -+{ -+ struct bfq_sched_data *sd; -+ -+ for_each_entity(entity) { -+ __bfq_activate_entity(entity); -+ -+ sd = entity->sched_data; -+ if (!bfq_update_next_in_service(sd)) -+ /* -+ * No need to propagate the activation to the -+ * upper entities, as they will be updated when -+ * the in-service entity is rescheduled. -+ */ -+ break; -+ } -+} -+ -+/** -+ * __bfq_deactivate_entity - deactivate an entity from its service tree. -+ * @entity: the entity to deactivate. -+ * @requeue: if false, the entity will not be put into the idle tree. -+ * -+ * Deactivate an entity, independently from its previous state. If the -+ * entity was not on a service tree just return, otherwise if it is on -+ * any scheduler tree, extract it from that tree, and if necessary -+ * and if the caller did not specify @requeue, put it on the idle tree. -+ * -+ * Return %1 if the caller should update the entity hierarchy, i.e., -+ * if the entity was in service or if it was the next_in_service for -+ * its sched_data; return %0 otherwise. -+ */ -+static int __bfq_deactivate_entity(struct bfq_entity *entity, int requeue) -+{ -+ struct bfq_sched_data *sd = entity->sched_data; -+ struct bfq_service_tree *st = bfq_entity_service_tree(entity); -+ int was_in_service = entity == sd->in_service_entity; -+ int ret = 0; -+ -+ if (!entity->on_st) -+ return 0; -+ -+ BUG_ON(was_in_service && entity->tree != NULL); -+ -+ if (was_in_service) { -+ bfq_calc_finish(entity, entity->service); -+ sd->in_service_entity = NULL; -+ } else if (entity->tree == &st->active) -+ bfq_active_extract(st, entity); -+ else if (entity->tree == &st->idle) -+ bfq_idle_extract(st, entity); -+ else if (entity->tree != NULL) -+ BUG(); -+ -+ if (was_in_service || sd->next_in_service == entity) -+ ret = bfq_update_next_in_service(sd); -+ -+ if (!requeue || !bfq_gt(entity->finish, st->vtime)) -+ bfq_forget_entity(st, entity); -+ else -+ bfq_idle_insert(st, entity); -+ -+ BUG_ON(sd->in_service_entity == entity); -+ BUG_ON(sd->next_in_service == entity); -+ -+ return ret; -+} -+ -+/** -+ * bfq_deactivate_entity - deactivate an entity. -+ * @entity: the entity to deactivate. -+ * @requeue: true if the entity can be put on the idle tree -+ */ -+static void bfq_deactivate_entity(struct bfq_entity *entity, int requeue) -+{ -+ struct bfq_sched_data *sd; -+ struct bfq_entity *parent; -+ -+ for_each_entity_safe(entity, parent) { -+ sd = entity->sched_data; -+ -+ if (!__bfq_deactivate_entity(entity, requeue)) -+ /* -+ * The parent entity is still backlogged, and -+ * we don't need to update it as it is still -+ * in service. -+ */ -+ break; -+ -+ if (sd->next_in_service != NULL) -+ /* -+ * The parent entity is still backlogged and -+ * the budgets on the path towards the root -+ * need to be updated. -+ */ -+ goto update; -+ -+ /* -+ * If we reach there the parent is no more backlogged and -+ * we want to propagate the dequeue upwards. -+ */ -+ requeue = 1; -+ } -+ -+ return; -+ -+update: -+ entity = parent; -+ for_each_entity(entity) { -+ __bfq_activate_entity(entity); -+ -+ sd = entity->sched_data; -+ if (!bfq_update_next_in_service(sd)) -+ break; -+ } -+} -+ -+/** -+ * bfq_update_vtime - update vtime if necessary. -+ * @st: the service tree to act upon. -+ * -+ * If necessary update the service tree vtime to have at least one -+ * eligible entity, skipping to its start time. Assumes that the -+ * active tree of the device is not empty. -+ * -+ * NOTE: this hierarchical implementation updates vtimes quite often, -+ * we may end up with reactivated processes getting timestamps after a -+ * vtime skip done because we needed a ->first_active entity on some -+ * intermediate node. -+ */ -+static void bfq_update_vtime(struct bfq_service_tree *st) -+{ -+ struct bfq_entity *entry; -+ struct rb_node *node = st->active.rb_node; -+ -+ entry = rb_entry(node, struct bfq_entity, rb_node); -+ if (bfq_gt(entry->min_start, st->vtime)) { -+ st->vtime = entry->min_start; -+ bfq_forget_idle(st); -+ } -+} -+ -+/** -+ * bfq_first_active_entity - find the eligible entity with -+ * the smallest finish time -+ * @st: the service tree to select from. -+ * -+ * This function searches the first schedulable entity, starting from the -+ * root of the tree and going on the left every time on this side there is -+ * a subtree with at least one eligible (start >= vtime) entity. The path on -+ * the right is followed only if a) the left subtree contains no eligible -+ * entities and b) no eligible entity has been found yet. -+ */ -+static struct bfq_entity *bfq_first_active_entity(struct bfq_service_tree *st) -+{ -+ struct bfq_entity *entry, *first = NULL; -+ struct rb_node *node = st->active.rb_node; -+ -+ while (node != NULL) { -+ entry = rb_entry(node, struct bfq_entity, rb_node); -+left: -+ if (!bfq_gt(entry->start, st->vtime)) -+ first = entry; -+ -+ BUG_ON(bfq_gt(entry->min_start, st->vtime)); -+ -+ if (node->rb_left != NULL) { -+ entry = rb_entry(node->rb_left, -+ struct bfq_entity, rb_node); -+ if (!bfq_gt(entry->min_start, st->vtime)) { -+ node = node->rb_left; -+ goto left; -+ } -+ } -+ if (first != NULL) -+ break; -+ node = node->rb_right; -+ } -+ -+ BUG_ON(first == NULL && !RB_EMPTY_ROOT(&st->active)); -+ return first; -+} -+ -+/** -+ * __bfq_lookup_next_entity - return the first eligible entity in @st. -+ * @st: the service tree. -+ * -+ * Update the virtual time in @st and return the first eligible entity -+ * it contains. -+ */ -+static struct bfq_entity *__bfq_lookup_next_entity(struct bfq_service_tree *st, -+ bool force) -+{ -+ struct bfq_entity *entity, *new_next_in_service = NULL; -+ -+ if (RB_EMPTY_ROOT(&st->active)) -+ return NULL; -+ -+ bfq_update_vtime(st); -+ entity = bfq_first_active_entity(st); -+ BUG_ON(bfq_gt(entity->start, st->vtime)); -+ -+ /* -+ * If the chosen entity does not match with the sched_data's -+ * next_in_service and we are forcedly serving the IDLE priority -+ * class tree, bubble up budget update. -+ */ -+ if (unlikely(force && entity != entity->sched_data->next_in_service)) { -+ new_next_in_service = entity; -+ for_each_entity(new_next_in_service) -+ bfq_update_budget(new_next_in_service); -+ } -+ -+ return entity; -+} -+ -+/** -+ * bfq_lookup_next_entity - return the first eligible entity in @sd. -+ * @sd: the sched_data. -+ * @extract: if true the returned entity will be also extracted from @sd. -+ * -+ * NOTE: since we cache the next_in_service entity at each level of the -+ * hierarchy, the complexity of the lookup can be decreased with -+ * absolutely no effort just returning the cached next_in_service value; -+ * we prefer to do full lookups to test the consistency of * the data -+ * structures. -+ */ -+static struct bfq_entity *bfq_lookup_next_entity(struct bfq_sched_data *sd, -+ int extract, -+ struct bfq_data *bfqd) -+{ -+ struct bfq_service_tree *st = sd->service_tree; -+ struct bfq_entity *entity; -+ int i = 0; -+ -+ BUG_ON(sd->in_service_entity != NULL); -+ -+ if (bfqd != NULL && -+ jiffies - bfqd->bfq_class_idle_last_service > BFQ_CL_IDLE_TIMEOUT) { -+ entity = __bfq_lookup_next_entity(st + BFQ_IOPRIO_CLASSES - 1, -+ true); -+ if (entity != NULL) { -+ i = BFQ_IOPRIO_CLASSES - 1; -+ bfqd->bfq_class_idle_last_service = jiffies; -+ sd->next_in_service = entity; -+ } -+ } -+ for (; i < BFQ_IOPRIO_CLASSES; i++) { -+ entity = __bfq_lookup_next_entity(st + i, false); -+ if (entity != NULL) { -+ if (extract) { -+ bfq_check_next_in_service(sd, entity); -+ bfq_active_extract(st + i, entity); -+ sd->in_service_entity = entity; -+ sd->next_in_service = NULL; -+ } -+ break; -+ } -+ } -+ -+ return entity; -+} -+ -+/* -+ * Get next queue for service. -+ */ -+static struct bfq_queue *bfq_get_next_queue(struct bfq_data *bfqd) -+{ -+ struct bfq_entity *entity = NULL; -+ struct bfq_sched_data *sd; -+ struct bfq_queue *bfqq; -+ -+ BUG_ON(bfqd->in_service_queue != NULL); -+ -+ if (bfqd->busy_queues == 0) -+ return NULL; -+ -+ sd = &bfqd->root_group->sched_data; -+ for (; sd != NULL; sd = entity->my_sched_data) { -+ entity = bfq_lookup_next_entity(sd, 1, bfqd); -+ BUG_ON(entity == NULL); -+ entity->service = 0; -+ } -+ -+ bfqq = bfq_entity_to_bfqq(entity); -+ BUG_ON(bfqq == NULL); -+ -+ return bfqq; -+} -+ -+/* -+ * Forced extraction of the given queue. -+ */ -+static void bfq_get_next_queue_forced(struct bfq_data *bfqd, -+ struct bfq_queue *bfqq) -+{ -+ struct bfq_entity *entity; -+ struct bfq_sched_data *sd; -+ -+ BUG_ON(bfqd->in_service_queue != NULL); -+ -+ entity = &bfqq->entity; -+ /* -+ * Bubble up extraction/update from the leaf to the root. -+ */ -+ for_each_entity(entity) { -+ sd = entity->sched_data; -+ bfq_update_budget(entity); -+ bfq_update_vtime(bfq_entity_service_tree(entity)); -+ bfq_active_extract(bfq_entity_service_tree(entity), entity); -+ sd->in_service_entity = entity; -+ sd->next_in_service = NULL; -+ entity->service = 0; -+ } -+ -+ return; -+} -+ -+static void __bfq_bfqd_reset_in_service(struct bfq_data *bfqd) -+{ -+ if (bfqd->in_service_bic != NULL) { -+ put_io_context(bfqd->in_service_bic->icq.ioc); -+ bfqd->in_service_bic = NULL; -+ } -+ -+ bfqd->in_service_queue = NULL; -+ del_timer(&bfqd->idle_slice_timer); -+} -+ -+static void bfq_deactivate_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq, -+ int requeue) -+{ -+ struct bfq_entity *entity = &bfqq->entity; -+ -+ if (bfqq == bfqd->in_service_queue) -+ __bfq_bfqd_reset_in_service(bfqd); -+ -+ bfq_deactivate_entity(entity, requeue); -+} -+ -+static void bfq_activate_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq) -+{ -+ struct bfq_entity *entity = &bfqq->entity; -+ -+ bfq_activate_entity(entity); -+} -+ -+/* -+ * Called when the bfqq no longer has requests pending, remove it from -+ * the service tree. -+ */ -+static void bfq_del_bfqq_busy(struct bfq_data *bfqd, struct bfq_queue *bfqq, -+ int requeue) -+{ -+ BUG_ON(!bfq_bfqq_busy(bfqq)); -+ BUG_ON(!RB_EMPTY_ROOT(&bfqq->sort_list)); -+ -+ bfq_log_bfqq(bfqd, bfqq, "del from busy"); -+ -+ bfq_clear_bfqq_busy(bfqq); -+ -+ BUG_ON(bfqd->busy_queues == 0); -+ bfqd->busy_queues--; -+ -+ if (!bfqq->dispatched) { -+ bfq_weights_tree_remove(bfqd, &bfqq->entity, -+ &bfqd->queue_weights_tree); -+ if (!blk_queue_nonrot(bfqd->queue)) { -+ BUG_ON(!bfqd->busy_in_flight_queues); -+ bfqd->busy_in_flight_queues--; -+ if (bfq_bfqq_constantly_seeky(bfqq)) { -+ BUG_ON(!bfqd-> -+ const_seeky_busy_in_flight_queues); -+ bfqd->const_seeky_busy_in_flight_queues--; -+ } -+ } -+ } -+ if (bfqq->wr_coeff > 1) -+ bfqd->wr_busy_queues--; -+ -+ bfq_deactivate_bfqq(bfqd, bfqq, requeue); -+} -+ -+/* -+ * Called when an inactive queue receives a new request. -+ */ -+static void bfq_add_bfqq_busy(struct bfq_data *bfqd, struct bfq_queue *bfqq) -+{ -+ BUG_ON(bfq_bfqq_busy(bfqq)); -+ BUG_ON(bfqq == bfqd->in_service_queue); -+ -+ bfq_log_bfqq(bfqd, bfqq, "add to busy"); -+ -+ bfq_activate_bfqq(bfqd, bfqq); -+ -+ bfq_mark_bfqq_busy(bfqq); -+ bfqd->busy_queues++; -+ -+ if (!bfqq->dispatched) { -+ if (bfqq->wr_coeff == 1) -+ bfq_weights_tree_add(bfqd, &bfqq->entity, -+ &bfqd->queue_weights_tree); -+ if (!blk_queue_nonrot(bfqd->queue)) { -+ bfqd->busy_in_flight_queues++; -+ if (bfq_bfqq_constantly_seeky(bfqq)) -+ bfqd->const_seeky_busy_in_flight_queues++; -+ } -+ } -+ if (bfqq->wr_coeff > 1) -+ bfqd->wr_busy_queues++; -+} -diff --git a/block/bfq.h b/block/bfq.h -new file mode 100644 -index 0000000..3c5d85e ---- /dev/null -+++ b/block/bfq.h -@@ -0,0 +1,775 @@ -+/* -+ * BFQ-v7r7 for 3.19.0: data structures and common functions prototypes. -+ * -+ * Based on ideas and code from CFQ: -+ * Copyright (C) 2003 Jens Axboe -+ * -+ * Copyright (C) 2008 Fabio Checconi -+ * Paolo Valente -+ * -+ * Copyright (C) 2010 Paolo Valente -+ */ -+ -+#ifndef _BFQ_H -+#define _BFQ_H -+ -+#include -+#include -+#include -+#include -+ -+#define BFQ_IOPRIO_CLASSES 3 -+#define BFQ_CL_IDLE_TIMEOUT (HZ/5) -+ -+#define BFQ_MIN_WEIGHT 1 -+#define BFQ_MAX_WEIGHT 1000 -+ -+#define BFQ_DEFAULT_QUEUE_IOPRIO 4 -+ -+#define BFQ_DEFAULT_GRP_WEIGHT 10 -+#define BFQ_DEFAULT_GRP_IOPRIO 0 -+#define BFQ_DEFAULT_GRP_CLASS IOPRIO_CLASS_BE -+ -+struct bfq_entity; -+ -+/** -+ * struct bfq_service_tree - per ioprio_class service tree. -+ * @active: tree for active entities (i.e., those backlogged). -+ * @idle: tree for idle entities (i.e., those not backlogged, with V <= F_i). -+ * @first_idle: idle entity with minimum F_i. -+ * @last_idle: idle entity with maximum F_i. -+ * @vtime: scheduler virtual time. -+ * @wsum: scheduler weight sum; active and idle entities contribute to it. -+ * -+ * Each service tree represents a B-WF2Q+ scheduler on its own. Each -+ * ioprio_class has its own independent scheduler, and so its own -+ * bfq_service_tree. All the fields are protected by the queue lock -+ * of the containing bfqd. -+ */ -+struct bfq_service_tree { -+ struct rb_root active; -+ struct rb_root idle; -+ -+ struct bfq_entity *first_idle; -+ struct bfq_entity *last_idle; -+ -+ u64 vtime; -+ unsigned long wsum; -+}; -+ -+/** -+ * struct bfq_sched_data - multi-class scheduler. -+ * @in_service_entity: entity in service. -+ * @next_in_service: head-of-the-line entity in the scheduler. -+ * @service_tree: array of service trees, one per ioprio_class. -+ * -+ * bfq_sched_data is the basic scheduler queue. It supports three -+ * ioprio_classes, and can be used either as a toplevel queue or as -+ * an intermediate queue on a hierarchical setup. -+ * @next_in_service points to the active entity of the sched_data -+ * service trees that will be scheduled next. -+ * -+ * The supported ioprio_classes are the same as in CFQ, in descending -+ * priority order, IOPRIO_CLASS_RT, IOPRIO_CLASS_BE, IOPRIO_CLASS_IDLE. -+ * Requests from higher priority queues are served before all the -+ * requests from lower priority queues; among requests of the same -+ * queue requests are served according to B-WF2Q+. -+ * All the fields are protected by the queue lock of the containing bfqd. -+ */ -+struct bfq_sched_data { -+ struct bfq_entity *in_service_entity; -+ struct bfq_entity *next_in_service; -+ struct bfq_service_tree service_tree[BFQ_IOPRIO_CLASSES]; -+}; -+ -+/** -+ * struct bfq_weight_counter - counter of the number of all active entities -+ * with a given weight. -+ * @weight: weight of the entities that this counter refers to. -+ * @num_active: number of active entities with this weight. -+ * @weights_node: weights tree member (see bfq_data's @queue_weights_tree -+ * and @group_weights_tree). -+ */ -+struct bfq_weight_counter { -+ short int weight; -+ unsigned int num_active; -+ struct rb_node weights_node; -+}; -+ -+/** -+ * struct bfq_entity - schedulable entity. -+ * @rb_node: service_tree member. -+ * @weight_counter: pointer to the weight counter associated with this entity. -+ * @on_st: flag, true if the entity is on a tree (either the active or -+ * the idle one of its service_tree). -+ * @finish: B-WF2Q+ finish timestamp (aka F_i). -+ * @start: B-WF2Q+ start timestamp (aka S_i). -+ * @tree: tree the entity is enqueued into; %NULL if not on a tree. -+ * @min_start: minimum start time of the (active) subtree rooted at -+ * this entity; used for O(log N) lookups into active trees. -+ * @service: service received during the last round of service. -+ * @budget: budget used to calculate F_i; F_i = S_i + @budget / @weight. -+ * @weight: weight of the queue -+ * @parent: parent entity, for hierarchical scheduling. -+ * @my_sched_data: for non-leaf nodes in the cgroup hierarchy, the -+ * associated scheduler queue, %NULL on leaf nodes. -+ * @sched_data: the scheduler queue this entity belongs to. -+ * @ioprio: the ioprio in use. -+ * @new_weight: when a weight change is requested, the new weight value. -+ * @orig_weight: original weight, used to implement weight boosting -+ * @new_ioprio: when an ioprio change is requested, the new ioprio value. -+ * @ioprio_class: the ioprio_class in use. -+ * @new_ioprio_class: when an ioprio_class change is requested, the new -+ * ioprio_class value. -+ * @ioprio_changed: flag, true when the user requested a weight, ioprio or -+ * ioprio_class change. -+ * -+ * A bfq_entity is used to represent either a bfq_queue (leaf node in the -+ * cgroup hierarchy) or a bfq_group into the upper level scheduler. Each -+ * entity belongs to the sched_data of the parent group in the cgroup -+ * hierarchy. Non-leaf entities have also their own sched_data, stored -+ * in @my_sched_data. -+ * -+ * Each entity stores independently its priority values; this would -+ * allow different weights on different devices, but this -+ * functionality is not exported to userspace by now. Priorities and -+ * weights are updated lazily, first storing the new values into the -+ * new_* fields, then setting the @ioprio_changed flag. As soon as -+ * there is a transition in the entity state that allows the priority -+ * update to take place the effective and the requested priority -+ * values are synchronized. -+ * -+ * Unless cgroups are used, the weight value is calculated from the -+ * ioprio to export the same interface as CFQ. When dealing with -+ * ``well-behaved'' queues (i.e., queues that do not spend too much -+ * time to consume their budget and have true sequential behavior, and -+ * when there are no external factors breaking anticipation) the -+ * relative weights at each level of the cgroups hierarchy should be -+ * guaranteed. All the fields are protected by the queue lock of the -+ * containing bfqd. -+ */ -+struct bfq_entity { -+ struct rb_node rb_node; -+ struct bfq_weight_counter *weight_counter; -+ -+ int on_st; -+ -+ u64 finish; -+ u64 start; -+ -+ struct rb_root *tree; -+ -+ u64 min_start; -+ -+ unsigned long service, budget; -+ unsigned short weight, new_weight; -+ unsigned short orig_weight; -+ -+ struct bfq_entity *parent; -+ -+ struct bfq_sched_data *my_sched_data; -+ struct bfq_sched_data *sched_data; -+ -+ unsigned short ioprio, new_ioprio; -+ unsigned short ioprio_class, new_ioprio_class; -+ -+ int ioprio_changed; -+}; -+ -+struct bfq_group; -+ -+/** -+ * struct bfq_queue - leaf schedulable entity. -+ * @ref: reference counter. -+ * @bfqd: parent bfq_data. -+ * @new_bfqq: shared bfq_queue if queue is cooperating with -+ * one or more other queues. -+ * @pos_node: request-position tree member (see bfq_data's @rq_pos_tree). -+ * @pos_root: request-position tree root (see bfq_data's @rq_pos_tree). -+ * @sort_list: sorted list of pending requests. -+ * @next_rq: if fifo isn't expired, next request to serve. -+ * @queued: nr of requests queued in @sort_list. -+ * @allocated: currently allocated requests. -+ * @meta_pending: pending metadata requests. -+ * @fifo: fifo list of requests in sort_list. -+ * @entity: entity representing this queue in the scheduler. -+ * @max_budget: maximum budget allowed from the feedback mechanism. -+ * @budget_timeout: budget expiration (in jiffies). -+ * @dispatched: number of requests on the dispatch list or inside driver. -+ * @flags: status flags. -+ * @bfqq_list: node for active/idle bfqq list inside our bfqd. -+ * @burst_list_node: node for the device's burst list. -+ * @seek_samples: number of seeks sampled -+ * @seek_total: sum of the distances of the seeks sampled -+ * @seek_mean: mean seek distance -+ * @last_request_pos: position of the last request enqueued -+ * @requests_within_timer: number of consecutive pairs of request completion -+ * and arrival, such that the queue becomes idle -+ * after the completion, but the next request arrives -+ * within an idle time slice; used only if the queue's -+ * IO_bound has been cleared. -+ * @pid: pid of the process owning the queue, used for logging purposes. -+ * @last_wr_start_finish: start time of the current weight-raising period if -+ * the @bfq-queue is being weight-raised, otherwise -+ * finish time of the last weight-raising period -+ * @wr_cur_max_time: current max raising time for this queue -+ * @soft_rt_next_start: minimum time instant such that, only if a new -+ * request is enqueued after this time instant in an -+ * idle @bfq_queue with no outstanding requests, then -+ * the task associated with the queue it is deemed as -+ * soft real-time (see the comments to the function -+ * bfq_bfqq_softrt_next_start()). -+ * @last_idle_bklogged: time of the last transition of the @bfq_queue from -+ * idle to backlogged -+ * @service_from_backlogged: cumulative service received from the @bfq_queue -+ * since the last transition from idle to -+ * backlogged -+ * -+ * A bfq_queue is a leaf request queue; it can be associated with an io_context -+ * or more, if it is async or shared between cooperating processes. @cgroup -+ * holds a reference to the cgroup, to be sure that it does not disappear while -+ * a bfqq still references it (mostly to avoid races between request issuing and -+ * task migration followed by cgroup destruction). -+ * All the fields are protected by the queue lock of the containing bfqd. -+ */ -+struct bfq_queue { -+ atomic_t ref; -+ struct bfq_data *bfqd; -+ -+ /* fields for cooperating queues handling */ -+ struct bfq_queue *new_bfqq; -+ struct rb_node pos_node; -+ struct rb_root *pos_root; -+ -+ struct rb_root sort_list; -+ struct request *next_rq; -+ int queued[2]; -+ int allocated[2]; -+ int meta_pending; -+ struct list_head fifo; -+ -+ struct bfq_entity entity; -+ -+ unsigned long max_budget; -+ unsigned long budget_timeout; -+ -+ int dispatched; -+ -+ unsigned int flags; -+ -+ struct list_head bfqq_list; -+ -+ struct hlist_node burst_list_node; -+ -+ unsigned int seek_samples; -+ u64 seek_total; -+ sector_t seek_mean; -+ sector_t last_request_pos; -+ -+ unsigned int requests_within_timer; -+ -+ pid_t pid; -+ -+ /* weight-raising fields */ -+ unsigned long wr_cur_max_time; -+ unsigned long soft_rt_next_start; -+ unsigned long last_wr_start_finish; -+ unsigned int wr_coeff; -+ unsigned long last_idle_bklogged; -+ unsigned long service_from_backlogged; -+}; -+ -+/** -+ * struct bfq_ttime - per process thinktime stats. -+ * @ttime_total: total process thinktime -+ * @ttime_samples: number of thinktime samples -+ * @ttime_mean: average process thinktime -+ */ -+struct bfq_ttime { -+ unsigned long last_end_request; -+ -+ unsigned long ttime_total; -+ unsigned long ttime_samples; -+ unsigned long ttime_mean; -+}; -+ -+/** -+ * struct bfq_io_cq - per (request_queue, io_context) structure. -+ * @icq: associated io_cq structure -+ * @bfqq: array of two process queues, the sync and the async -+ * @ttime: associated @bfq_ttime struct -+ */ -+struct bfq_io_cq { -+ struct io_cq icq; /* must be the first member */ -+ struct bfq_queue *bfqq[2]; -+ struct bfq_ttime ttime; -+ int ioprio; -+}; -+ -+enum bfq_device_speed { -+ BFQ_BFQD_FAST, -+ BFQ_BFQD_SLOW, -+}; -+ -+/** -+ * struct bfq_data - per device data structure. -+ * @queue: request queue for the managed device. -+ * @root_group: root bfq_group for the device. -+ * @rq_pos_tree: rbtree sorted by next_request position, used when -+ * determining if two or more queues have interleaving -+ * requests (see bfq_close_cooperator()). -+ * @active_numerous_groups: number of bfq_groups containing more than one -+ * active @bfq_entity. -+ * @queue_weights_tree: rbtree of weight counters of @bfq_queues, sorted by -+ * weight. Used to keep track of whether all @bfq_queues -+ * have the same weight. The tree contains one counter -+ * for each distinct weight associated to some active -+ * and not weight-raised @bfq_queue (see the comments to -+ * the functions bfq_weights_tree_[add|remove] for -+ * further details). -+ * @group_weights_tree: rbtree of non-queue @bfq_entity weight counters, sorted -+ * by weight. Used to keep track of whether all -+ * @bfq_groups have the same weight. The tree contains -+ * one counter for each distinct weight associated to -+ * some active @bfq_group (see the comments to the -+ * functions bfq_weights_tree_[add|remove] for further -+ * details). -+ * @busy_queues: number of bfq_queues containing requests (including the -+ * queue in service, even if it is idling). -+ * @busy_in_flight_queues: number of @bfq_queues containing pending or -+ * in-flight requests, plus the @bfq_queue in -+ * service, even if idle but waiting for the -+ * possible arrival of its next sync request. This -+ * field is updated only if the device is rotational, -+ * but used only if the device is also NCQ-capable. -+ * The reason why the field is updated also for non- -+ * NCQ-capable rotational devices is related to the -+ * fact that the value of @hw_tag may be set also -+ * later than when busy_in_flight_queues may need to -+ * be incremented for the first time(s). Taking also -+ * this possibility into account, to avoid unbalanced -+ * increments/decrements, would imply more overhead -+ * than just updating busy_in_flight_queues -+ * regardless of the value of @hw_tag. -+ * @const_seeky_busy_in_flight_queues: number of constantly-seeky @bfq_queues -+ * (that is, seeky queues that expired -+ * for budget timeout at least once) -+ * containing pending or in-flight -+ * requests, including the in-service -+ * @bfq_queue if constantly seeky. This -+ * field is updated only if the device -+ * is rotational, but used only if the -+ * device is also NCQ-capable (see the -+ * comments to @busy_in_flight_queues). -+ * @wr_busy_queues: number of weight-raised busy @bfq_queues. -+ * @queued: number of queued requests. -+ * @rq_in_driver: number of requests dispatched and waiting for completion. -+ * @sync_flight: number of sync requests in the driver. -+ * @max_rq_in_driver: max number of reqs in driver in the last -+ * @hw_tag_samples completed requests. -+ * @hw_tag_samples: nr of samples used to calculate hw_tag. -+ * @hw_tag: flag set to one if the driver is showing a queueing behavior. -+ * @budgets_assigned: number of budgets assigned. -+ * @idle_slice_timer: timer set when idling for the next sequential request -+ * from the queue in service. -+ * @unplug_work: delayed work to restart dispatching on the request queue. -+ * @in_service_queue: bfq_queue in service. -+ * @in_service_bic: bfq_io_cq (bic) associated with the @in_service_queue. -+ * @last_position: on-disk position of the last served request. -+ * @last_budget_start: beginning of the last budget. -+ * @last_idling_start: beginning of the last idle slice. -+ * @peak_rate: peak transfer rate observed for a budget. -+ * @peak_rate_samples: number of samples used to calculate @peak_rate. -+ * @bfq_max_budget: maximum budget allotted to a bfq_queue before -+ * rescheduling. -+ * @group_list: list of all the bfq_groups active on the device. -+ * @active_list: list of all the bfq_queues active on the device. -+ * @idle_list: list of all the bfq_queues idle on the device. -+ * @bfq_quantum: max number of requests dispatched per dispatch round. -+ * @bfq_fifo_expire: timeout for async/sync requests; when it expires -+ * requests are served in fifo order. -+ * @bfq_back_penalty: weight of backward seeks wrt forward ones. -+ * @bfq_back_max: maximum allowed backward seek. -+ * @bfq_slice_idle: maximum idling time. -+ * @bfq_user_max_budget: user-configured max budget value -+ * (0 for auto-tuning). -+ * @bfq_max_budget_async_rq: maximum budget (in nr of requests) allotted to -+ * async queues. -+ * @bfq_timeout: timeout for bfq_queues to consume their budget; used to -+ * to prevent seeky queues to impose long latencies to well -+ * behaved ones (this also implies that seeky queues cannot -+ * receive guarantees in the service domain; after a timeout -+ * they are charged for the whole allocated budget, to try -+ * to preserve a behavior reasonably fair among them, but -+ * without service-domain guarantees). -+ * @bfq_coop_thresh: number of queue merges after which a @bfq_queue is -+ * no more granted any weight-raising. -+ * @bfq_failed_cooperations: number of consecutive failed cooperation -+ * chances after which weight-raising is restored -+ * to a queue subject to more than bfq_coop_thresh -+ * queue merges. -+ * @bfq_requests_within_timer: number of consecutive requests that must be -+ * issued within the idle time slice to set -+ * again idling to a queue which was marked as -+ * non-I/O-bound (see the definition of the -+ * IO_bound flag for further details). -+ * @last_ins_in_burst: last time at which a queue entered the current -+ * burst of queues being activated shortly after -+ * each other; for more details about this and the -+ * following parameters related to a burst of -+ * activations, see the comments to the function -+ * @bfq_handle_burst. -+ * @bfq_burst_interval: reference time interval used to decide whether a -+ * queue has been activated shortly after -+ * @last_ins_in_burst. -+ * @burst_size: number of queues in the current burst of queue activations. -+ * @bfq_large_burst_thresh: maximum burst size above which the current -+ * queue-activation burst is deemed as 'large'. -+ * @large_burst: true if a large queue-activation burst is in progress. -+ * @burst_list: head of the burst list (as for the above fields, more details -+ * in the comments to the function bfq_handle_burst). -+ * @low_latency: if set to true, low-latency heuristics are enabled. -+ * @bfq_wr_coeff: maximum factor by which the weight of a weight-raised -+ * queue is multiplied. -+ * @bfq_wr_max_time: maximum duration of a weight-raising period (jiffies). -+ * @bfq_wr_rt_max_time: maximum duration for soft real-time processes. -+ * @bfq_wr_min_idle_time: minimum idle period after which weight-raising -+ * may be reactivated for a queue (in jiffies). -+ * @bfq_wr_min_inter_arr_async: minimum period between request arrivals -+ * after which weight-raising may be -+ * reactivated for an already busy queue -+ * (in jiffies). -+ * @bfq_wr_max_softrt_rate: max service-rate for a soft real-time queue, -+ * sectors per seconds. -+ * @RT_prod: cached value of the product R*T used for computing the maximum -+ * duration of the weight raising automatically. -+ * @device_speed: device-speed class for the low-latency heuristic. -+ * @oom_bfqq: fallback dummy bfqq for extreme OOM conditions. -+ * -+ * All the fields are protected by the @queue lock. -+ */ -+struct bfq_data { -+ struct request_queue *queue; -+ -+ struct bfq_group *root_group; -+ struct rb_root rq_pos_tree; -+ -+#ifdef CONFIG_CGROUP_BFQIO -+ int active_numerous_groups; -+#endif -+ -+ struct rb_root queue_weights_tree; -+ struct rb_root group_weights_tree; -+ -+ int busy_queues; -+ int busy_in_flight_queues; -+ int const_seeky_busy_in_flight_queues; -+ int wr_busy_queues; -+ int queued; -+ int rq_in_driver; -+ int sync_flight; -+ -+ int max_rq_in_driver; -+ int hw_tag_samples; -+ int hw_tag; -+ -+ int budgets_assigned; -+ -+ struct timer_list idle_slice_timer; -+ struct work_struct unplug_work; -+ -+ struct bfq_queue *in_service_queue; -+ struct bfq_io_cq *in_service_bic; -+ -+ sector_t last_position; -+ -+ ktime_t last_budget_start; -+ ktime_t last_idling_start; -+ int peak_rate_samples; -+ u64 peak_rate; -+ unsigned long bfq_max_budget; -+ -+ struct hlist_head group_list; -+ struct list_head active_list; -+ struct list_head idle_list; -+ -+ unsigned int bfq_quantum; -+ unsigned int bfq_fifo_expire[2]; -+ unsigned int bfq_back_penalty; -+ unsigned int bfq_back_max; -+ unsigned int bfq_slice_idle; -+ u64 bfq_class_idle_last_service; -+ -+ unsigned int bfq_user_max_budget; -+ unsigned int bfq_max_budget_async_rq; -+ unsigned int bfq_timeout[2]; -+ -+ unsigned int bfq_coop_thresh; -+ unsigned int bfq_failed_cooperations; -+ unsigned int bfq_requests_within_timer; -+ -+ unsigned long last_ins_in_burst; -+ unsigned long bfq_burst_interval; -+ int burst_size; -+ unsigned long bfq_large_burst_thresh; -+ bool large_burst; -+ struct hlist_head burst_list; -+ -+ bool low_latency; -+ -+ /* parameters of the low_latency heuristics */ -+ unsigned int bfq_wr_coeff; -+ unsigned int bfq_wr_max_time; -+ unsigned int bfq_wr_rt_max_time; -+ unsigned int bfq_wr_min_idle_time; -+ unsigned long bfq_wr_min_inter_arr_async; -+ unsigned int bfq_wr_max_softrt_rate; -+ u64 RT_prod; -+ enum bfq_device_speed device_speed; -+ -+ struct bfq_queue oom_bfqq; -+}; -+ -+enum bfqq_state_flags { -+ BFQ_BFQQ_FLAG_busy = 0, /* has requests or is in service */ -+ BFQ_BFQQ_FLAG_wait_request, /* waiting for a request */ -+ BFQ_BFQQ_FLAG_must_alloc, /* must be allowed rq alloc */ -+ BFQ_BFQQ_FLAG_fifo_expire, /* FIFO checked in this slice */ -+ BFQ_BFQQ_FLAG_idle_window, /* slice idling enabled */ -+ BFQ_BFQQ_FLAG_prio_changed, /* task priority has changed */ -+ BFQ_BFQQ_FLAG_sync, /* synchronous queue */ -+ BFQ_BFQQ_FLAG_budget_new, /* no completion with this budget */ -+ BFQ_BFQQ_FLAG_IO_bound, /* -+ * bfqq has timed-out at least once -+ * having consumed at most 2/10 of -+ * its budget -+ */ -+ BFQ_BFQQ_FLAG_in_large_burst, /* -+ * bfqq activated in a large burst, -+ * see comments to bfq_handle_burst. -+ */ -+ BFQ_BFQQ_FLAG_constantly_seeky, /* -+ * bfqq has proved to be slow and -+ * seeky until budget timeout -+ */ -+ BFQ_BFQQ_FLAG_softrt_update, /* -+ * may need softrt-next-start -+ * update -+ */ -+ BFQ_BFQQ_FLAG_coop, /* bfqq is shared */ -+ BFQ_BFQQ_FLAG_split_coop, /* shared bfqq will be splitted */ -+}; -+ -+#define BFQ_BFQQ_FNS(name) \ -+static inline void bfq_mark_bfqq_##name(struct bfq_queue *bfqq) \ -+{ \ -+ (bfqq)->flags |= (1 << BFQ_BFQQ_FLAG_##name); \ -+} \ -+static inline void bfq_clear_bfqq_##name(struct bfq_queue *bfqq) \ -+{ \ -+ (bfqq)->flags &= ~(1 << BFQ_BFQQ_FLAG_##name); \ -+} \ -+static inline int bfq_bfqq_##name(const struct bfq_queue *bfqq) \ -+{ \ -+ return ((bfqq)->flags & (1 << BFQ_BFQQ_FLAG_##name)) != 0; \ -+} -+ -+BFQ_BFQQ_FNS(busy); -+BFQ_BFQQ_FNS(wait_request); -+BFQ_BFQQ_FNS(must_alloc); -+BFQ_BFQQ_FNS(fifo_expire); -+BFQ_BFQQ_FNS(idle_window); -+BFQ_BFQQ_FNS(prio_changed); -+BFQ_BFQQ_FNS(sync); -+BFQ_BFQQ_FNS(budget_new); -+BFQ_BFQQ_FNS(IO_bound); -+BFQ_BFQQ_FNS(in_large_burst); -+BFQ_BFQQ_FNS(constantly_seeky); -+BFQ_BFQQ_FNS(coop); -+BFQ_BFQQ_FNS(split_coop); -+BFQ_BFQQ_FNS(softrt_update); -+#undef BFQ_BFQQ_FNS -+ -+/* Logging facilities. */ -+#define bfq_log_bfqq(bfqd, bfqq, fmt, args...) \ -+ blk_add_trace_msg((bfqd)->queue, "bfq%d " fmt, (bfqq)->pid, ##args) -+ -+#define bfq_log(bfqd, fmt, args...) \ -+ blk_add_trace_msg((bfqd)->queue, "bfq " fmt, ##args) -+ -+/* Expiration reasons. */ -+enum bfqq_expiration { -+ BFQ_BFQQ_TOO_IDLE = 0, /* -+ * queue has been idling for -+ * too long -+ */ -+ BFQ_BFQQ_BUDGET_TIMEOUT, /* budget took too long to be used */ -+ BFQ_BFQQ_BUDGET_EXHAUSTED, /* budget consumed */ -+ BFQ_BFQQ_NO_MORE_REQUESTS, /* the queue has no more requests */ -+}; -+ -+#ifdef CONFIG_CGROUP_BFQIO -+/** -+ * struct bfq_group - per (device, cgroup) data structure. -+ * @entity: schedulable entity to insert into the parent group sched_data. -+ * @sched_data: own sched_data, to contain child entities (they may be -+ * both bfq_queues and bfq_groups). -+ * @group_node: node to be inserted into the bfqio_cgroup->group_data -+ * list of the containing cgroup's bfqio_cgroup. -+ * @bfqd_node: node to be inserted into the @bfqd->group_list list -+ * of the groups active on the same device; used for cleanup. -+ * @bfqd: the bfq_data for the device this group acts upon. -+ * @async_bfqq: array of async queues for all the tasks belonging to -+ * the group, one queue per ioprio value per ioprio_class, -+ * except for the idle class that has only one queue. -+ * @async_idle_bfqq: async queue for the idle class (ioprio is ignored). -+ * @my_entity: pointer to @entity, %NULL for the toplevel group; used -+ * to avoid too many special cases during group creation/ -+ * migration. -+ * @active_entities: number of active entities belonging to the group; -+ * unused for the root group. Used to know whether there -+ * are groups with more than one active @bfq_entity -+ * (see the comments to the function -+ * bfq_bfqq_must_not_expire()). -+ * -+ * Each (device, cgroup) pair has its own bfq_group, i.e., for each cgroup -+ * there is a set of bfq_groups, each one collecting the lower-level -+ * entities belonging to the group that are acting on the same device. -+ * -+ * Locking works as follows: -+ * o @group_node is protected by the bfqio_cgroup lock, and is accessed -+ * via RCU from its readers. -+ * o @bfqd is protected by the queue lock, RCU is used to access it -+ * from the readers. -+ * o All the other fields are protected by the @bfqd queue lock. -+ */ -+struct bfq_group { -+ struct bfq_entity entity; -+ struct bfq_sched_data sched_data; -+ -+ struct hlist_node group_node; -+ struct hlist_node bfqd_node; -+ -+ void *bfqd; -+ -+ struct bfq_queue *async_bfqq[2][IOPRIO_BE_NR]; -+ struct bfq_queue *async_idle_bfqq; -+ -+ struct bfq_entity *my_entity; -+ -+ int active_entities; -+}; -+ -+/** -+ * struct bfqio_cgroup - bfq cgroup data structure. -+ * @css: subsystem state for bfq in the containing cgroup. -+ * @online: flag marked when the subsystem is inserted. -+ * @weight: cgroup weight. -+ * @ioprio: cgroup ioprio. -+ * @ioprio_class: cgroup ioprio_class. -+ * @lock: spinlock that protects @ioprio, @ioprio_class and @group_data. -+ * @group_data: list containing the bfq_group belonging to this cgroup. -+ * -+ * @group_data is accessed using RCU, with @lock protecting the updates, -+ * @ioprio and @ioprio_class are protected by @lock. -+ */ -+struct bfqio_cgroup { -+ struct cgroup_subsys_state css; -+ bool online; -+ -+ unsigned short weight, ioprio, ioprio_class; -+ -+ spinlock_t lock; -+ struct hlist_head group_data; -+}; -+#else -+struct bfq_group { -+ struct bfq_sched_data sched_data; -+ -+ struct bfq_queue *async_bfqq[2][IOPRIO_BE_NR]; -+ struct bfq_queue *async_idle_bfqq; -+}; -+#endif -+ -+static inline struct bfq_service_tree * -+bfq_entity_service_tree(struct bfq_entity *entity) -+{ -+ struct bfq_sched_data *sched_data = entity->sched_data; -+ unsigned int idx = entity->ioprio_class - 1; -+ -+ BUG_ON(idx >= BFQ_IOPRIO_CLASSES); -+ BUG_ON(sched_data == NULL); -+ -+ return sched_data->service_tree + idx; -+} -+ -+static inline struct bfq_queue *bic_to_bfqq(struct bfq_io_cq *bic, -+ bool is_sync) -+{ -+ return bic->bfqq[is_sync]; -+} -+ -+static inline void bic_set_bfqq(struct bfq_io_cq *bic, -+ struct bfq_queue *bfqq, bool is_sync) -+{ -+ bic->bfqq[is_sync] = bfqq; -+} -+ -+static inline struct bfq_data *bic_to_bfqd(struct bfq_io_cq *bic) -+{ -+ return bic->icq.q->elevator->elevator_data; -+} -+ -+/** -+ * bfq_get_bfqd_locked - get a lock to a bfqd using a RCU protected pointer. -+ * @ptr: a pointer to a bfqd. -+ * @flags: storage for the flags to be saved. -+ * -+ * This function allows bfqg->bfqd to be protected by the -+ * queue lock of the bfqd they reference; the pointer is dereferenced -+ * under RCU, so the storage for bfqd is assured to be safe as long -+ * as the RCU read side critical section does not end. After the -+ * bfqd->queue->queue_lock is taken the pointer is rechecked, to be -+ * sure that no other writer accessed it. If we raced with a writer, -+ * the function returns NULL, with the queue unlocked, otherwise it -+ * returns the dereferenced pointer, with the queue locked. -+ */ -+static inline struct bfq_data *bfq_get_bfqd_locked(void **ptr, -+ unsigned long *flags) -+{ -+ struct bfq_data *bfqd; -+ -+ rcu_read_lock(); -+ bfqd = rcu_dereference(*(struct bfq_data **)ptr); -+ -+ if (bfqd != NULL) { -+ spin_lock_irqsave(bfqd->queue->queue_lock, *flags); -+ if (*ptr == bfqd) -+ goto out; -+ spin_unlock_irqrestore(bfqd->queue->queue_lock, *flags); -+ } -+ -+ bfqd = NULL; -+out: -+ rcu_read_unlock(); -+ return bfqd; -+} -+ -+static inline void bfq_put_bfqd_unlock(struct bfq_data *bfqd, -+ unsigned long *flags) -+{ -+ spin_unlock_irqrestore(bfqd->queue->queue_lock, *flags); -+} -+ -+static void bfq_changed_ioprio(struct bfq_io_cq *bic); -+static void bfq_put_queue(struct bfq_queue *bfqq); -+static void bfq_dispatch_insert(struct request_queue *q, struct request *rq); -+static struct bfq_queue *bfq_get_queue(struct bfq_data *bfqd, -+ struct bfq_group *bfqg, int is_sync, -+ struct bfq_io_cq *bic, gfp_t gfp_mask); -+static void bfq_end_wr_async_queues(struct bfq_data *bfqd, -+ struct bfq_group *bfqg); -+static void bfq_put_async_queues(struct bfq_data *bfqd, struct bfq_group *bfqg); -+static void bfq_exit_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq); -+ -+#endif /* _BFQ_H */ --- -2.3.0 - diff --git a/kernel/kernel/files/patches/gentoo/5003_block-bfq-add-Early-Queue-Merge-EQM-to-BFQ-v7r7-for-3.19.0.patch b/kernel/kernel/files/patches/gentoo/5003_block-bfq-add-Early-Queue-Merge-EQM-to-BFQ-v7r7-for-3.19.0.patch deleted file mode 100644 index b2e83e40..00000000 --- a/kernel/kernel/files/patches/gentoo/5003_block-bfq-add-Early-Queue-Merge-EQM-to-BFQ-v7r7-for-3.19.0.patch +++ /dev/null @@ -1,1222 +0,0 @@ -From 8308a96c0ba080015eb1c58a1bfbfbf1fee80fd6 Mon Sep 17 00:00:00 2001 -From: Mauro Andreolini -Date: Thu, 18 Dec 2014 21:32:08 +0100 -Subject: [PATCH 3/3] block, bfq: add Early Queue Merge (EQM) to BFQ-v7r7 for - 3.19.0 - -A set of processes may happen to perform interleaved reads, i.e.,requests -whose union would give rise to a sequential read pattern. There are two -typical cases: in the first case, processes read fixed-size chunks of -data at a fixed distance from each other, while in the second case processes -may read variable-size chunks at variable distances. The latter case occurs -for example with QEMU, which splits the I/O generated by the guest into -multiple chunks, and lets these chunks be served by a pool of cooperating -processes, iteratively assigning the next chunk of I/O to the first -available process. CFQ uses actual queue merging for the first type of -rocesses, whereas it uses preemption to get a sequential read pattern out -of the read requests performed by the second type of processes. In the end -it uses two different mechanisms to achieve the same goal: boosting the -throughput with interleaved I/O. - -This patch introduces Early Queue Merge (EQM), a unified mechanism to get a -sequential read pattern with both types of processes. The main idea is -checking newly arrived requests against the next request of the active queue -both in case of actual request insert and in case of request merge. By doing -so, both the types of processes can be handled by just merging their queues. -EQM is then simpler and more compact than the pair of mechanisms used in -CFQ. - -Finally, EQM also preserves the typical low-latency properties of BFQ, by -properly restoring the weight-raising state of a queue when it gets back to -a non-merged state. - -Signed-off-by: Mauro Andreolini -Signed-off-by: Arianna Avanzini -Signed-off-by: Paolo Valente ---- - block/bfq-iosched.c | 751 +++++++++++++++++++++++++++++++++++++--------------- - block/bfq-sched.c | 28 -- - block/bfq.h | 54 +++- - 3 files changed, 581 insertions(+), 252 deletions(-) - -diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c -index 97ee934..328f33c 100644 ---- a/block/bfq-iosched.c -+++ b/block/bfq-iosched.c -@@ -571,6 +571,57 @@ static inline unsigned int bfq_wr_duration(struct bfq_data *bfqd) - return dur; - } - -+static inline unsigned -+bfq_bfqq_cooperations(struct bfq_queue *bfqq) -+{ -+ return bfqq->bic ? bfqq->bic->cooperations : 0; -+} -+ -+static inline void -+bfq_bfqq_resume_state(struct bfq_queue *bfqq, struct bfq_io_cq *bic) -+{ -+ if (bic->saved_idle_window) -+ bfq_mark_bfqq_idle_window(bfqq); -+ else -+ bfq_clear_bfqq_idle_window(bfqq); -+ if (bic->saved_IO_bound) -+ bfq_mark_bfqq_IO_bound(bfqq); -+ else -+ bfq_clear_bfqq_IO_bound(bfqq); -+ /* Assuming that the flag in_large_burst is already correctly set */ -+ if (bic->wr_time_left && bfqq->bfqd->low_latency && -+ !bfq_bfqq_in_large_burst(bfqq) && -+ bic->cooperations < bfqq->bfqd->bfq_coop_thresh) { -+ /* -+ * Start a weight raising period with the duration given by -+ * the raising_time_left snapshot. -+ */ -+ if (bfq_bfqq_busy(bfqq)) -+ bfqq->bfqd->wr_busy_queues++; -+ bfqq->wr_coeff = bfqq->bfqd->bfq_wr_coeff; -+ bfqq->wr_cur_max_time = bic->wr_time_left; -+ bfqq->last_wr_start_finish = jiffies; -+ bfqq->entity.ioprio_changed = 1; -+ } -+ /* -+ * Clear wr_time_left to prevent bfq_bfqq_save_state() from -+ * getting confused about the queue's need of a weight-raising -+ * period. -+ */ -+ bic->wr_time_left = 0; -+} -+ -+/* Must be called with the queue_lock held. */ -+static int bfqq_process_refs(struct bfq_queue *bfqq) -+{ -+ int process_refs, io_refs; -+ -+ io_refs = bfqq->allocated[READ] + bfqq->allocated[WRITE]; -+ process_refs = atomic_read(&bfqq->ref) - io_refs - bfqq->entity.on_st; -+ BUG_ON(process_refs < 0); -+ return process_refs; -+} -+ - /* Empty burst list and add just bfqq (see comments to bfq_handle_burst) */ - static inline void bfq_reset_burst_list(struct bfq_data *bfqd, - struct bfq_queue *bfqq) -@@ -815,7 +866,7 @@ static void bfq_add_request(struct request *rq) - bfq_rq_pos_tree_add(bfqd, bfqq); - - if (!bfq_bfqq_busy(bfqq)) { -- bool soft_rt, -+ bool soft_rt, coop_or_in_burst, - idle_for_long_time = time_is_before_jiffies( - bfqq->budget_timeout + - bfqd->bfq_wr_min_idle_time); -@@ -839,11 +890,12 @@ static void bfq_add_request(struct request *rq) - bfqd->last_ins_in_burst = jiffies; - } - -+ coop_or_in_burst = bfq_bfqq_in_large_burst(bfqq) || -+ bfq_bfqq_cooperations(bfqq) >= bfqd->bfq_coop_thresh; - soft_rt = bfqd->bfq_wr_max_softrt_rate > 0 && -- !bfq_bfqq_in_large_burst(bfqq) && -+ !coop_or_in_burst && - time_is_before_jiffies(bfqq->soft_rt_next_start); -- interactive = !bfq_bfqq_in_large_burst(bfqq) && -- idle_for_long_time; -+ interactive = !coop_or_in_burst && idle_for_long_time; - entity->budget = max_t(unsigned long, bfqq->max_budget, - bfq_serv_to_charge(next_rq, bfqq)); - -@@ -862,11 +914,20 @@ static void bfq_add_request(struct request *rq) - if (!bfqd->low_latency) - goto add_bfqq_busy; - -+ if (bfq_bfqq_just_split(bfqq)) -+ goto set_ioprio_changed; -+ - /* -- * If the queue is not being boosted and has been idle -- * for enough time, start a weight-raising period -+ * If the queue: -+ * - is not being boosted, -+ * - has been idle for enough time, -+ * - is not a sync queue or is linked to a bfq_io_cq (it is -+ * shared "for its nature" or it is not shared and its -+ * requests have not been redirected to a shared queue) -+ * start a weight-raising period. - */ -- if (old_wr_coeff == 1 && (interactive || soft_rt)) { -+ if (old_wr_coeff == 1 && (interactive || soft_rt) && -+ (!bfq_bfqq_sync(bfqq) || bfqq->bic != NULL)) { - bfqq->wr_coeff = bfqd->bfq_wr_coeff; - if (interactive) - bfqq->wr_cur_max_time = bfq_wr_duration(bfqd); -@@ -880,7 +941,7 @@ static void bfq_add_request(struct request *rq) - } else if (old_wr_coeff > 1) { - if (interactive) - bfqq->wr_cur_max_time = bfq_wr_duration(bfqd); -- else if (bfq_bfqq_in_large_burst(bfqq) || -+ else if (coop_or_in_burst || - (bfqq->wr_cur_max_time == - bfqd->bfq_wr_rt_max_time && - !soft_rt)) { -@@ -899,18 +960,18 @@ static void bfq_add_request(struct request *rq) - /* - * - * The remaining weight-raising time is lower -- * than bfqd->bfq_wr_rt_max_time, which -- * means that the application is enjoying -- * weight raising either because deemed soft- -- * rt in the near past, or because deemed -- * interactive a long ago. In both cases, -- * resetting now the current remaining weight- -- * raising time for the application to the -- * weight-raising duration for soft rt -- * applications would not cause any latency -- * increase for the application (as the new -- * duration would be higher than the remaining -- * time). -+ * than bfqd->bfq_wr_rt_max_time, which means -+ * that the application is enjoying weight -+ * raising either because deemed soft-rt in -+ * the near past, or because deemed interactive -+ * a long ago. -+ * In both cases, resetting now the current -+ * remaining weight-raising time for the -+ * application to the weight-raising duration -+ * for soft rt applications would not cause any -+ * latency increase for the application (as the -+ * new duration would be higher than the -+ * remaining time). - * - * In addition, the application is now meeting - * the requirements for being deemed soft rt. -@@ -945,6 +1006,7 @@ static void bfq_add_request(struct request *rq) - bfqd->bfq_wr_rt_max_time; - } - } -+set_ioprio_changed: - if (old_wr_coeff != bfqq->wr_coeff) - entity->ioprio_changed = 1; - add_bfqq_busy: -@@ -1156,90 +1218,35 @@ static void bfq_end_wr(struct bfq_data *bfqd) - spin_unlock_irq(bfqd->queue->queue_lock); - } - --static int bfq_allow_merge(struct request_queue *q, struct request *rq, -- struct bio *bio) -+static inline sector_t bfq_io_struct_pos(void *io_struct, bool request) - { -- struct bfq_data *bfqd = q->elevator->elevator_data; -- struct bfq_io_cq *bic; -- struct bfq_queue *bfqq; -- -- /* -- * Disallow merge of a sync bio into an async request. -- */ -- if (bfq_bio_sync(bio) && !rq_is_sync(rq)) -- return 0; -- -- /* -- * Lookup the bfqq that this bio will be queued with. Allow -- * merge only if rq is queued there. -- * Queue lock is held here. -- */ -- bic = bfq_bic_lookup(bfqd, current->io_context); -- if (bic == NULL) -- return 0; -- -- bfqq = bic_to_bfqq(bic, bfq_bio_sync(bio)); -- return bfqq == RQ_BFQQ(rq); --} -- --static void __bfq_set_in_service_queue(struct bfq_data *bfqd, -- struct bfq_queue *bfqq) --{ -- if (bfqq != NULL) { -- bfq_mark_bfqq_must_alloc(bfqq); -- bfq_mark_bfqq_budget_new(bfqq); -- bfq_clear_bfqq_fifo_expire(bfqq); -- -- bfqd->budgets_assigned = (bfqd->budgets_assigned*7 + 256) / 8; -- -- bfq_log_bfqq(bfqd, bfqq, -- "set_in_service_queue, cur-budget = %lu", -- bfqq->entity.budget); -- } -- -- bfqd->in_service_queue = bfqq; --} -- --/* -- * Get and set a new queue for service. -- */ --static struct bfq_queue *bfq_set_in_service_queue(struct bfq_data *bfqd, -- struct bfq_queue *bfqq) --{ -- if (!bfqq) -- bfqq = bfq_get_next_queue(bfqd); -+ if (request) -+ return blk_rq_pos(io_struct); - else -- bfq_get_next_queue_forced(bfqd, bfqq); -- -- __bfq_set_in_service_queue(bfqd, bfqq); -- return bfqq; -+ return ((struct bio *)io_struct)->bi_iter.bi_sector; - } - --static inline sector_t bfq_dist_from_last(struct bfq_data *bfqd, -- struct request *rq) -+static inline sector_t bfq_dist_from(sector_t pos1, -+ sector_t pos2) - { -- if (blk_rq_pos(rq) >= bfqd->last_position) -- return blk_rq_pos(rq) - bfqd->last_position; -+ if (pos1 >= pos2) -+ return pos1 - pos2; - else -- return bfqd->last_position - blk_rq_pos(rq); -+ return pos2 - pos1; - } - --/* -- * Return true if bfqq has no request pending and rq is close enough to -- * bfqd->last_position, or if rq is closer to bfqd->last_position than -- * bfqq->next_rq -- */ --static inline int bfq_rq_close(struct bfq_data *bfqd, struct request *rq) -+static inline int bfq_rq_close_to_sector(void *io_struct, bool request, -+ sector_t sector) - { -- return bfq_dist_from_last(bfqd, rq) <= BFQQ_SEEK_THR; -+ return bfq_dist_from(bfq_io_struct_pos(io_struct, request), sector) <= -+ BFQQ_SEEK_THR; - } - --static struct bfq_queue *bfqq_close(struct bfq_data *bfqd) -+static struct bfq_queue *bfqq_close(struct bfq_data *bfqd, sector_t sector) - { - struct rb_root *root = &bfqd->rq_pos_tree; - struct rb_node *parent, *node; - struct bfq_queue *__bfqq; -- sector_t sector = bfqd->last_position; - - if (RB_EMPTY_ROOT(root)) - return NULL; -@@ -1258,7 +1265,7 @@ static struct bfq_queue *bfqq_close(struct bfq_data *bfqd) - * next_request position). - */ - __bfqq = rb_entry(parent, struct bfq_queue, pos_node); -- if (bfq_rq_close(bfqd, __bfqq->next_rq)) -+ if (bfq_rq_close_to_sector(__bfqq->next_rq, true, sector)) - return __bfqq; - - if (blk_rq_pos(__bfqq->next_rq) < sector) -@@ -1269,7 +1276,7 @@ static struct bfq_queue *bfqq_close(struct bfq_data *bfqd) - return NULL; - - __bfqq = rb_entry(node, struct bfq_queue, pos_node); -- if (bfq_rq_close(bfqd, __bfqq->next_rq)) -+ if (bfq_rq_close_to_sector(__bfqq->next_rq, true, sector)) - return __bfqq; - - return NULL; -@@ -1278,14 +1285,12 @@ static struct bfq_queue *bfqq_close(struct bfq_data *bfqd) - /* - * bfqd - obvious - * cur_bfqq - passed in so that we don't decide that the current queue -- * is closely cooperating with itself. -- * -- * We are assuming that cur_bfqq has dispatched at least one request, -- * and that bfqd->last_position reflects a position on the disk associated -- * with the I/O issued by cur_bfqq. -+ * is closely cooperating with itself -+ * sector - used as a reference point to search for a close queue - */ - static struct bfq_queue *bfq_close_cooperator(struct bfq_data *bfqd, -- struct bfq_queue *cur_bfqq) -+ struct bfq_queue *cur_bfqq, -+ sector_t sector) - { - struct bfq_queue *bfqq; - -@@ -1305,7 +1310,7 @@ static struct bfq_queue *bfq_close_cooperator(struct bfq_data *bfqd, - * working closely on the same area of the disk. In that case, - * we can group them together and don't waste time idling. - */ -- bfqq = bfqq_close(bfqd); -+ bfqq = bfqq_close(bfqd, sector); - if (bfqq == NULL || bfqq == cur_bfqq) - return NULL; - -@@ -1332,6 +1337,315 @@ static struct bfq_queue *bfq_close_cooperator(struct bfq_data *bfqd, - return bfqq; - } - -+static struct bfq_queue * -+bfq_setup_merge(struct bfq_queue *bfqq, struct bfq_queue *new_bfqq) -+{ -+ int process_refs, new_process_refs; -+ struct bfq_queue *__bfqq; -+ -+ /* -+ * If there are no process references on the new_bfqq, then it is -+ * unsafe to follow the ->new_bfqq chain as other bfqq's in the chain -+ * may have dropped their last reference (not just their last process -+ * reference). -+ */ -+ if (!bfqq_process_refs(new_bfqq)) -+ return NULL; -+ -+ /* Avoid a circular list and skip interim queue merges. */ -+ while ((__bfqq = new_bfqq->new_bfqq)) { -+ if (__bfqq == bfqq) -+ return NULL; -+ new_bfqq = __bfqq; -+ } -+ -+ process_refs = bfqq_process_refs(bfqq); -+ new_process_refs = bfqq_process_refs(new_bfqq); -+ /* -+ * If the process for the bfqq has gone away, there is no -+ * sense in merging the queues. -+ */ -+ if (process_refs == 0 || new_process_refs == 0) -+ return NULL; -+ -+ bfq_log_bfqq(bfqq->bfqd, bfqq, "scheduling merge with queue %d", -+ new_bfqq->pid); -+ -+ /* -+ * Merging is just a redirection: the requests of the process -+ * owning one of the two queues are redirected to the other queue. -+ * The latter queue, in its turn, is set as shared if this is the -+ * first time that the requests of some process are redirected to -+ * it. -+ * -+ * We redirect bfqq to new_bfqq and not the opposite, because we -+ * are in the context of the process owning bfqq, hence we have -+ * the io_cq of this process. So we can immediately configure this -+ * io_cq to redirect the requests of the process to new_bfqq. -+ * -+ * NOTE, even if new_bfqq coincides with the in-service queue, the -+ * io_cq of new_bfqq is not available, because, if the in-service -+ * queue is shared, bfqd->in_service_bic may not point to the -+ * io_cq of the in-service queue. -+ * Redirecting the requests of the process owning bfqq to the -+ * currently in-service queue is in any case the best option, as -+ * we feed the in-service queue with new requests close to the -+ * last request served and, by doing so, hopefully increase the -+ * throughput. -+ */ -+ bfqq->new_bfqq = new_bfqq; -+ atomic_add(process_refs, &new_bfqq->ref); -+ return new_bfqq; -+} -+ -+/* -+ * Attempt to schedule a merge of bfqq with the currently in-service queue -+ * or with a close queue among the scheduled queues. -+ * Return NULL if no merge was scheduled, a pointer to the shared bfq_queue -+ * structure otherwise. -+ * -+ * The OOM queue is not allowed to participate to cooperation: in fact, since -+ * the requests temporarily redirected to the OOM queue could be redirected -+ * again to dedicated queues at any time, the state needed to correctly -+ * handle merging with the OOM queue would be quite complex and expensive -+ * to maintain. Besides, in such a critical condition as an out of memory, -+ * the benefits of queue merging may be little relevant, or even negligible. -+ */ -+static struct bfq_queue * -+bfq_setup_cooperator(struct bfq_data *bfqd, struct bfq_queue *bfqq, -+ void *io_struct, bool request) -+{ -+ struct bfq_queue *in_service_bfqq, *new_bfqq; -+ -+ if (bfqq->new_bfqq) -+ return bfqq->new_bfqq; -+ -+ if (!io_struct || unlikely(bfqq == &bfqd->oom_bfqq)) -+ return NULL; -+ -+ in_service_bfqq = bfqd->in_service_queue; -+ -+ if (in_service_bfqq == NULL || in_service_bfqq == bfqq || -+ !bfqd->in_service_bic || -+ unlikely(in_service_bfqq == &bfqd->oom_bfqq)) -+ goto check_scheduled; -+ -+ if (bfq_class_idle(in_service_bfqq) || bfq_class_idle(bfqq)) -+ goto check_scheduled; -+ -+ if (bfq_class_rt(in_service_bfqq) != bfq_class_rt(bfqq)) -+ goto check_scheduled; -+ -+ if (in_service_bfqq->entity.parent != bfqq->entity.parent) -+ goto check_scheduled; -+ -+ if (bfq_rq_close_to_sector(io_struct, request, bfqd->last_position) && -+ bfq_bfqq_sync(in_service_bfqq) && bfq_bfqq_sync(bfqq)) { -+ new_bfqq = bfq_setup_merge(bfqq, in_service_bfqq); -+ if (new_bfqq != NULL) -+ return new_bfqq; /* Merge with in-service queue */ -+ } -+ -+ /* -+ * Check whether there is a cooperator among currently scheduled -+ * queues. The only thing we need is that the bio/request is not -+ * NULL, as we need it to establish whether a cooperator exists. -+ */ -+check_scheduled: -+ new_bfqq = bfq_close_cooperator(bfqd, bfqq, -+ bfq_io_struct_pos(io_struct, request)); -+ if (new_bfqq && likely(new_bfqq != &bfqd->oom_bfqq)) -+ return bfq_setup_merge(bfqq, new_bfqq); -+ -+ return NULL; -+} -+ -+static inline void -+bfq_bfqq_save_state(struct bfq_queue *bfqq) -+{ -+ /* -+ * If bfqq->bic == NULL, the queue is already shared or its requests -+ * have already been redirected to a shared queue; both idle window -+ * and weight raising state have already been saved. Do nothing. -+ */ -+ if (bfqq->bic == NULL) -+ return; -+ if (bfqq->bic->wr_time_left) -+ /* -+ * This is the queue of a just-started process, and would -+ * deserve weight raising: we set wr_time_left to the full -+ * weight-raising duration to trigger weight-raising when -+ * and if the queue is split and the first request of the -+ * queue is enqueued. -+ */ -+ bfqq->bic->wr_time_left = bfq_wr_duration(bfqq->bfqd); -+ else if (bfqq->wr_coeff > 1) { -+ unsigned long wr_duration = -+ jiffies - bfqq->last_wr_start_finish; -+ /* -+ * It may happen that a queue's weight raising period lasts -+ * longer than its wr_cur_max_time, as weight raising is -+ * handled only when a request is enqueued or dispatched (it -+ * does not use any timer). If the weight raising period is -+ * about to end, don't save it. -+ */ -+ if (bfqq->wr_cur_max_time <= wr_duration) -+ bfqq->bic->wr_time_left = 0; -+ else -+ bfqq->bic->wr_time_left = -+ bfqq->wr_cur_max_time - wr_duration; -+ /* -+ * The bfq_queue is becoming shared or the requests of the -+ * process owning the queue are being redirected to a shared -+ * queue. Stop the weight raising period of the queue, as in -+ * both cases it should not be owned by an interactive or -+ * soft real-time application. -+ */ -+ bfq_bfqq_end_wr(bfqq); -+ } else -+ bfqq->bic->wr_time_left = 0; -+ bfqq->bic->saved_idle_window = bfq_bfqq_idle_window(bfqq); -+ bfqq->bic->saved_IO_bound = bfq_bfqq_IO_bound(bfqq); -+ bfqq->bic->saved_in_large_burst = bfq_bfqq_in_large_burst(bfqq); -+ bfqq->bic->was_in_burst_list = !hlist_unhashed(&bfqq->burst_list_node); -+ bfqq->bic->cooperations++; -+ bfqq->bic->failed_cooperations = 0; -+} -+ -+static inline void -+bfq_get_bic_reference(struct bfq_queue *bfqq) -+{ -+ /* -+ * If bfqq->bic has a non-NULL value, the bic to which it belongs -+ * is about to begin using a shared bfq_queue. -+ */ -+ if (bfqq->bic) -+ atomic_long_inc(&bfqq->bic->icq.ioc->refcount); -+} -+ -+static void -+bfq_merge_bfqqs(struct bfq_data *bfqd, struct bfq_io_cq *bic, -+ struct bfq_queue *bfqq, struct bfq_queue *new_bfqq) -+{ -+ bfq_log_bfqq(bfqd, bfqq, "merging with queue %lu", -+ (long unsigned)new_bfqq->pid); -+ /* Save weight raising and idle window of the merged queues */ -+ bfq_bfqq_save_state(bfqq); -+ bfq_bfqq_save_state(new_bfqq); -+ if (bfq_bfqq_IO_bound(bfqq)) -+ bfq_mark_bfqq_IO_bound(new_bfqq); -+ bfq_clear_bfqq_IO_bound(bfqq); -+ /* -+ * Grab a reference to the bic, to prevent it from being destroyed -+ * before being possibly touched by a bfq_split_bfqq(). -+ */ -+ bfq_get_bic_reference(bfqq); -+ bfq_get_bic_reference(new_bfqq); -+ /* -+ * Merge queues (that is, let bic redirect its requests to new_bfqq) -+ */ -+ bic_set_bfqq(bic, new_bfqq, 1); -+ bfq_mark_bfqq_coop(new_bfqq); -+ /* -+ * new_bfqq now belongs to at least two bics (it is a shared queue): -+ * set new_bfqq->bic to NULL. bfqq either: -+ * - does not belong to any bic any more, and hence bfqq->bic must -+ * be set to NULL, or -+ * - is a queue whose owning bics have already been redirected to a -+ * different queue, hence the queue is destined to not belong to -+ * any bic soon and bfqq->bic is already NULL (therefore the next -+ * assignment causes no harm). -+ */ -+ new_bfqq->bic = NULL; -+ bfqq->bic = NULL; -+ bfq_put_queue(bfqq); -+} -+ -+static inline void bfq_bfqq_increase_failed_cooperations(struct bfq_queue *bfqq) -+{ -+ struct bfq_io_cq *bic = bfqq->bic; -+ struct bfq_data *bfqd = bfqq->bfqd; -+ -+ if (bic && bfq_bfqq_cooperations(bfqq) >= bfqd->bfq_coop_thresh) { -+ bic->failed_cooperations++; -+ if (bic->failed_cooperations >= bfqd->bfq_failed_cooperations) -+ bic->cooperations = 0; -+ } -+} -+ -+static int bfq_allow_merge(struct request_queue *q, struct request *rq, -+ struct bio *bio) -+{ -+ struct bfq_data *bfqd = q->elevator->elevator_data; -+ struct bfq_io_cq *bic; -+ struct bfq_queue *bfqq, *new_bfqq; -+ -+ /* -+ * Disallow merge of a sync bio into an async request. -+ */ -+ if (bfq_bio_sync(bio) && !rq_is_sync(rq)) -+ return 0; -+ -+ /* -+ * Lookup the bfqq that this bio will be queued with. Allow -+ * merge only if rq is queued there. -+ * Queue lock is held here. -+ */ -+ bic = bfq_bic_lookup(bfqd, current->io_context); -+ if (bic == NULL) -+ return 0; -+ -+ bfqq = bic_to_bfqq(bic, bfq_bio_sync(bio)); -+ /* -+ * We take advantage of this function to perform an early merge -+ * of the queues of possible cooperating processes. -+ */ -+ if (bfqq != NULL) { -+ new_bfqq = bfq_setup_cooperator(bfqd, bfqq, bio, false); -+ if (new_bfqq != NULL) { -+ bfq_merge_bfqqs(bfqd, bic, bfqq, new_bfqq); -+ /* -+ * If we get here, the bio will be queued in the -+ * shared queue, i.e., new_bfqq, so use new_bfqq -+ * to decide whether bio and rq can be merged. -+ */ -+ bfqq = new_bfqq; -+ } else -+ bfq_bfqq_increase_failed_cooperations(bfqq); -+ } -+ -+ return bfqq == RQ_BFQQ(rq); -+} -+ -+static void __bfq_set_in_service_queue(struct bfq_data *bfqd, -+ struct bfq_queue *bfqq) -+{ -+ if (bfqq != NULL) { -+ bfq_mark_bfqq_must_alloc(bfqq); -+ bfq_mark_bfqq_budget_new(bfqq); -+ bfq_clear_bfqq_fifo_expire(bfqq); -+ -+ bfqd->budgets_assigned = (bfqd->budgets_assigned*7 + 256) / 8; -+ -+ bfq_log_bfqq(bfqd, bfqq, -+ "set_in_service_queue, cur-budget = %lu", -+ bfqq->entity.budget); -+ } -+ -+ bfqd->in_service_queue = bfqq; -+} -+ -+/* -+ * Get and set a new queue for service. -+ */ -+static struct bfq_queue *bfq_set_in_service_queue(struct bfq_data *bfqd) -+{ -+ struct bfq_queue *bfqq = bfq_get_next_queue(bfqd); -+ -+ __bfq_set_in_service_queue(bfqd, bfqq); -+ return bfqq; -+} -+ - /* - * If enough samples have been computed, return the current max budget - * stored in bfqd, which is dynamically updated according to the -@@ -1475,61 +1789,6 @@ static struct request *bfq_check_fifo(struct bfq_queue *bfqq) - return rq; - } - --/* Must be called with the queue_lock held. */ --static int bfqq_process_refs(struct bfq_queue *bfqq) --{ -- int process_refs, io_refs; -- -- io_refs = bfqq->allocated[READ] + bfqq->allocated[WRITE]; -- process_refs = atomic_read(&bfqq->ref) - io_refs - bfqq->entity.on_st; -- BUG_ON(process_refs < 0); -- return process_refs; --} -- --static void bfq_setup_merge(struct bfq_queue *bfqq, struct bfq_queue *new_bfqq) --{ -- int process_refs, new_process_refs; -- struct bfq_queue *__bfqq; -- -- /* -- * If there are no process references on the new_bfqq, then it is -- * unsafe to follow the ->new_bfqq chain as other bfqq's in the chain -- * may have dropped their last reference (not just their last process -- * reference). -- */ -- if (!bfqq_process_refs(new_bfqq)) -- return; -- -- /* Avoid a circular list and skip interim queue merges. */ -- while ((__bfqq = new_bfqq->new_bfqq)) { -- if (__bfqq == bfqq) -- return; -- new_bfqq = __bfqq; -- } -- -- process_refs = bfqq_process_refs(bfqq); -- new_process_refs = bfqq_process_refs(new_bfqq); -- /* -- * If the process for the bfqq has gone away, there is no -- * sense in merging the queues. -- */ -- if (process_refs == 0 || new_process_refs == 0) -- return; -- -- /* -- * Merge in the direction of the lesser amount of work. -- */ -- if (new_process_refs >= process_refs) { -- bfqq->new_bfqq = new_bfqq; -- atomic_add(process_refs, &new_bfqq->ref); -- } else { -- new_bfqq->new_bfqq = bfqq; -- atomic_add(new_process_refs, &bfqq->ref); -- } -- bfq_log_bfqq(bfqq->bfqd, bfqq, "scheduling merge with queue %d", -- new_bfqq->pid); --} -- - static inline unsigned long bfq_bfqq_budget_left(struct bfq_queue *bfqq) - { - struct bfq_entity *entity = &bfqq->entity; -@@ -2263,7 +2522,7 @@ static inline bool bfq_bfqq_must_idle(struct bfq_queue *bfqq) - */ - static struct bfq_queue *bfq_select_queue(struct bfq_data *bfqd) - { -- struct bfq_queue *bfqq, *new_bfqq = NULL; -+ struct bfq_queue *bfqq; - struct request *next_rq; - enum bfqq_expiration reason = BFQ_BFQQ_BUDGET_TIMEOUT; - -@@ -2273,17 +2532,6 @@ static struct bfq_queue *bfq_select_queue(struct bfq_data *bfqd) - - bfq_log_bfqq(bfqd, bfqq, "select_queue: already in-service queue"); - -- /* -- * If another queue has a request waiting within our mean seek -- * distance, let it run. The expire code will check for close -- * cooperators and put the close queue at the front of the -- * service tree. If possible, merge the expiring queue with the -- * new bfqq. -- */ -- new_bfqq = bfq_close_cooperator(bfqd, bfqq); -- if (new_bfqq != NULL && bfqq->new_bfqq == NULL) -- bfq_setup_merge(bfqq, new_bfqq); -- - if (bfq_may_expire_for_budg_timeout(bfqq) && - !timer_pending(&bfqd->idle_slice_timer) && - !bfq_bfqq_must_idle(bfqq)) -@@ -2322,10 +2570,7 @@ static struct bfq_queue *bfq_select_queue(struct bfq_data *bfqd) - bfq_clear_bfqq_wait_request(bfqq); - del_timer(&bfqd->idle_slice_timer); - } -- if (new_bfqq == NULL) -- goto keep_queue; -- else -- goto expire; -+ goto keep_queue; - } - } - -@@ -2334,40 +2579,30 @@ static struct bfq_queue *bfq_select_queue(struct bfq_data *bfqd) - * in flight (possibly waiting for a completion) or is idling for a - * new request, then keep it. - */ -- if (new_bfqq == NULL && (timer_pending(&bfqd->idle_slice_timer) || -- (bfqq->dispatched != 0 && bfq_bfqq_must_not_expire(bfqq)))) { -+ if (timer_pending(&bfqd->idle_slice_timer) || -+ (bfqq->dispatched != 0 && bfq_bfqq_must_not_expire(bfqq))) { - bfqq = NULL; - goto keep_queue; -- } else if (new_bfqq != NULL && timer_pending(&bfqd->idle_slice_timer)) { -- /* -- * Expiring the queue because there is a close cooperator, -- * cancel timer. -- */ -- bfq_clear_bfqq_wait_request(bfqq); -- del_timer(&bfqd->idle_slice_timer); - } - - reason = BFQ_BFQQ_NO_MORE_REQUESTS; - expire: - bfq_bfqq_expire(bfqd, bfqq, 0, reason); - new_queue: -- bfqq = bfq_set_in_service_queue(bfqd, new_bfqq); -+ bfqq = bfq_set_in_service_queue(bfqd); - bfq_log(bfqd, "select_queue: new queue %d returned", - bfqq != NULL ? bfqq->pid : 0); - keep_queue: - return bfqq; - } - --static void bfq_update_wr_data(struct bfq_data *bfqd, -- struct bfq_queue *bfqq) -+static void bfq_update_wr_data(struct bfq_data *bfqd, struct bfq_queue *bfqq) - { -- if (bfqq->wr_coeff > 1) { /* queue is being boosted */ -- struct bfq_entity *entity = &bfqq->entity; -- -+ struct bfq_entity *entity = &bfqq->entity; -+ if (bfqq->wr_coeff > 1) { /* queue is being weight-raised */ - bfq_log_bfqq(bfqd, bfqq, - "raising period dur %u/%u msec, old coeff %u, w %d(%d)", -- jiffies_to_msecs(jiffies - -- bfqq->last_wr_start_finish), -+ jiffies_to_msecs(jiffies - bfqq->last_wr_start_finish), - jiffies_to_msecs(bfqq->wr_cur_max_time), - bfqq->wr_coeff, - bfqq->entity.weight, bfqq->entity.orig_weight); -@@ -2376,12 +2611,16 @@ static void bfq_update_wr_data(struct bfq_data *bfqd, - entity->orig_weight * bfqq->wr_coeff); - if (entity->ioprio_changed) - bfq_log_bfqq(bfqd, bfqq, "WARN: pending prio change"); -+ - /* - * If the queue was activated in a burst, or - * too much time has elapsed from the beginning -- * of this weight-raising, then end weight raising. -+ * of this weight-raising period, or the queue has -+ * exceeded the acceptable number of cooperations, -+ * then end weight raising. - */ - if (bfq_bfqq_in_large_burst(bfqq) || -+ bfq_bfqq_cooperations(bfqq) >= bfqd->bfq_coop_thresh || - time_is_before_jiffies(bfqq->last_wr_start_finish + - bfqq->wr_cur_max_time)) { - bfqq->last_wr_start_finish = jiffies; -@@ -2390,11 +2629,13 @@ static void bfq_update_wr_data(struct bfq_data *bfqd, - bfqq->last_wr_start_finish, - jiffies_to_msecs(bfqq->wr_cur_max_time)); - bfq_bfqq_end_wr(bfqq); -- __bfq_entity_update_weight_prio( -- bfq_entity_service_tree(entity), -- entity); - } - } -+ /* Update weight both if it must be raised and if it must be lowered */ -+ if ((entity->weight > entity->orig_weight) != (bfqq->wr_coeff > 1)) -+ __bfq_entity_update_weight_prio( -+ bfq_entity_service_tree(entity), -+ entity); - } - - /* -@@ -2642,6 +2883,25 @@ static inline void bfq_init_icq(struct io_cq *icq) - struct bfq_io_cq *bic = icq_to_bic(icq); - - bic->ttime.last_end_request = jiffies; -+ /* -+ * A newly created bic indicates that the process has just -+ * started doing I/O, and is probably mapping into memory its -+ * executable and libraries: it definitely needs weight raising. -+ * There is however the possibility that the process performs, -+ * for a while, I/O close to some other process. EQM intercepts -+ * this behavior and may merge the queue corresponding to the -+ * process with some other queue, BEFORE the weight of the queue -+ * is raised. Merged queues are not weight-raised (they are assumed -+ * to belong to processes that benefit only from high throughput). -+ * If the merge is basically the consequence of an accident, then -+ * the queue will be split soon and will get back its old weight. -+ * It is then important to write down somewhere that this queue -+ * does need weight raising, even if it did not make it to get its -+ * weight raised before being merged. To this purpose, we overload -+ * the field raising_time_left and assign 1 to it, to mark the queue -+ * as needing weight raising. -+ */ -+ bic->wr_time_left = 1; - } - - static void bfq_exit_icq(struct io_cq *icq) -@@ -2655,6 +2915,13 @@ static void bfq_exit_icq(struct io_cq *icq) - } - - if (bic->bfqq[BLK_RW_SYNC]) { -+ /* -+ * If the bic is using a shared queue, put the reference -+ * taken on the io_context when the bic started using a -+ * shared bfq_queue. -+ */ -+ if (bfq_bfqq_coop(bic->bfqq[BLK_RW_SYNC])) -+ put_io_context(icq->ioc); - bfq_exit_bfqq(bfqd, bic->bfqq[BLK_RW_SYNC]); - bic->bfqq[BLK_RW_SYNC] = NULL; - } -@@ -2950,6 +3217,10 @@ static void bfq_update_idle_window(struct bfq_data *bfqd, - if (!bfq_bfqq_sync(bfqq) || bfq_class_idle(bfqq)) - return; - -+ /* Idle window just restored, statistics are meaningless. */ -+ if (bfq_bfqq_just_split(bfqq)) -+ return; -+ - enable_idle = bfq_bfqq_idle_window(bfqq); - - if (atomic_read(&bic->icq.ioc->active_ref) == 0 || -@@ -2997,6 +3268,7 @@ static void bfq_rq_enqueued(struct bfq_data *bfqd, struct bfq_queue *bfqq, - if (bfqq->entity.service > bfq_max_budget(bfqd) / 8 || - !BFQQ_SEEKY(bfqq)) - bfq_update_idle_window(bfqd, bfqq, bic); -+ bfq_clear_bfqq_just_split(bfqq); - - bfq_log_bfqq(bfqd, bfqq, - "rq_enqueued: idle_window=%d (seeky %d, mean %llu)", -@@ -3057,13 +3329,49 @@ static void bfq_rq_enqueued(struct bfq_data *bfqd, struct bfq_queue *bfqq, - static void bfq_insert_request(struct request_queue *q, struct request *rq) - { - struct bfq_data *bfqd = q->elevator->elevator_data; -- struct bfq_queue *bfqq = RQ_BFQQ(rq); -+ struct bfq_queue *bfqq = RQ_BFQQ(rq), *new_bfqq; - - assert_spin_locked(bfqd->queue->queue_lock); -+ -+ /* -+ * An unplug may trigger a requeue of a request from the device -+ * driver: make sure we are in process context while trying to -+ * merge two bfq_queues. -+ */ -+ if (!in_interrupt()) { -+ new_bfqq = bfq_setup_cooperator(bfqd, bfqq, rq, true); -+ if (new_bfqq != NULL) { -+ if (bic_to_bfqq(RQ_BIC(rq), 1) != bfqq) -+ new_bfqq = bic_to_bfqq(RQ_BIC(rq), 1); -+ /* -+ * Release the request's reference to the old bfqq -+ * and make sure one is taken to the shared queue. -+ */ -+ new_bfqq->allocated[rq_data_dir(rq)]++; -+ bfqq->allocated[rq_data_dir(rq)]--; -+ atomic_inc(&new_bfqq->ref); -+ bfq_put_queue(bfqq); -+ if (bic_to_bfqq(RQ_BIC(rq), 1) == bfqq) -+ bfq_merge_bfqqs(bfqd, RQ_BIC(rq), -+ bfqq, new_bfqq); -+ rq->elv.priv[1] = new_bfqq; -+ bfqq = new_bfqq; -+ } else -+ bfq_bfqq_increase_failed_cooperations(bfqq); -+ } -+ - bfq_init_prio_data(bfqq, RQ_BIC(rq)); - - bfq_add_request(rq); - -+ /* -+ * Here a newly-created bfq_queue has already started a weight-raising -+ * period: clear raising_time_left to prevent bfq_bfqq_save_state() -+ * from assigning it a full weight-raising period. See the detailed -+ * comments about this field in bfq_init_icq(). -+ */ -+ if (bfqq->bic != NULL) -+ bfqq->bic->wr_time_left = 0; - rq->fifo_time = jiffies + bfqd->bfq_fifo_expire[rq_is_sync(rq)]; - list_add_tail(&rq->queuelist, &bfqq->fifo); - -@@ -3228,18 +3536,6 @@ static void bfq_put_request(struct request *rq) - } - } - --static struct bfq_queue * --bfq_merge_bfqqs(struct bfq_data *bfqd, struct bfq_io_cq *bic, -- struct bfq_queue *bfqq) --{ -- bfq_log_bfqq(bfqd, bfqq, "merging with queue %lu", -- (long unsigned)bfqq->new_bfqq->pid); -- bic_set_bfqq(bic, bfqq->new_bfqq, 1); -- bfq_mark_bfqq_coop(bfqq->new_bfqq); -- bfq_put_queue(bfqq); -- return bic_to_bfqq(bic, 1); --} -- - /* - * Returns NULL if a new bfqq should be allocated, or the old bfqq if this - * was the last process referring to said bfqq. -@@ -3248,6 +3544,9 @@ static struct bfq_queue * - bfq_split_bfqq(struct bfq_io_cq *bic, struct bfq_queue *bfqq) - { - bfq_log_bfqq(bfqq->bfqd, bfqq, "splitting queue"); -+ -+ put_io_context(bic->icq.ioc); -+ - if (bfqq_process_refs(bfqq) == 1) { - bfqq->pid = current->pid; - bfq_clear_bfqq_coop(bfqq); -@@ -3276,6 +3575,7 @@ static int bfq_set_request(struct request_queue *q, struct request *rq, - struct bfq_queue *bfqq; - struct bfq_group *bfqg; - unsigned long flags; -+ bool split = false; - - might_sleep_if(gfp_mask & __GFP_WAIT); - -@@ -3293,25 +3593,26 @@ new_queue: - if (bfqq == NULL || bfqq == &bfqd->oom_bfqq) { - bfqq = bfq_get_queue(bfqd, bfqg, is_sync, bic, gfp_mask); - bic_set_bfqq(bic, bfqq, is_sync); -+ if (split && is_sync) { -+ if ((bic->was_in_burst_list && bfqd->large_burst) || -+ bic->saved_in_large_burst) -+ bfq_mark_bfqq_in_large_burst(bfqq); -+ else { -+ bfq_clear_bfqq_in_large_burst(bfqq); -+ if (bic->was_in_burst_list) -+ hlist_add_head(&bfqq->burst_list_node, -+ &bfqd->burst_list); -+ } -+ } - } else { -- /* -- * If the queue was seeky for too long, break it apart. -- */ -+ /* If the queue was seeky for too long, break it apart. */ - if (bfq_bfqq_coop(bfqq) && bfq_bfqq_split_coop(bfqq)) { - bfq_log_bfqq(bfqd, bfqq, "breaking apart bfqq"); - bfqq = bfq_split_bfqq(bic, bfqq); -+ split = true; - if (!bfqq) - goto new_queue; - } -- -- /* -- * Check to see if this queue is scheduled to merge with -- * another closely cooperating queue. The merging of queues -- * happens here as it must be done in process context. -- * The reference on new_bfqq was taken in merge_bfqqs. -- */ -- if (bfqq->new_bfqq != NULL) -- bfqq = bfq_merge_bfqqs(bfqd, bic, bfqq); - } - - bfqq->allocated[rw]++; -@@ -3322,6 +3623,26 @@ new_queue: - rq->elv.priv[0] = bic; - rq->elv.priv[1] = bfqq; - -+ /* -+ * If a bfq_queue has only one process reference, it is owned -+ * by only one bfq_io_cq: we can set the bic field of the -+ * bfq_queue to the address of that structure. Also, if the -+ * queue has just been split, mark a flag so that the -+ * information is available to the other scheduler hooks. -+ */ -+ if (likely(bfqq != &bfqd->oom_bfqq) && bfqq_process_refs(bfqq) == 1) { -+ bfqq->bic = bic; -+ if (split) { -+ bfq_mark_bfqq_just_split(bfqq); -+ /* -+ * If the queue has just been split from a shared -+ * queue, restore the idle window and the possible -+ * weight raising period. -+ */ -+ bfq_bfqq_resume_state(bfqq, bic); -+ } -+ } -+ - spin_unlock_irqrestore(q->queue_lock, flags); - - return 0; -diff --git a/block/bfq-sched.c b/block/bfq-sched.c -index 2931563..6764a7e 100644 ---- a/block/bfq-sched.c -+++ b/block/bfq-sched.c -@@ -1091,34 +1091,6 @@ static struct bfq_queue *bfq_get_next_queue(struct bfq_data *bfqd) - return bfqq; - } - --/* -- * Forced extraction of the given queue. -- */ --static void bfq_get_next_queue_forced(struct bfq_data *bfqd, -- struct bfq_queue *bfqq) --{ -- struct bfq_entity *entity; -- struct bfq_sched_data *sd; -- -- BUG_ON(bfqd->in_service_queue != NULL); -- -- entity = &bfqq->entity; -- /* -- * Bubble up extraction/update from the leaf to the root. -- */ -- for_each_entity(entity) { -- sd = entity->sched_data; -- bfq_update_budget(entity); -- bfq_update_vtime(bfq_entity_service_tree(entity)); -- bfq_active_extract(bfq_entity_service_tree(entity), entity); -- sd->in_service_entity = entity; -- sd->next_in_service = NULL; -- entity->service = 0; -- } -- -- return; --} -- - static void __bfq_bfqd_reset_in_service(struct bfq_data *bfqd) - { - if (bfqd->in_service_bic != NULL) { -diff --git a/block/bfq.h b/block/bfq.h -index 3c5d85e..5ced336 100644 ---- a/block/bfq.h -+++ b/block/bfq.h -@@ -218,18 +218,21 @@ struct bfq_group; - * idle @bfq_queue with no outstanding requests, then - * the task associated with the queue it is deemed as - * soft real-time (see the comments to the function -- * bfq_bfqq_softrt_next_start()). -+ * bfq_bfqq_softrt_next_start()) - * @last_idle_bklogged: time of the last transition of the @bfq_queue from - * idle to backlogged - * @service_from_backlogged: cumulative service received from the @bfq_queue - * since the last transition from idle to - * backlogged -+ * @bic: pointer to the bfq_io_cq owning the bfq_queue, set to %NULL if the -+ * queue is shared - * -- * A bfq_queue is a leaf request queue; it can be associated with an io_context -- * or more, if it is async or shared between cooperating processes. @cgroup -- * holds a reference to the cgroup, to be sure that it does not disappear while -- * a bfqq still references it (mostly to avoid races between request issuing and -- * task migration followed by cgroup destruction). -+ * A bfq_queue is a leaf request queue; it can be associated with an -+ * io_context or more, if it is async or shared between cooperating -+ * processes. @cgroup holds a reference to the cgroup, to be sure that it -+ * does not disappear while a bfqq still references it (mostly to avoid -+ * races between request issuing and task migration followed by cgroup -+ * destruction). - * All the fields are protected by the queue lock of the containing bfqd. - */ - struct bfq_queue { -@@ -269,6 +272,7 @@ struct bfq_queue { - unsigned int requests_within_timer; - - pid_t pid; -+ struct bfq_io_cq *bic; - - /* weight-raising fields */ - unsigned long wr_cur_max_time; -@@ -298,12 +302,42 @@ struct bfq_ttime { - * @icq: associated io_cq structure - * @bfqq: array of two process queues, the sync and the async - * @ttime: associated @bfq_ttime struct -+ * @wr_time_left: snapshot of the time left before weight raising ends -+ * for the sync queue associated to this process; this -+ * snapshot is taken to remember this value while the weight -+ * raising is suspended because the queue is merged with a -+ * shared queue, and is used to set @raising_cur_max_time -+ * when the queue is split from the shared queue and its -+ * weight is raised again -+ * @saved_idle_window: same purpose as the previous field for the idle -+ * window -+ * @saved_IO_bound: same purpose as the previous two fields for the I/O -+ * bound classification of a queue -+ * @saved_in_large_burst: same purpose as the previous fields for the -+ * value of the field keeping the queue's belonging -+ * to a large burst -+ * @was_in_burst_list: true if the queue belonged to a burst list -+ * before its merge with another cooperating queue -+ * @cooperations: counter of consecutive successful queue merges underwent -+ * by any of the process' @bfq_queues -+ * @failed_cooperations: counter of consecutive failed queue merges of any -+ * of the process' @bfq_queues - */ - struct bfq_io_cq { - struct io_cq icq; /* must be the first member */ - struct bfq_queue *bfqq[2]; - struct bfq_ttime ttime; - int ioprio; -+ -+ unsigned int wr_time_left; -+ bool saved_idle_window; -+ bool saved_IO_bound; -+ -+ bool saved_in_large_burst; -+ bool was_in_burst_list; -+ -+ unsigned int cooperations; -+ unsigned int failed_cooperations; - }; - - enum bfq_device_speed { -@@ -539,7 +573,7 @@ enum bfqq_state_flags { - BFQ_BFQQ_FLAG_prio_changed, /* task priority has changed */ - BFQ_BFQQ_FLAG_sync, /* synchronous queue */ - BFQ_BFQQ_FLAG_budget_new, /* no completion with this budget */ -- BFQ_BFQQ_FLAG_IO_bound, /* -+ BFQ_BFQQ_FLAG_IO_bound, /* - * bfqq has timed-out at least once - * having consumed at most 2/10 of - * its budget -@@ -552,12 +586,13 @@ enum bfqq_state_flags { - * bfqq has proved to be slow and - * seeky until budget timeout - */ -- BFQ_BFQQ_FLAG_softrt_update, /* -+ BFQ_BFQQ_FLAG_softrt_update, /* - * may need softrt-next-start - * update - */ - BFQ_BFQQ_FLAG_coop, /* bfqq is shared */ -- BFQ_BFQQ_FLAG_split_coop, /* shared bfqq will be splitted */ -+ BFQ_BFQQ_FLAG_split_coop, /* shared bfqq will be split */ -+ BFQ_BFQQ_FLAG_just_split, /* queue has just been split */ - }; - - #define BFQ_BFQQ_FNS(name) \ -@@ -587,6 +622,7 @@ BFQ_BFQQ_FNS(in_large_burst); - BFQ_BFQQ_FNS(constantly_seeky); - BFQ_BFQQ_FNS(coop); - BFQ_BFQQ_FNS(split_coop); -+BFQ_BFQQ_FNS(just_split); - BFQ_BFQQ_FNS(softrt_update); - #undef BFQ_BFQQ_FNS - --- -2.3.0 - diff --git a/kernel/kernel/files/patches/gentoo/5010_enable-additional-cpu-optimizations-for-gcc-4.9.patch b/kernel/kernel/files/patches/gentoo/5010_enable-additional-cpu-optimizations-for-gcc-4.9.patch deleted file mode 100644 index f931f75f..00000000 --- a/kernel/kernel/files/patches/gentoo/5010_enable-additional-cpu-optimizations-for-gcc-4.9.patch +++ /dev/null @@ -1,387 +0,0 @@ -WARNING - this version of the patch works with version 4.9+ of gcc and with -kernel version 3.15.x+ and should NOT be applied when compiling on older -versions due to name changes of the flags with the 4.9 release of gcc. -Use the older version of this patch hosted on the same github for older -versions of gcc. For example: - -corei7 --> nehalem -corei7-avx --> sandybridge -core-avx-i --> ivybridge -core-avx2 --> haswell - -For more, see: https://gcc.gnu.org/gcc-4.9/changes.html - -It also changes 'atom' to 'bonnell' in accordance with the gcc v4.9 changes. -Note that upstream is using the deprecated 'match=atom' flags when I believe it -should use the newer 'march=bonnell' flag for atom processors. - -I have made that change to this patch set as well. See the following kernel -bug report to see if I'm right: https://bugzilla.kernel.org/show_bug.cgi?id=77461 - -This patch will expand the number of microarchitectures to include new -processors including: AMD K10-family, AMD Family 10h (Barcelona), AMD Family -14h (Bobcat), AMD Family 15h (Bulldozer), AMD Family 15h (Piledriver), AMD -Family 16h (Jaguar), Intel 1st Gen Core i3/i5/i7 (Nehalem), Intel 1.5 Gen Core -i3/i5/i7 (Westmere), Intel 2nd Gen Core i3/i5/i7 (Sandybridge), Intel 3rd Gen -Core i3/i5/i7 (Ivybridge), Intel 4th Gen Core i3/i5/i7 (Haswell), and Intel 5th -Gen Core i3/i5/i7 (Broadwell). It also offers the compiler the 'native' flag. - -Small but real speed increases are measurable using a make endpoint comparing -a generic kernel to one built with one of the respective microarchs. - -See the following experimental evidence supporting this statement: -https://github.com/graysky2/kernel_gcc_patch - -REQUIREMENTS -linux version >=3.15 -gcc version >=4.9 - ---- a/arch/x86/include/asm/module.h 2014-08-03 18:25:02.000000000 -0400 -+++ b/arch/x86/include/asm/module.h 2014-09-13 09:37:16.721385247 -0400 -@@ -15,6 +15,20 @@ - #define MODULE_PROC_FAMILY "586MMX " - #elif defined CONFIG_MCORE2 - #define MODULE_PROC_FAMILY "CORE2 " -+#elif defined CONFIG_MNATIVE -+#define MODULE_PROC_FAMILY "NATIVE " -+#elif defined CONFIG_MNEHALEM -+#define MODULE_PROC_FAMILY "NEHALEM " -+#elif defined CONFIG_MWESTMERE -+#define MODULE_PROC_FAMILY "WESTMERE " -+#elif defined CONFIG_MSANDYBRIDGE -+#define MODULE_PROC_FAMILY "SANDYBRIDGE " -+#elif defined CONFIG_MIVYBRIDGE -+#define MODULE_PROC_FAMILY "IVYBRIDGE " -+#elif defined CONFIG_MHASWELL -+#define MODULE_PROC_FAMILY "HASWELL " -+#elif defined CONFIG_MBROADWELL -+#define MODULE_PROC_FAMILY "BROADWELL " - #elif defined CONFIG_MATOM - #define MODULE_PROC_FAMILY "ATOM " - #elif defined CONFIG_M686 -@@ -33,6 +47,20 @@ - #define MODULE_PROC_FAMILY "K7 " - #elif defined CONFIG_MK8 - #define MODULE_PROC_FAMILY "K8 " -+#elif defined CONFIG_MK8SSE3 -+#define MODULE_PROC_FAMILY "K8SSE3 " -+#elif defined CONFIG_MK10 -+#define MODULE_PROC_FAMILY "K10 " -+#elif defined CONFIG_MBARCELONA -+#define MODULE_PROC_FAMILY "BARCELONA " -+#elif defined CONFIG_MBOBCAT -+#define MODULE_PROC_FAMILY "BOBCAT " -+#elif defined CONFIG_MBULLDOZER -+#define MODULE_PROC_FAMILY "BULLDOZER " -+#elif defined CONFIG_MPILEDRIVER -+#define MODULE_PROC_FAMILY "PILEDRIVER " -+#elif defined CONFIG_MJAGUAR -+#define MODULE_PROC_FAMILY "JAGUAR " - #elif defined CONFIG_MELAN - #define MODULE_PROC_FAMILY "ELAN " - #elif defined CONFIG_MCRUSOE ---- a/arch/x86/Kconfig.cpu 2014-08-03 18:25:02.000000000 -0400 -+++ b/arch/x86/Kconfig.cpu 2014-09-13 09:37:16.721385247 -0400 -@@ -137,9 +137,8 @@ config MPENTIUM4 - -Paxville - -Dempsey - -- - config MK6 -- bool "K6/K6-II/K6-III" -+ bool "AMD K6/K6-II/K6-III" - depends on X86_32 - ---help--- - Select this for an AMD K6-family processor. Enables use of -@@ -147,7 +146,7 @@ config MK6 - flags to GCC. - - config MK7 -- bool "Athlon/Duron/K7" -+ bool "AMD Athlon/Duron/K7" - depends on X86_32 - ---help--- - Select this for an AMD Athlon K7-family processor. Enables use of -@@ -155,12 +154,62 @@ config MK7 - flags to GCC. - - config MK8 -- bool "Opteron/Athlon64/Hammer/K8" -+ bool "AMD Opteron/Athlon64/Hammer/K8" - ---help--- - Select this for an AMD Opteron or Athlon64 Hammer-family processor. - Enables use of some extended instructions, and passes appropriate - optimization flags to GCC. - -+config MK8SSE3 -+ bool "AMD Opteron/Athlon64/Hammer/K8 with SSE3" -+ ---help--- -+ Select this for improved AMD Opteron or Athlon64 Hammer-family processors. -+ Enables use of some extended instructions, and passes appropriate -+ optimization flags to GCC. -+ -+config MK10 -+ bool "AMD 61xx/7x50/PhenomX3/X4/II/K10" -+ ---help--- -+ Select this for an AMD 61xx Eight-Core Magny-Cours, Athlon X2 7x50, -+ Phenom X3/X4/II, Athlon II X2/X3/X4, or Turion II-family processor. -+ Enables use of some extended instructions, and passes appropriate -+ optimization flags to GCC. -+ -+config MBARCELONA -+ bool "AMD Barcelona" -+ ---help--- -+ Select this for AMD Barcelona and newer processors. -+ -+ Enables -march=barcelona -+ -+config MBOBCAT -+ bool "AMD Bobcat" -+ ---help--- -+ Select this for AMD Bobcat processors. -+ -+ Enables -march=btver1 -+ -+config MBULLDOZER -+ bool "AMD Bulldozer" -+ ---help--- -+ Select this for AMD Bulldozer processors. -+ -+ Enables -march=bdver1 -+ -+config MPILEDRIVER -+ bool "AMD Piledriver" -+ ---help--- -+ Select this for AMD Piledriver processors. -+ -+ Enables -march=bdver2 -+ -+config MJAGUAR -+ bool "AMD Jaguar" -+ ---help--- -+ Select this for AMD Jaguar processors. -+ -+ Enables -march=btver2 -+ - config MCRUSOE - bool "Crusoe" - depends on X86_32 -@@ -251,8 +300,17 @@ config MPSC - using the cpu family field - in /proc/cpuinfo. Family 15 is an older Xeon, Family 6 a newer one. - -+config MATOM -+ bool "Intel Atom" -+ ---help--- -+ -+ Select this for the Intel Atom platform. Intel Atom CPUs have an -+ in-order pipelining architecture and thus can benefit from -+ accordingly optimized code. Use a recent GCC with specific Atom -+ support in order to fully benefit from selecting this option. -+ - config MCORE2 -- bool "Core 2/newer Xeon" -+ bool "Intel Core 2" - ---help--- - - Select this for Intel Core 2 and newer Core 2 Xeons (Xeon 51xx and -@@ -260,14 +318,55 @@ config MCORE2 - family in /proc/cpuinfo. Newer ones have 6 and older ones 15 - (not a typo) - --config MATOM -- bool "Intel Atom" -+ Enables -march=core2 -+ -+config MNEHALEM -+ bool "Intel Nehalem" - ---help--- - -- Select this for the Intel Atom platform. Intel Atom CPUs have an -- in-order pipelining architecture and thus can benefit from -- accordingly optimized code. Use a recent GCC with specific Atom -- support in order to fully benefit from selecting this option. -+ Select this for 1st Gen Core processors in the Nehalem family. -+ -+ Enables -march=nehalem -+ -+config MWESTMERE -+ bool "Intel Westmere" -+ ---help--- -+ -+ Select this for the Intel Westmere formerly Nehalem-C family. -+ -+ Enables -march=westmere -+ -+config MSANDYBRIDGE -+ bool "Intel Sandy Bridge" -+ ---help--- -+ -+ Select this for 2nd Gen Core processors in the Sandy Bridge family. -+ -+ Enables -march=sandybridge -+ -+config MIVYBRIDGE -+ bool "Intel Ivy Bridge" -+ ---help--- -+ -+ Select this for 3rd Gen Core processors in the Ivy Bridge family. -+ -+ Enables -march=ivybridge -+ -+config MHASWELL -+ bool "Intel Haswell" -+ ---help--- -+ -+ Select this for 4th Gen Core processors in the Haswell family. -+ -+ Enables -march=haswell -+ -+config MBROADWELL -+ bool "Intel Broadwell" -+ ---help--- -+ -+ Select this for 5th Gen Core processors in the Broadwell family. -+ -+ Enables -march=broadwell - - config GENERIC_CPU - bool "Generic-x86-64" -@@ -276,6 +375,19 @@ config GENERIC_CPU - Generic x86-64 CPU. - Run equally well on all x86-64 CPUs. - -+config MNATIVE -+ bool "Native optimizations autodetected by GCC" -+ ---help--- -+ -+ GCC 4.2 and above support -march=native, which automatically detects -+ the optimum settings to use based on your processor. -march=native -+ also detects and applies additional settings beyond -march specific -+ to your CPU, (eg. -msse4). Unless you have a specific reason not to -+ (e.g. distcc cross-compiling), you should probably be using -+ -march=native rather than anything listed below. -+ -+ Enables -march=native -+ - endchoice - - config X86_GENERIC -@@ -300,7 +412,7 @@ config X86_INTERNODE_CACHE_SHIFT - config X86_L1_CACHE_SHIFT - int - default "7" if MPENTIUM4 || MPSC -- default "6" if MK7 || MK8 || MPENTIUMM || MCORE2 || MATOM || MVIAC7 || X86_GENERIC || GENERIC_CPU -+ default "6" if MK7 || MK8 || MK8SSE3 || MK10 || MBARCELONA || MBOBCAT || MBULLDOZER || MPILEDRIVER || MJAGUAR || MPENTIUMM || MCORE2 || MNEHALEM || MWESTMERE || MSANDYBRIDGE || MIVYBRIDGE || MHASWELL || BROADWELL || MNATIVE || MATOM || MVIAC7 || X86_GENERIC || GENERIC_CPU - default "4" if MELAN || M486 || MGEODEGX1 - default "5" if MWINCHIP3D || MWINCHIPC6 || MCRUSOE || MEFFICEON || MCYRIXIII || MK6 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || MVIAC3_2 || MGEODE_LX - -@@ -331,11 +443,11 @@ config X86_ALIGNMENT_16 - - config X86_INTEL_USERCOPY - def_bool y -- depends on MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M586MMX || X86_GENERIC || MK8 || MK7 || MEFFICEON || MCORE2 -+ depends on MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M586MMX || X86_GENERIC || MK8 || MK8SSE3 || MK7 || MEFFICEON || MCORE2 || MK10 || MBARCELONA || MNEHALEM || MWESTMERE || MSANDYBRIDGE || MIVYBRIDGE || MHASWELL || MBROADWELL || MNATIVE - - config X86_USE_PPRO_CHECKSUM - def_bool y -- depends on MWINCHIP3D || MWINCHIPC6 || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MK8 || MVIAC3_2 || MVIAC7 || MEFFICEON || MGEODE_LX || MCORE2 || MATOM -+ depends on MWINCHIP3D || MWINCHIPC6 || MCYRIXIII || MK7 || MK6 || MK10 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MK8 || MK8SSE3 || MVIAC3_2 || MVIAC7 || MEFFICEON || MGEODE_LX || MCORE2 || MNEHALEM || MWESTMERE || MSANDYBRIDGE || MIVYBRIDGE || MHASWELL || MBROADWELL || MATOM || MNATIVE - - config X86_USE_3DNOW - def_bool y -@@ -359,17 +471,17 @@ config X86_P6_NOP - - config X86_TSC - def_bool y -- depends on (MWINCHIP3D || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2 || MVIAC7 || MGEODEGX1 || MGEODE_LX || MCORE2 || MATOM) || X86_64 -+ depends on (MWINCHIP3D || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MK8SSE3 || MVIAC3_2 || MVIAC7 || MGEODEGX1 || MGEODE_LX || MCORE2 || MNEHALEM || MWESTMERE || MSANDYBRIDGE || MIVYBRIDGE || MHASWELL || MBROADWELL || MNATIVE || MATOM) || X86_64 - - config X86_CMPXCHG64 - def_bool y -- depends on X86_PAE || X86_64 || MCORE2 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MATOM -+ depends on X86_PAE || X86_64 || MCORE2 || MNEHALEM || MWESTMERE || MSANDYBRIDGE || MIVYBRIDGE || MHASWELL || MBROADWELL || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MATOM || MNATIVE - - # this should be set for all -march=.. options where the compiler - # generates cmov. - config X86_CMOV - def_bool y -- depends on (MK8 || MK7 || MCORE2 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MVIAC3_2 || MVIAC7 || MCRUSOE || MEFFICEON || X86_64 || MATOM || MGEODE_LX) -+ depends on (MK8 || MK8SSE3 || MK10 || MBARCELONA || MBOBCAT || MBULLDOZER || MPILEDRIVER || MJAGUAR || MK7 || MCORE2 || MNEHALEM || MWESTMERE || MSANDYBRIDGE || MIVYBRIDGE || MHASWELL || MBROADWELL || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MVIAC3_2 || MVIAC7 || MCRUSOE || MEFFICEON || X86_64 || MNATIVE || MATOM || MGEODE_LX) - - config X86_MINIMUM_CPU_FAMILY - int ---- a/arch/x86/Makefile 2014-08-03 18:25:02.000000000 -0400 -+++ b/arch/x86/Makefile 2014-09-13 09:37:16.721385247 -0400 -@@ -92,13 +92,33 @@ else - KBUILD_CFLAGS += $(call cc-option,-mpreferred-stack-boundary=3) - - # FIXME - should be integrated in Makefile.cpu (Makefile_32.cpu) -+ cflags-$(CONFIG_MNATIVE) += $(call cc-option,-march=native) - cflags-$(CONFIG_MK8) += $(call cc-option,-march=k8) -+ cflags-$(CONFIG_MK8SSE3) += $(call cc-option,-march=k8-sse3,-mtune=k8) -+ cflags-$(CONFIG_MK10) += $(call cc-option,-march=amdfam10) -+ cflags-$(CONFIG_MBARCELONA) += $(call cc-option,-march=barcelona) -+ cflags-$(CONFIG_MBOBCAT) += $(call cc-option,-march=btver1) -+ cflags-$(CONFIG_MBULLDOZER) += $(call cc-option,-march=bdver1) -+ cflags-$(CONFIG_MPILEDRIVER) += $(call cc-option,-march=bdver2) -+ cflags-$(CONFIG_MJAGUAR) += $(call cc-option,-march=btver2) - cflags-$(CONFIG_MPSC) += $(call cc-option,-march=nocona) - - cflags-$(CONFIG_MCORE2) += \ -- $(call cc-option,-march=core2,$(call cc-option,-mtune=generic)) -- cflags-$(CONFIG_MATOM) += $(call cc-option,-march=atom) \ -- $(call cc-option,-mtune=atom,$(call cc-option,-mtune=generic)) -+ $(call cc-option,-march=core2,$(call cc-option,-mtune=core2)) -+ cflags-$(CONFIG_MNEHALEM) += \ -+ $(call cc-option,-march=nehalem,$(call cc-option,-mtune=nehalem)) -+ cflags-$(CONFIG_MWESTMERE) += \ -+ $(call cc-option,-march=westmere,$(call cc-option,-mtune=westmere)) -+ cflags-$(CONFIG_MSANDYBRIDGE) += \ -+ $(call cc-option,-march=sandybridge,$(call cc-option,-mtune=sandybridge)) -+ cflags-$(CONFIG_MIVYBRIDGE) += \ -+ $(call cc-option,-march=ivybridge,$(call cc-option,-mtune=ivybridge)) -+ cflags-$(CONFIG_MHASWELL) += \ -+ $(call cc-option,-march=haswell,$(call cc-option,-mtune=haswell)) -+ cflags-$(CONFIG_MBROADWELL) += \ -+ $(call cc-option,-march=broadwell,$(call cc-option,-mtune=broadwell)) -+ cflags-$(CONFIG_MATOM) += $(call cc-option,-march=bonnell) \ -+ $(call cc-option,-mtune=bonnell,$(call cc-option,-mtune=generic)) - cflags-$(CONFIG_GENERIC_CPU) += $(call cc-option,-mtune=generic) - KBUILD_CFLAGS += $(cflags-y) - ---- a/arch/x86/Makefile_32.cpu 2014-08-03 18:25:02.000000000 -0400 -+++ b/arch/x86/Makefile_32.cpu 2014-09-13 09:37:16.721385247 -0400 -@@ -23,7 +23,15 @@ cflags-$(CONFIG_MK6) += -march=k6 - # Please note, that patches that add -march=athlon-xp and friends are pointless. - # They make zero difference whatsosever to performance at this time. - cflags-$(CONFIG_MK7) += -march=athlon -+cflags-$(CONFIG_MNATIVE) += $(call cc-option,-march=native) - cflags-$(CONFIG_MK8) += $(call cc-option,-march=k8,-march=athlon) -+cflags-$(CONFIG_MK8SSE3) += $(call cc-option,-march=k8-sse3,-march=athlon) -+cflags-$(CONFIG_MK10) += $(call cc-option,-march=amdfam10,-march=athlon) -+cflags-$(CONFIG_MBARCELONA) += $(call cc-option,-march=barcelona,-march=athlon) -+cflags-$(CONFIG_MBOBCAT) += $(call cc-option,-march=btver1,-march=athlon) -+cflags-$(CONFIG_MBULLDOZER) += $(call cc-option,-march=bdver1,-march=athlon) -+cflags-$(CONFIG_MPILEDRIVER) += $(call cc-option,-march=bdver2,-march=athlon) -+cflags-$(CONFIG_MJAGUAR) += $(call cc-option,-march=btver2,-march=athlon) - cflags-$(CONFIG_MCRUSOE) += -march=i686 $(align)-functions=0 $(align)-jumps=0 $(align)-loops=0 - cflags-$(CONFIG_MEFFICEON) += -march=i686 $(call tune,pentium3) $(align)-functions=0 $(align)-jumps=0 $(align)-loops=0 - cflags-$(CONFIG_MWINCHIPC6) += $(call cc-option,-march=winchip-c6,-march=i586) -@@ -32,8 +40,14 @@ cflags-$(CONFIG_MCYRIXIII) += $(call cc- - cflags-$(CONFIG_MVIAC3_2) += $(call cc-option,-march=c3-2,-march=i686) - cflags-$(CONFIG_MVIAC7) += -march=i686 - cflags-$(CONFIG_MCORE2) += -march=i686 $(call tune,core2) --cflags-$(CONFIG_MATOM) += $(call cc-option,-march=atom,$(call cc-option,-march=core2,-march=i686)) \ -- $(call cc-option,-mtune=atom,$(call cc-option,-mtune=generic)) -+cflags-$(CONFIG_MNEHALEM) += -march=i686 $(call tune,nehalem) -+cflags-$(CONFIG_MWESTMERE) += -march=i686 $(call tune,westmere) -+cflags-$(CONFIG_MSANDYBRIDGE) += -march=i686 $(call tune,sandybridge) -+cflags-$(CONFIG_MIVYBRIDGE) += -march=i686 $(call tune,ivybridge) -+cflags-$(CONFIG_MHASWELL) += -march=i686 $(call tune,haswell) -+cflags-$(CONFIG_MBROADWELL) += -march=i686 $(call tune,broadwell) -+cflags-$(CONFIG_MATOM) += $(call cc-option,-march=bonnell,$(call cc-option,-march=core2,-march=i686)) \ -+ $(call cc-option,-mtune=bonnell,$(call cc-option,-mtune=generic)) - - # AMD Elan support - cflags-$(CONFIG_MELAN) += -march=i486 diff --git a/kernel/kernel/files/patches/linux/patch-5.10.11.xz b/kernel/kernel/files/patches/linux/patch-5.10.11.xz deleted file mode 100644 index 93aadcd31ca44359747941ee32a93cc7a975dae2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 397188 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 z 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 z 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%0A!sThUeK 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 $=%fg*Za60 z(%JW!YODH8T=DQ1rNY{2v~n`#(_}V#QcqKcQhk79(Fvhbx+ zsyI%P1cpSOQbrsq%v4MMp0l`f^_!a2U(b#oYqY}_1R4y=X5{db;WbI$w_45UIB`=B zPj=@-I!il(1-huUHwd_(=tHktjj>VK&J`+YrEtQxPK;rfJjQVR4_oJn{r@sopBQtv zYxV}&n&}HfJQ)wieeDAQb8k9~afQ2&Vi)mS1r2S$laSCW=%9gH$gmfuGI=FPRZFj# z5Wad8K@w|I9HY*riz+E!1)G!1TzEm>w!&g>sjs!c0$dqGs?ce}y682GS!4A9$d_39 z7+W2wcDCjeK?kkvQ5f_fgMv3};@Uaj;p6Q3;!KZrY3)SI5PtQ!hQfH`3=wV4BRuF?#W`Az-4Msj}X1v0;&wSHt^Orp6OUds&hQ@ z8lvH3pPT|V4k!*-hx}>B5F~VL-oTx`#RGbJyHoU#t@}Kr<-m&_t=vM*vH1nB)5v<# zul>w6gi<|$^>XbMFOYZ>e{BA7i=I>54_%9CBy&p-^QD7BnKmrk91kWUnbPSY#W~xD zh%gu|(|w%ZIEWZH$+xf2zRMwTK>tU0<=t<+{bImY3zV?nNiq2k3EAvEL=KBXAel%N z7uvjb>#7etXk6p~!utjcj^g|_6OZ0?dZ#DWGi<6x6}^S5GfSkmtLWd77BhqM06>_e z@C!Zzb`@hwu{&1#Cf)QFgl(OphRL^e>LqW9Y;e{`$KI#4X>`-Y9YiQ!gT)bM z*M0NK9);rs$^ppQj#xkFS~Q8A(2E6|0MZp^m~q#V#GuE#kqCpwr0+aPZ<~5re0=D4 zOzn0WyQ>D1pYM_6Q96Kh)VFED&y$NmMecc8!tRmjW7h?4i3$m1sYK?F>z^8q6~!kp z%X~RZdA3WXwy0)OHa5g>d~)rADO6e%)%jJPD@Gaz!K~jx`kU8Rs+ixhEpS@8ztB-io{$x6o-TK?jiO@C_NDgaxmfh?hz5pEY=a5lnPFe9V`5|3mezuCJp*f(m) z(FO;VP(4W5fcC<$`geUQB^&(UXyCFLh}~lQ?yYHSQ+)(Bw!l>H61X|ub&=i~IrRvh zVv@RadB<~+p5K3T7b%G4byD#=*IDEL?d$Rk~9}NSGB-d}M zCRp0C7)tty@P~x$e^z~_MO1SgeZ6{H5GDf3i+{C_Q+0{t+DKaejGN|G zWEP~36z|MI1Pk&x6dyqvLNz@Y(TWJw0u>TGrYSh4guWgyIw3@eJ%P5YQ_CA<6soz&!pe zct=uj-*;h%=;b=Bz^%kk$yUt>@oQDr&SNU{2bF*ZakQ-DJzYNmvrp`77EjOVEW=4V zZv(Wa=I(@RvEe@gpb9mfIl7smgZ5w)hT#UTwtLZ^4qCwp8)(5=hFX{r7SClDB-{`8d5nR!T1} zA#5x|;2iHRYTt<7cQyaiMk3t?Y)AOa`UaPP?gs)W@ppd2u6>gTQ1R%w8^?*pfB+D@ zZ~I$|6G}uBhGX?iFh(pJLWjA5-FJ$Jc^whAc(8=}71FONOhzWbp4P*nMSY-)XCNev zctRZlUIq7Wpugl`C*wA`XW=GYic#V*jj{q9OM)qOSLLi`fk-D)6KK*h8 zhX|VBb&2Qc>ipzhDl`G&wXeKsrbK?QmHeRqgh9>k{s2w>UdjNF1BudDO;l&d()0*N z-HSaEA~7J4-z0=~41P1vFl|W%jMh4@G>%eGRCSQ zf-cJ=)ma)96S!B@^=U}lC5^zqNKoxZWPu$*$qEk3=Ondsy}arTjnOBYXs;!cx;tOg z8fwSkS30)!i&H5paPFQw1ggb`leT$wP>O+>__-kBQ9f{GY6tPOI`i;q%Jm(Qkz}2v z;^T@0d6xp+248oK(4yja@fFw$WpJx}1`@*>&_hJ(^DNj#*ZF;1yy#Z2zPmjL@435% z_`2e%LS8(pD<_5|5upK^`am{thc%-MC{T7zb&%o28VHV&}~y}GFC-R z!j}|AEf50)b1#ldZ}xZPG4sos!z>=wkxxtYhB2i|(1#t9t?Z6Ap7EEicaG6u*G%G- zXW$&a>SmQhlx;q^$Di``P5>m{UJ-de*NBYMfxfT5Ktq%L(+kM+X--dWHKKsaZy&W~ zs3i}rcJo`l{iy}e4=7BStO_vg>>n0I(isf4A(R&i`-+?L&;=bny}L_g3dErgZt8V$N;BDPrt&3ozy6eA|Wxll?YOaxj|ZRF)~;q7a+w#!;Px7CPAwO zYIPz<|4Zy#W0PWHq8-pqz^z})Z%YGVK-Ot>X4Dv5uu=KiG*Lryk1CHH;Ge%^J>q7S zP&En}v(2|k^z5;Jpflo_o}!OAU>q!^pa|!!wjEXEgL^mg8TApRhT{yGf=7%|EHNQ1 z)2k*{`~q3d5)wZDj+2ORuI-Yz;STozV*gJ(%_!iCtOTM;zPt?yi}n(0m5{ejhuw12 z%&1=fCrjFJjAI%P(CsO;7W4+aefo+_cLyBw#e=ItFk3c--%D`o9W}!TmaXG=G6Wq} zL3(T~++;%5ocxsMkZRFv&te@a67F_JG{BE93d$bappo`Ny3yO{Knq56Z&qp9;iq#c zJ4a|ZrBWHc{onKCSJ5Q@!3W3I1MVF$X8Af>>b%MLOb|`M6>`}ze8FAAd4IwdAF*0{oWb*AKj4cq%p=NqoAlf z)dr}TG(%Jr7pQIlncTzUAd8&>O!F-(>mTNG8IEIpZ_>N^VKzvr?JsYW(H;l{;Q8pW z`L?j)r2bWGivvD163aaF6kGdbcN#J_; z5ryAXhpS_-;nB5HdTzuG>jC1NpmJKBi^xDoISV8e+WP&AcXCoguu))2DlW6vF-5xa z?k@3NQ26a&n<5?e7m~)J)?WD8CP67)9Ex(ZD6?PFX?w<6e3~xKjwOhV+xZoEtvxPH z%s+^T1&&jz;)m0K`r(~W%OiT}eW%@XR_Yq(` zL9!=}#k(JXB44Bc)wLGYezoX2(!qLINOV~<049I9pF+@dDm)pH!eM4JpT(uRAoR+o zSl0tQPhY57dvXK2f7~vjah^lC!ewZW~D4%UQF20Q$w5zmq-=k9P~Rub{yx(lLk!Y7hP` z>UjCRuCT@(Ak4~)1OD^Md}DAoTzNfx%L}+bGEKl_g?sjylmf-zx7<$@K?i4r?1zu9 z(9vLkS2{Fbq`aB=kadJm4t!=CmEJc|PS(n=S6(yOT#;?d=UQNt;Wmqafl@Q30SCy$ za0LfiYVyAvgELT>lP&*U^N9~^tOV8^@k6~`l<+D}Seng^{%!>0%*F$N|ABQL%#0>i zU8@J|{V`)su z$(^ng6hzA|81NR1z2=3k#gkSV*Aa?+j}5KsGm1W%3eBN!v-Q6{(+d-o?|_Nz+*y3t zZ@t8l!J+4BjYbZ*Cz|G&4=MT#MOM5t9?k}w9X6_CJoft6tn~LGns2G_;2yZ+^YwyR zQiTOW2QB#AP_;v8nj^esuGzcKc5j3t?7IBVJ$k_wi5Iez;9kMkYcWh{`_g(Rpc5=x zxM+e!*0f$~rv4Uz5p&3=WxaNyvXvYDNM!9&P$pZ#yyfc%rudb~fmLLgsx4e4?%AyR zqSVD-?qT-(8D?=Ig-WUj#)HV&#ZDmt7{Gr6JEDI5vSnbvc6%U&w|KewaOR3z5M?c( z8}N6A0dLJ=g^8BrbjL^@f*V4%bFJCqF5!1)J!A8$CdkjA-ozd_lJKL4-+77##rUV@ zEAmaBNrPl^GNY|B!@I=7tt30yYbTn|iq5XdT--gm3(B*u>G}rERxt8`W%*vmqN41A zd8skqcKOU9pURoGs(m!KP|E4i4<4r(615ru&G0_`4FWSdM3U_ZC2O!BMUaIHI5HQu z_06rh@AA`VF$r|X4q>=tdEs8_lV78ndc<1hyR~zr5@`Pf_pMXa|_@9lL@Del_$IM!D^^3F4$DesG zY7gKNXa5hsf&?d3flsT$y*hcnjOgg}ABXUo2F=~Jgo_E-St8JY08W;^&Sb?HuDO(< zsoiYen?Bqh1`rHhPpdZa$^~P%BdI7SJD73)nOg=$n7$dqJXp;1fWu5#P+VP zE+H6bCObu29<|}%1{mb=qz3SE#4;HjhUp+P2)$U+N&EJ-pMtIVCQJ(l@W+ClTNTz- zMhYIqArK|a?%Eo9>}eo85oV%WXIk`>qdVfzi;&%p-u5Vr|sk@p7B{fy*T1ro&vOL?f7IKQ>VFVq^LW*{GWA=_Ao`GD|S}p+% zGe;fyvN)e-YQdnc8q@G6GwF`ztVfLAyqz2f(uJ(0V0!OS7^vjU6aTCxp}n!^i2%Et zTUnR9y^%ZjIdO9pn8Ef9h`t?!)p(id4N8db|= zRs`2Fuad?uR*GR<5L@I;F&1CHmbJau$p5wF!^~VmC8(w1(iD}r#@IJ-1zW9h>LcEq zc*U5gSpUh$0l(8nM>nO=l_Y*K2C966#_qfFK-ySpt*x!`PO=KOls?C8diM@6Vrhv< zGnteFdO2z#*9J9><@Upduq@1KV6rxhbBFoLrhi-&K#s2hf3qL zJhP4|NtmyKl@z~ylD64;<5Lc#JzZ;VaZK06vG5_KL*qB;SQchH+^lh}unri$qu5`C zX;RW>(fT~0F#|YPjxb;qaKeKkpoQV|#e?Mx`vD~1i_4tgoew*~Je=+x8(6@PW8k&s zE&~V2CNl^%SDSPYH_p4di3G{sjk@@ZHS6=IFF&*06^S(OmL<220QCg-pdX)mHgcmi zoKLUK3?2>%dg6&5w;IqEaI91Yu#kahTQ3U^&n%%=hUt@Rzws!|r${yFxrwrR&o#LYLq+*F%)96)p^Pg`0PY5?Dj1cuG) zc~{R}T`*38h|^0^0tHU2m-k)nka^PD-Nwq0PTYvC{~8Hk-Aw~lUP1-uBHw?ACh&3l zbGq2q$YNezdsP*KF)3r5Fo^xK;?~)ALg_ef(mb5BN?47JIs@OJ8&WPKl=pKo{Q7YI z8dU~5Z!M+ywEBJM68bxX9frnG?-%Dy!ITzPBYcJWiF<^xs+deK%;hOmY#c?Qpu;RE zsD2D0OE_m}Q{Klg?`ccwxC!lvCrK#0H{zTie(sz%Fd>h_KC%tcxZd`i-+wt{%(L2b zX?8$kBi-RSc6@k=ZKuzrw)+?Xb(XHuHa?hE&2`o&6m;OrR#~V&RJ3`&gz)g;P(D*D zDUV1<>NZHFiL`(^4e{T!b9~0~bMB+vqi4awKY!K5*iR)4*Xy`+y(r%PLYi40)IWq8 z`A>e8FTn+xIkHEVZwE3Uk#ITtxww-j{`>*2pw{L;wlI z%BOP2_R#R>ICF#^G2w8g)>RNf@fT0tVz<7k@!G4?G_I;3sxP26#_u(c=>XkoFOq(e zbS`O%i?G__N9??NPJeZoE*>76-I~@$w9V@IU3#qFIlHFLz!_wtaD{>nKgTz&qx@LK zCVdP2#{!)ZNEUE?4hq`7Ns&3X@y67bm8>=jx=zDSS*U^G8Tms~fa!)PqbFxgN{7@y zN{is!h<4YkU#a32f-lpKS)yPy@Uxhq85?*S>M*oWk+qt!V&5snX8@wQ66MW%F$&7X zp2kDpI3hHg>xG3y_7HN*$q-QcgoC`>rR50eUfD#}7|4IrFTX|*3l2B?cHYYk49^zs z+Qr)@3Qp&gDozeL-iS`B*z={g#nm-{_roX8)aAw*}#cpEjzQ34;Te+RfnFx?b)qoe57o|2{; zIQ{)XRbze1@Y>d6;f^Mcq19Xds)W2-3Goeg^iopSekFQ;m6t^<0L+dgUy$?uc?E6r z@|zU({d)C65mX!zFw|fcqS#YzatHCzb#5*)5^;sRkPect77qJeYIW4D6_MZrZ^}B z%AOI6xej84Rx#+Qbq3Ib9WPXg|M)Z|8U8Y}@T}B#W75;HY`pv?RVj`WwW8Gp5GElX z3BAWDPTp`M+9yyC1t*#hg(gW_rGgCm^lA5lkfJS4F&5r@1*uIsp8&a zmm2z>9g**3;GI0`*T3G%RYFvaTJuu_3*V%|q_95NL<-D2zDoA4T0Ay6Fc~9 z9aP)7a~+fM@^3{Imugyh{{Yg6*%~`b$CLO;{1<=;sV8(x`uu=&5$e1h=l_cFLz|S_ zrABDl69x+O1j~Fkvk}%#*TCdg#}yki*pFhz=$ZTKF4!isow36sqhYYQ|M_td8u6`i zZ=&BQ=gfFWCqmv=g;Lg`+?z>nt_A#OA6OWDApvH~a21265^1>N$ck1T5(E66frrP1$E>`neEOMhz$@-&+>e?8aqn+HH@;g+XcLcG}S!D&I z+SFT4i)2*Ga3rZW$J&ER^ zVbJ2mgKqW_YUb`|;4_P6A9sVkNdmu2lgkOUuN&&uI4gdw)G24Bqj#N?g50S!?nNRH z2v2VLaAenMaIEj9mHY-5elX(D26FrGt4EhD+yXnki1&LoJX&^onK%-M+SSPe?-y<7 z%|n7l&uDdBUgn}zCH%d4aJh(x+iiLm`!<=H3y^ws6*ZKBL;0D^czzRow4CL4rQ}4i z0{e~4wMLJ;tj4^U5xxjnjjJ%oe5#4!N@RrR9P$;fJVZFRQWQpLPG@SwVAJF4cd3}K z8CA=oPg)B)B2Od>h$p;L`ktpP`P!k>EzcUcj#mLMt@zEiq`T-6y!asqGnktt_N-|f zYH9S6;eO1BY^kchETd`hT4a;VX7B6KmofjvEwN6Jhth8yG_d9Fd(7Ty_ut50Wv2zS zxV$n@{MD=7Yv8Z=uws>L38@nAbbe&OnbK0)EU=R}NFQ~BwiP(2w`4GGRRVI8l?0OG zl;VwmA}fh3M4egM4MZ|r=!S(^-j zew+fd(^Xf!fx@Ypv$WYSsk=iI3fW;RSPg!aO?LO)!pXX}&+zn-^^ml7N!%XXefm4nykI{j))~iA2Le9 zc7}{RLpK9J=J&&#`|M}guF<-WAGF}`61odF5o@D6KEIW(e74|EJa)AN8J0xgaVJ{r zak{P12QF6U3A|*c1dTv#$dYa))!Yc%NA@R2Bvr-L2mJ1-HH|NGlJZ4|6D292&!zu9 z61di1vQrSO-t9ZgaI@pWx4$Q2_+;D>hY?;BxU?KGn@8@kMRs7~w;(z`kn z4offXhUc<)z`V`t7pVn?wLWz3p04lXMGWb-z={^GqMGYdfMi4Yx%7vSB6C?R>jVKw z_hqVVQ*Ue3$KYW@Wnz?2O|BQDq5&7FmOFFTRlur48CkC6EPCB|OUl!_&nd#kt<%K5 z|Eo8Y_+W0dq*J?M0W_9E(0L;6OTmx->&sC|Ww0tt`Ae^i++a?YPq(%AD+~V(>f3Ab z2P^Wv3|PKVb{7A{=qw?8#-$}i98~cmyJvY`rQy6fk$~FjpNmDLNaBES!3QwW3k5Dm ze?PIrRrCdLItFztY*!39p}44lv&)yr{=W;QPW8YIMgluYr6#tjrx=Mi)ok&mCYvuXYw(=UdA}0EcYg5Uh*a zWIq}mZuSr$E{q%VksFMpEIv_I8O={iO>0u^0)@WAFU%GEIkIvE98z6d>zJ~aTeP2z zVd3NaAFs%D9xQFPHYgM^kj37>cR`}0Av!gpEirYany2*WWK7Ob#9(-O*UgG<6i5$( zsl_+|=0KY4mVQ8A8!-EwlJ#}9o~Q{|z3#3uC5^4>5b9BF%0L<&IN5cj*k@adLB=Vn zVJ%H5(DS@;Z4oWuOA?l?}w&W(Kk z5;HJPpZb0j*}%#}=L|prV*|;LKfv9DSKGzwS_uBlOfd@&M$+%}?}MlyA>28)wf^X# zCiuy=^4lIYk=}AZ_LO`Hs*Aou4dBSv=OI&n+vWI!IJfL4uIQW_Vf#xQ=6w~k?NmJ5 z#dLkx$GC63TfGZ8MU7qG+TB+)tXEkug6Q!4x$3ix+Z}Am!9bGKCB# zQTy-VywFi>r)#J@W9E*4F~8ihQ!5~+ZvI4PrMi3VJ7XDv?QXiHy)gHq>;kv~?QVbn zPs3ka{h zXKS0N8#aq|J~p&2JOe`c<9Pz0Py6)490d*f9Q&1wsp>O2jqvQ~%n5(19n%L@>gx~; z8M4F1ehzCMcvH-1&JO=e`G`CqvYZ(qFpW1WPFX9j0dWH?&gjx~B*^zA|H$z5L33*( zLF%s^eX2l%=2U#=MiZ{h>_JevNCP9ZW>wR~785HEvJfkn%xLz4dT06$QO0TVIv_;= zg%=`TwbdQt08@7Ier3582Mo5)*G?Dn6$%O`!Ok55An0DHhDxa7r{)43YZ?3;m?DB` zP)=IC0F8;U^+JroZ)E z7_KmX0CO^qNsO~9`Z z+4ayaOA2_6Uz$OI*uqSYsOe;>-KcXc5SMu<``4FHMHO*e-jWbHfR0~UvJ!DX#cK8^ zB^gBDx4Q&5$kvY|HSbxATJ)AU^{Vf=`rf7dCm*$k#bX6!46~~W(`Jz1(u>D=mokG6 zX5ytP0bbO@5w`V<9NlkaT11X@C8D!9vWNqkDs>aTm4dno+04CpMw-QLFtt3C*$RDu;&YA%7lH)oEeUsg7G-2nBtA|-X z-MBKksayfbeN$H|bp;lbdlA)s0hi#30Dy;ylG#M_f{A2ChLo;7OH>!M6dOTulF8HD z?~r=H1UV~cughwdoBEesa4{mXMB2DHo17`E(MV^v0mxTA;ru}UtP(P4`7))hG~?Iu zR-R^VjWEW+cF3xxp%HsEOW}(5xos*?sZ;o(wRntiT&iQ|&W^!>jkV=n`_c*PkCk#X z7-EjMA5iS-AZJDiqe@Q5Tl}Loq6KMOt(aXAFO{I~U<^jy>r>QCR})QUi^IA$UutS< zwRFbj5En0oA1!|5Yf0jms#Mg9mnrkLk9EN(;)7aGA}mI|9Z@rWgaFNa_luDKCNf-m z%gM@*d<+~VN;;Lp{qxT9X7p^@Nojs%fQB32v5;IkQ$^()qXNfJ3>7B6epYzyZv}Rq zFT`V-O;gP7eDd9h$vz^Mgm(G8-69_Xart4vyB=Oplv-Ib@X>xBj+cDb#Z^&A!v}AQ zkAjpjv%lHi{Mv!nmTgEX(4_yS!m(my!7#V;QdCw=LJHu@H4#Z8ab`ND6gI(pGU-=Q_M)n_zE^s=ufD8cn|(}IzkF;Z%@4haJx%bN2a)w zzmg=V*4?~`}s{4nW{!>#yqn&+KIXhvIocdX6517V{r(7 zP%R)bDj`3fL8ryS`_+(}qrb`tFndOre>+sxFt`7SdDPbmk9{ot>A?Btbr=pzf$wZK z85AO)HuwVjJRlS&1PKSt&(kNQ6%+ipqT*C3E^}{nG7&Zuwji82;*w$K(P7n5;i=MRx=on`A1u$iz!RPyjKSF|7oc1`0s5K;16`ztTC!AlM&i z=^L|+FbEJMYDmh z8UQ!2+RC2X7y|qs3r}-~?ywNq2}bWS>DTy<7 zkSxw7wWp-KwhcekO%EzO+UGx8SHoVf>AA89 zRfBFLxtMApdP_lHC2daXsSvOSb$CrvlxS&!c+PxJ=6+muQU6!YCn^InpYQ|GAvNuXT855f zZ8q2`53?7*v%=>gp?{*Xpba#TYgLnXz9aT{@$ius<`IZVbfM3aVCFl3zW!v`zI#Ef zb)6QG!#YS_2!*|xI8aMUYbBx*UvV;t;YwTc=CLUSB(Vk697QmeD_ItLpCV^t&i6BR zsi97iiL%;hHDW7Wx6TbcI9dgpp{OkJ&?jfbH(i8*G?4!A%Tfgz&U?g9ObW+vb(m@a zZ680V#?vOz$h{Q6mr$4G%a0O*KjF^h73IF}HG!dHxdeoeI9wx>+@tH^Aq)CC4U*Wd z1T*;Ah+;$3MG!nEqE-yVv0|>WRZeZ+f2IqX_Ybd;48sU7Y=Y_Z7X6xz6$4GY#~1Bs zuesb8*j?PsQ%OXeE`O}Qu+j--xJ$dWpgDU#3Oyo6T&hk!yvJJK8L5y2JPi28{k>A8 zt3dg5w;+cA2V>arD$<;O?3Q3ZujhKluQXj-7FiCIo$M*oW*%RqI)X5IF%m1vy3j=5 zWDpy6hk-b7|HX$z7p~pACw3Wzux%~Ip(+Na0kgE=@N>9Lcrksxpe%N!F4_rO60OGEd9{*>)w^(|lF97@sr;z^*3;pbagNlZO}-=w&*jI% zqszz8G10Ou`Py(U$rgod`{Vlj>F`_umRlIqO=s&jgkN{0U zvcF<=x!R`jGd_D`A&O{b)KJMLBHHi1Xd+}J7?*F^KZothme!3h)`VToNliQ^4qjPZ z=WXIhTDwHcH4-?<1v+86b>PQWxpY}sXr1PAiZg8B`Ch2gYc+dKvy-9 z!xgAxp=Iw!0#aLJZb#L-w$ZzWjHsa;td?@=YK?SpR1R!E|FrEdL->T_&GPw#orbqr zA4%MTLTb9Od|i~4)dl?8imh3Y9Bi@BxVsAfo+X#a*7|~JoS_7)!uEgx*1JpflK~+`Hjf)Nzpn4hz ztwr^YqNb}n%?7}x z_y(JpImx=6m{DRkDDcK!Y$OA;Gd|`S%KqL>sY-Yd2i07A48|~RC;E~%15KwLaS&eU z@P`590CpA^wvuXEDrBY^F{4w-8l3syn_lqDQg-rb$@!oPuQWA5<{kjV8JbB)?gq!O zu;0|!rc-^f<_hi*aY~DnrsFp&-NNAoc7%iYOVxrQIdJ%05?VpWMu!EjL`#C`_!(HJ zy)neHsd!<^QC?*|b631sDcjD7Q!V@QmK}Q&R=l%DsqMu8)u1-;?o(_@01iE&Z?1^f zoC#VrH+XF;FE-Vz0LmRy$B``cm*L%sjjq2$L0;JgMiM7z3ZEm12+HUapu1f}fFZ@7 zaVwng=k!x_UNejyS;3L@cA|Koz)pX@4ivD6qelrgqbw}2WXl)JW(h^9at9DCEG19s_6HD$Z#Iq>6w^{W(B85DR+(lUrOJW44#7pg~|f$Oy;|&8RoAo`cY*ulz!y6 zwsVv_(&BtHtO7*d=U*o#mKmB58H)@ybggSQr#gX~=-7gDKFL9gw#zY>*#K)1B)hok znD{r&)~!WI$=EpdJJMu7tIV4Y{0ciJ8|{~~mKvLq>JS~;-icwj@QD;Mv|#HNu1XfV zmv*}KnCrp{cb>B2U)!2q@_eP~-%9=HuT1^`Q9iCIf6&tOp;OZrjj2R;}OaY2Ntv(grhRvO5>%x1=|9i{t zKxGc7qR9_p@Ey$EK1=9B^u?^pXa+Gcc#2-Vj}~lKfszXB$QOK&v#>+yt?|T@V;BA@ zyDbxKJ6lAJ4P}64_2aZO4i762*ik*OH4dKE9&J{sMwOzBD@kOb8{bxe5M!@<#B|p+taV|4&UFy=>x^;u`bcVR6r^jil$4fp}qTObfK70X?A2f96n3{=)B!Wc#)(%HQN&# zY&|w)TSh_6Cbvm)Li_MD57;NFs(;u0+2h-FIntgTsj=sGb=B0&Sm9(KPhrMGb~i)p zf@3rAaOjofg9XYigSz6eP*9e5>0v+d9LOOq#R!^fUl$hodt$Bt$U8{zGLSmAX-N_4 z#>uCw^yreE9CRL_MB$&4%KimE%1UU;!sk#41H4QgQ=#7Ir-eF>)HO;YN04?A1oDa- z_BPXZPE&5*A7dl*DIn*HvGDb1>C#?P_mKfki;WH=cPBP(lw1ej)w-l|HIhu}-6Lr( z_=e?EO#gq^Q8WMoYBc*#w`4PYw=ds6)fA(;m7!ZCV@<0N7)8=7_<6`$-})Sn6OO@Z%iWXbQa0=rJ@b!< zn1BFKC2*Eu|2!J#LcDlB4Q*Lj5eTP#k~la{wP;Nz|^Qx!1O05R2VD#~fW! z)T3FUsfJ32i9;Lz@{`E1isYApd3b$DAXU$c=djmIIGrzLSU+bVyAg!`nc>!G88+7OyT>Ou=*%h@xFkv$)RZ~0(Z}A>z>rrrx;48d zAx7ikWvNv37TeP_oTdPLpf1+T(~{~b95pA#SgUJ9!a6zOigJT?l64uAZYmm@qZ-eu zr5bghgJ%qu;M4s;EdUJXiC+{vCwZ-ES5NgrSa zdS&hXCAeifyvll7oIy5GzW_uNM=%h?HcW#79o4;aZ$>`Z-G8>%$y}Gt$`P`n0_BFf z0Zhq;IACaUSHK-t3FdLdLDs~UueKe@uK{KfQ}j!ge_C z-+xG<26J8-WU$Nfhf;?W51^;m*4$o47xJWn73t|fx&j1> zG|Ens9k!}iFtNrV`iRz(GY_NY#w)|)leZ(022+q@R>>J} zbQYQ(1}RROD~!P8|6Igv2@`Y<&qdG_x^SR=v0Dw=r1z*-yV_1DRm?mWuoCB{;cSeU z2Qhc7lOd4knZwPmfCgS2^X-DUgQJ?Fd~o4YTn#P4lR1nhl!Ya+KXCiYX9jLPL}@bM zOp}V;E${;sOHr()MMHmP1oNQJLyP)f0thKI;a&2Y#YD&CrW0IBwa!fs?(;QH#Aly- zvgoatT2=G8FC+%hxwti|yrdvYBF9&%jBr5+UukzWY&2x`7RAst^m?qxy7_vRNNGM9 zY(?ChjX+haDZ2v`LW1hNmKK_oF3hItmwNsJHlVlMYWOG6$r7~-PK=aES`nz)<;F73 zaz-^4rI&#+`gQxgtA<4$Axys9>#3x|dU6pCp>VHTs0Q%#Uf~&qqI`+>Xi|U35)I%{q~Gk%ryPBI1cR>!^#;@d3YxTN__s`vJS$u&k5w zO_j09nrk+8qPYvWXfy*9^2+#NEzLptF2R4Gx@rsD>%vw zSw&6#m)w{7eFSXUjroD8zcqvhR*U;d9xjxN~-0$UIFw$}UQydjlf;KL#T z{*hdS@OZ7*J=Tsp`_VQ!Vu9I&ha??Q{~!C(Dk!`OXM-65tB0J?N5n}9(E#w+hvT6* zyMDl`z}5>Lcez63!3xIp91k|868htdfXTh2tJ#JjGI-7vYJi5YzYLGg-zFC6W_iMo zA0%HbQPFJg-WB!3Aa1X_0Q*u2f9GC1ut2W^{4Sqt$TP-FthBWYI0hG%q^YV)3gq00 z9KWc>eFP4wz&8H?{s{sGRhzV@Mwk1F4X=Y z3Z|Mgu0O;UsV6*FqLPsE18uZFUrKCIssOIxkw0QGOukrMAQJv`zsHJ1kcY}YYV~~H2Ezz9^RN>cRbHzH4N3>Cq*z{Qdao4HTI-Z z^my@|`Z1kvedFUhX7*xF*Yq)%s+O}Ywn7=5l>xi={rW%Pe64Ub=kQIv00^tCVNP`( z3$gvR-2nF2wHREJ0V5RY9t*4GaE_S5K{Y85@XjnIw{*p?123JGGW5f|jeKd#-)$Wm zJiE;zI7yA=mpI@at-tP!1Y&jZcOBH!oW$P=J`l3v%q5M$(x5#RZ15c>J4~vDpTlM; z?5H?lz=|^*YEHg|nNYlFkkjG&uI8RY6TYt2`|;`Z!2z)wUf7H+=Pp?&m61kqCH-W& zc?j(%h-I7fZLsr1^ zGTadX=O13;6L)NhdoD(5=OLsNJcy`)3)Bk%CqU1>r_61~&tm6c9UmLkSCTXZPNs^` zc&H@Qg=zj5)TqE4iakAA|H$!mk0G!H)$#7=+WIQ|dLvQN2Wdv&n-=@j2N`SsV(H{` zaI*<9Es8S6kO z;Y{1uMND61xVJ*LMC~d*ZQSazB9@S{4)7`^TSOj-aqcXvD`m`zhCTXh!LZiySs~Q? zYJLM%r8`mvFSw<ja;^n>ET)3X1cqz(+6XLtwK~Fqf_0oQU8eKTm7bq~Q z2VV2`T`E;m-knM{x+>LQ8ixqLvPbB^RT(n{xopdUJszZVA}GaALwSseny4*u1%ZcV zilWl*T6*#3ta8;z<1K41!be>QNX-Xa-HR{w03S?$*_12Gt4Mc`U7V6M z>e2r3sudUtb8(1RHuLUE6r88{nh6jX_AKs{r=kxxRVH1Zusme}ayX4^JUB|9<`2;K z^s?+Y>wY5UH5VWqh-rIJSU6AI?ck_;J*&pZ<08FJNAu1-Vr}&hP*ijHOOmt3X&An) z6&Ttv(yytrujaSjayW#CO$7jK3;mdTvSq_C~g=$bWJthTB&9d(`$`%8KFU6>7p@Bga?EKrAlt z@kfv)`sMyOW}kS=;IEP@`s7%26c0YDVq6ie{%&F5evm5l!{g{TGZ|)tQ_Y#H5~@`dw<3;KtL-gpHetqA5hk2vOe!P znw9)?h(MnfR{SCa}r-BX(Qpfa>YrOK@sKQ0My$C$pn;4n{Zu;hhZCG-y6 zf3ml%@Q0h<(_8(KsnS)VQ$D(HP>V1oHMpa0pkmN7h=Sa$B?MObh6_{0sQ&6FM>JD@ zb(yEUU)2pw3+4vv9XH#2##`gbx>b6xx7GHEhQGej}Faey6W{3MU73CiDJDkkHATLoMjxS;BasVy-9 z3J-xKks8omIXjOfx(8~T<7eDtyy&VO#pSO*w=byqE*64?y0-YJF!dC?&EMo){Tm>G zaAqo#c8&mSj{EqgmiqZCZLoJ~EG8bRiVS=4-qoQ#%qoz-+=fM*!|2t#V=qaa?}>Te zY@L7b06?=n+BSmqKb-6Wwlar`*BxG*sMJSPeh$B`rjex)8q@lZ(VLqb2YuQ9@Hk~Y z#D5twaEHEZ`&9uz71*3B*`OueRoCMq3x1>5V5PuM6{La&M)}0P#0wn;TrJG$&G)HH z9#rF83ZWB7Oe#{kb5ru{Wq`)-m=09%gHyrDURz~q@5xff0OjZWfGQ6O{G~<8mQvdF7*{>putI-ixmkHVKY8I#EIbV04?{w4F05TqotUXc^o1uzw*J< zk&v;zyR+;MseGA(@0Tej-lgCYdL46PZ^x!LpR6d)8Tj!T zx^rX<&FnCayZ z=A5xGKjc(K&Z0oU(nmHWk~e?hWj}*e?ar!4I!UcW;v7_q{vIHy@Ec8ko5+k{DFRM4 z!9uj$woW7~U^CLRB(+t|d29rR>GB9Q0n|86X}ZvgaFA9>3(n1VBG6rfC$c)^6uD(B z)iu@MypU6R3!!Oh$L*Vy4Q8rhLEUMojC9wXhP1TD5wm~CR_i%|0MPM`F5XZ7>-=~>tA`m)Fi&4Lbw|;aF8;Zv zv5kOi*$Gqs0&q7Pkuv0$649zabn=Q%4v|wkkb{FJdXu=Ks_m75Kg z$IKtLn)sC{^s?%f%Q;BcW8$GwVHL%AME?koCg)TVSndxn-HNA|znF*Z!jVp%5$x?Z zBN?ZdMgZY08kn@fj+h6>^U!K~eHMTOM(1ZzJsitn9`>Y);bl+dY_w8@V?Kja2`!wUB!0KIs_;qAMU5gp9q$YT1fVzrfkvrWReltNxC$Wph~f5vC0{W1=W8_ zaQ>-9(H>Wz##)ca8E62>Ob`1i+Upeeix@uHYG>GA!T*18bpYWgl6}~P;mW}l$S|wl zhK)WX6X8JKsVb9IkVKP{2kAMOJ%q@;p#&m9L_A*W96#VVNF)2cjw<(5FhxAn_Hkdw zYXT1@jB{C2dIPk72ts^aOAg}6@v&E4{PJPy&72;!CylvCv?{1wfolkyr9B^oVbt+2 zD%*>|&o8TO1Ar<10rise9sh4g%xwc&Ze(*7%q@GGSQXW$f&?{oDbnc}`z{WovDU zxy#FkN;`yYoe%4MUl|PYox?HZFP1J`PP31cO^tV1TKDxkg?YbiHu5<;JZM2;$MVNX z!3!($)7*A3DklBoC{fUyd4Gg2vPW6|l{j|U?e^}->n33KJSpcR>@2$`_^N|Kta_h; z_>qhHlu`hm%m+3hPd{2o*3=U+amhj9PlZIdOAC{jF7i@rIyW@gQ1X|?7Fst%?S#JL zaqqQ40#PXt!D5)SxT-QE;@XKGYK_J(_AnQ(<94LxDt_|Yp|WAO3~&q384%t6HJ+QC z%5vy@EcFY=Dg>fMcVi`SAxYsf;iM}djfkoJ zBkFtP0sbyHEBuKMiu-VdHNq*L!Fh>bcnZu41#UqgQUp=Axso%j8W*1yhTgAZ6j_n^q4&O6wWudwF385xhh2>f%l7juVw;lw#TnXmcqYnk2e7#n49vz2| z{B!JA1J;<;71>Yz4sLT80b`6A9pcWi2K`j!$w<=5G+6rzSmwj#*-)QI3)*)64URc0 z-JRITUqNiJ^?_34fb5Hh(*030f7XVBOXJPj`1V}RnSCx;AKc8b%8~y)oh=Y)6*ju5Z) zBTSe+A9uhhD^NOp#I@MZoG5A6iBDu2sVygfU2Q551nPke}y9;!Y@lX00d zIn;%GAjU{!3aT0)UhitZiA^X(TJMf{kBAxK<&mj6Z6}bG?BMSS;Aq!WuO2RLnM7>%ehkZhp1Qwi}td|$!crs6Lt~JZ_0}bzRf;fOkfWA zghXN{9G)~4uGZgTn7C11)U=RNWNCvgf;-D6g8~@#q#jrnh>ew?s$nYI>$}sT%4XwNtC<@5r0c$o|Kec<2oB=tCm#u!?#z=j`0j zaba~qg8p8nK;{?^wHeWXtfS`{yt+OySKBJM8Cm7eTWyTJ^JwBK zxp43&B~)ldrrLC$c@fXI7g+^fCQcIVrk%s4Z&g$JNkahFuO=)Lbbo@?b$1?Hyb%p7 zVUhcvHM8(5qx8~TuVQoJnakzEZ2pekG$zVKj)pK|!bT?QSlKh+s*}SK7csW4gD!vI zW3fTiY}sQIqDP)eF~lU;d9e!64Z|ht&Iukbvh&JbjJZ+|okmq^ql-UH_DT&aFx4b_PM}K-qv>Z8#0twh z!-Y*6^QF4U!Ib?6&JilmyF4?9r7ZSN`irHcysa|r?Iru@v-d~k=0xgJ+ZvQcV zBZdXdM)Vbji*BC&k0{YTbS}fv``}I8HU!ztXAS0SXTIgIJc9pZ1}V^Vxh9G*$AjpG zQH%vcsA`&a5H@tgjzWhU<$?@fPIY{n#RZ97%L%(4tR*klCKdY0$S*n&+O)6KBoi_V zaTVtKt%00-ZkHIqPTD~SS5~NQnG#3qkdks{EvL!bMcf*{UxTb(4eKtw&r8W`HHc-3 zbKHgCVHz?-^aKKq$TUv;q9xd=8O&dr#*TdroX;}mUyJIx0A*d=$NL0R8WY!b$NuGX z1lc+rv&x$w3r)~fc7hO~^-FTvT~$;n4Y+zhJ~17ItWZ^$#4ob^NwWcRlb}bv_-5ZiTtuy zZ&Ii!V*x{C1He(BG-0ETkdE$8WuI1WF zD}50P@KsHRM#Yc6P^pICDq0%Xy|@p~f(PtEZ8US?#+sh#zljKWZHLr|^T&<^p`5mG z*~^Uke{=rpuBc{cXBp=11qmXFNn8Ob8?)v#!h$i{-HJ6B_sB;|aW*WgGE6h?j&HDi zAikP(mXLZ;!=l_!%d2nzn2i0S__aE(USuLipkBJxB>aJS2_Qn<29~Vu*rjjTQS0kcHpU0+qfg|5~-MnU(Uvh#;!&*n0T^dhowEORT6U(r z?2|}Hq(i#hR}IiQe4sjAVJfK0JH?;3^RzkG#eRlfvMCp+wWyTB-IxOW5LeL}BrxDf zn~B-#$#JM)o)2K?0rJ~x12UdScjSIzFRYQ5G$w&O^_ z3zcWrc-eBYf7H{iA-bM)9*1#mW7Bj{lNLsSIl<8N!KXU1gtL_u_ebnY4o2rMl&P zK7=~%d%?@XjkubLcz*}Ck&>mMOlhb7j<&RqW;$yCxvD&UG_!Gt2J9eUK4s9}ODOWW zoe&OMV=m!)P#E&v+FiU!6oHY21-ht?zx9nhodA=Ib{EvLtKbmKUtIz9YPY=|;gh#h zrJ8%iio{{Niole*w?0<~W(!=0JL~GE;RGD$KM{GJMpkrYV&idMPqAhKUNX|IN3wx| zQchFezjh(+4jj|1zPt2_UbICcnJyky0yYQu!WtiBEcoxhVWNIoSSg#%>r4|ntb@TI zkvliJ?CKkveYhJqW4L<*T+^Ts%h?$qL#4aWs-Y;Qd15lA5UoZMDy{o*kK0;@P#*?RZ&LMt{zesgbW zq!)MU^cJs3im|LOX;0MjIr$qVRyM(f2>IFkkQ}5cmtF0+F=ttp5d2TyU>)85yzx~S z2*@Slm85`z*$-4m0=;S3NWcBEi-Mw??9k50VqJ)4V%d1q!{nvBFvoC;V(JTP?8J{= zjJ|`HfY}tp8ic>D4kYl3I!a6dr znX8$;&KvRIZyzOpQkio-_ODF(ae+I_HtTkOJz3XX9XttP`3p`E>HFuY487PfGhLzI z;tGCLEnJO*iwuuwK@O^_aL>dYmlOf}O)3kADGR;jwn8qfbjs~;OB$89<-qKrxtPaDHVfYiAl61@phk2)>9%4 zF31rU+tDsc@m`S)W+ftZ`}BGss}j{(iAu(a=o5%|3H&01Z51V${hQYvv4PtA=0ilK zIU&`D=friOl}Pe|aTT)wK*&9hiw=~|YjDg^$@N2Ykaift*O~s~+4Mx~rkd|OUiUm^6kT>@*h;Y#*oK*kJZAtNw(DC8nR1%$ z84RmEG8Q(EjrY#)37Q2xCVkEY&Zagat~73Aa4c+Ej;!c4m`GJLBaTGlvkiz_|9WOv z+*?5;FuiLZ40$*kIU|YUG}VX`4{Z^uiFVyJHjyzA7(@H>1^-tpQq++}NJJ6=!Nf1^ zZ%*>Jexnw#SohM3ikFNcK^V!@7bTXjdqaefES@|YMM$sHBM-iFoycTYqT-UiPiDag zbKZyh)ilhKsiC@IMQs~TS?ex~aXu4|pv!2g zE$3pyLYruMPzS)qfW4jcH0`_p4$xYm&pD^wjwhb?RPU=TPmJ^kz|N(t|7g&v;jdgW z<@f~(_J;b3S^M=Om!kyRTK*O_Uu_XI18S89kgB^wOVUX2D1YGLSEr1Q5QGROSE}OT z4rdVmaFY%HgAZla9xqWG*%kKwSi}kr*mW<(tbv%LQ;{Nq`~kn>jRvesxfGDv@mDOE z7)i=;Lv5#9j9H!o`!qJ!r{bU!4-vLrl z7($`VY0w-H&ZXc9Frre{)Kc|DyGrl>0fa7SL>nX3$)c) z>L*n?zqx`13PMI5Csy^_PpdjmF%m|53S@vP=05@if2`!(z5@WE5&CC;{J~iqCPpn0 zq|Dnr+QMMQPMffA2jGH0+3K9XqYD}-6Hd@Z*n<44da{J^xu!a}rtTmcn3}TqIrgWG0^gQC`ywHcL`r^cHCh>W-ZP|zYdp;Si zBR<^)pX-TB6A2LrQ;pIx8k(Pa;DmLAe@M2>g)Q8+)%Dz0=)QVcMNtaQI?Qs!>9W*~ zoT|eEWy`hw6yV_X7`9h|iG6^v+OyJDXZkX&t+JwL78Ov^)A*90nG?U> zGTUo?WoXO|nUE>h;~xr}bD&}rlLg$!Id7b960`U;Q-1J4E9OW9E58DV0DzB`a4jGzu9v@lT|DxK)fBO)pt`w5=euG zhrFysCYv}{&npe1v#zyKq*VxBgV0(pY1PG?^A&gV2DeN3B|j|W1)>A27bJ*y@8M1E zS-Unr`*s`7UNXOZcS4H_;H1T@E=&9LN<}u!32x>>{Z?Hssx7ajw=9JbisP#}y9Ap6 z1b~l@$%7?ZnSUqF3p6i}(r!;6``(!OGSjeew1~36sY26<`&>}TH=B=&=hm$#)gKor zK1E;1MZ1FxybM{AFBrJRS7rbDs1gT`Qb$L`;MlflWuIf2J;liM&OBizr-QA`0XA|g71bH=n94>7cByKWWrbBoizfJ{D6hzXO zeotD*53Zq$(*rI%4TUJ9>jFU%I(b=6L-OmZ%~sk?WrM#?gwqH;4owe}QId9PK)-o3 zm3rv`nkGb1t@#~O?Q#WHd^0>>!s+xsk?84$O~hC=rei9LB67zRMQYLTD{b;iMSw^c zTPaaklb-1#P4Y^zBk*lpBtbXr772fh~R;fi~O~2tO z&m+INZ^b*LXiZEH2?+_A7yW*1JkZlD$G%2}7cn=b>}_n_^KxraynV90+#Ca5WV>CI zfQ9A3(GDXF0qj&pVG3bIA_AN0r6r@ATHc`=;#y0V$(AI#P{KRUeG+e3EGAooqj9{Z zaJWXAeDF?9hV@`C!25jORhAlr$s6i|vBgZic9YZXg*(wKccT~(LkLYkw-RCx4Za7) z#`z5GeeviPBhKchqVQLA`ZH%t?WV^e0`EHL$|H*Hde^wLKt*#>AZ9~&bNq9}(v+)l z9G!j1a*-L?aNZ;azl3n6y3N5{reHfwitU{~QD`=NwpSg4?!HMxz}Qkk@+rI?DOIna zLj4DCW99*2h!!&ie!iNg_i7iwxA*v-lc8!+J@39tQp$@yP}rzDDYXRsxb%2~n3>^@ z{N#5VFAPZ}8LX=~cMt`i%8ZyB>3O(K(I|Wngbgp}77P7DOt>U7w_CPwYMvagaYa$ZuN8 zS>$$;w!^iIrm~mLofPXaGIp6Ke1=d<(~3otUT~YH1~4NmJCwDL&1$C!!BK@eS0}ax8b* z=Y}AfbDguM&*>Kd4sa93JP%I{T_fs41LE}E0dS9)iZ~5k*@6S$E-*AZ)XUrqtW#h7 za|d~*ql~v86wpAyhmOAYmd=o|p||eJiXa9dk4iU-0Yg#1v%8Mu`=Iidi9Vn%Jz-Jv zxVz4Y9wKhCHy!!Mi%*a9rY*Oyr#m*$-hVndgRkiM;$mY3B*8KxHGFb^YG%{>gVM6;+sQ{;`DM*n(-EH3LETGCS%(&6oA zJiB_A0THiT6ll!}x@!hiZy7CJ7E5U_p2e54xrnq+@gEu=omjo~Pmo2qj*Fn|;mQjLz@vH{ zYX#+i=?Y=hh9D}m!9-}S@FnWqtmuz$=0cz+(^wXpVDIgdl9+XNkLrokcpdw07h|G` zyOP(Rh&$rnl{{9Qy^)1ZM9dx9+H>_&%-EN$tzwoc(c2Xt>D{d?fRU`bkH^ z18JqffxO`OFrR7PWboBKH6sosOjUoKbXW9q>{r${>g?ID68X47aJ!L6u~>;tS3n%M z4{|#Hlu8&V?NSGwgM&3F9akWu$pG~T-zuX-J(ry3`R?bDN%#U28D>+7$5%@i7xTy~ zLO|a2KKCgU^+s<8#nM4+OxN!k^p70SZ?kQXwYr#rFUvcE{+J@vj)_<#-kAaZ(dvTn zPq0_~C2tuIO1o*8MDkFWK5+cC!ks+70K(?XPq`q^8&MyYnAi=KL9eB`hu8t7Et5Uj$^?HiHvODcOBi;5ve;c%#u68UDQJT=8z(GdYjZ!6V5fNyrTXWN**Ww$((_!<2MLtdJo*TJ-R5ZQUtb-4riWk;74{Rs@Q|P9~a^Gi^ zieq|0T#H~wVBO2dfMM{0_8X22aBT@4vbLVav8Me$18tS84j&K0P=?tv(_*+tv@Tw& zaLN3*w{xf`KScZ=@Pjj&?sQ2?J9jHD(R|vlTjy@X!QDyy#+fLqCl}C>W8Zd| z5>vMz`%@;wl8b^B3uyWctQf_5i`q&jMf}uwok(FiqU$th;U}fWpX3Z0wn{>twj5WH z^9&6F*!wY80mCd}hUI{-&eshOyaWsx;iTwOwvOvhTKq`;=R_tK`}D8b2VYL;V7?rs zK!Lvf`4?op)ArIv0b{a2OW>o^LmIKLXRx|%IjjD9Z~t7h=4>l`Ttm?!U`ru)0n5{S zSQ-xEja@SztZoNHLp2Ele?|@7e>RVZ;eza}Mzgzj5 zgVf%g5x$EciVkx$eLl0uU$*h7LD;lJ2(cr=8UfT3bHU;yoi_=T9^Ah#$Dlvt9K~C} zo`aH*5(|pZ4$|#MOLjW+XttjxNy>ncyFMOl7L{Oon2N|A4$k$tuhMi)TxkR}iBP># zyLmtR5}R%u2&3?P2}2i2+~Ztbk48@=nvr|Q4VQYUPW@};LR|z^ zSYm5aS=p5*w@hIVFJ9Eyh3gQke}}KBM)L;JwT7HW0honiy4xKc0QJetX>6RqTaYo}X`pZ`vR}~1({*l%;<@nv{2l2H2tz?#jq3X8R zvW8)O%TZ%_Mm;^Dxwv4j=+bQfQ$jkuK}}fc#ZKuTaqhT` zbsRNW%j>*VgT);x3$lu&doP!_fhwn0C}}#$Gydz$P!e$?KLTtM)c$9;r_k zJ6Pz~wFw;#cyFM;YU|=8tJ0wT`>7cafjj~rfd38u1KY!QWy&`9kX#b`B)9SJjOJv8 z+8$Gsm9bj+FT#7b{=G-dZrIl}^*svzYVr-lg&!f5L8hCdv{O)e^Z|b$I+o7DErax2 z&rGpAfKeR)U2&>usrj$IGBR;2gK;rpum2wwcI$L z#dPy=dOs6X_DQ2Y9c6X->`Da_=eGRh=jhcP^KrjknLV$W5T=5VrgP&&qvzdCFEbCQ z3V**6*zTsprob-C)U-w&`0WW|I}?oDST!ye9G-?uHgvG@tuY3lqv zJ_-hMlo37g5K6}89k`abQ3+>VGCDWJcKWHXT|xq&L*AQX3jWe;LYfyW1gRD~PEVA$ zbv=dDiTj+pS(RA6n6MO81m^>>$-;{py#FzyJh?P>_D6@bZoEkE4AcooPF>Tehh#uj zbXk(bfW^UR)W<9(OhAgXzoPDYAkxIz&=^~a38>KbEK3|ZD}iH>%4;DI-w1yRBgO}{ zT_r_v8mym_HdoT=)KsJtf{Y*XPd4-W&I6hRjsodH`tQdMyyy-{r`PlB1nZi*!kuQ9 zxkb5bW@5X>#L+!%T(>b^AsUPt9zTpCq!fy8jv_S8&8%)(K*M)5`#s~sO}A`dE(%!z zXCXB*=VW8(qkS2v?D=Z$TE~k5Kh4$E>FB^2Xhd`)AKP=N{+)K|sF0A3#vX!8F71C{m%m>v&*f zf8<9je0&u8s?n3?YTtIH99OMoRu^GPZr#CpBDO)M361j$9i#R%gp{<27+hdRdZXx49uc ziPA^*$2jGq6cCnu@(uIXwpC+q!inL>`PQB~jn;kNlNi+Eb8^_<9Du=m*cNxd5B;jH zHlVa~L*`(z0q$V`DNnax%CL{NxEFdyhss^ieF};~v-6|!x^LmsR0;Cb8C#_8cZuu@ z_p07wJh!#PW*@JghX2i*fNn+4^;C!jit#>x!0Py4WrEt zg>XEe(srwnP(Y6A$+hgrR4`UpiqwS0W_&3ceLo(xLXSMEIMS~)sac7W_{KoQz@c{| zo>s8o?Pg69K`ayG>+Nj%c5%84 zvIp?xL04t>iKw&kJgIbrlmPE8bxIAT?(ef{Cju=# z4|~y%QgTuhk1<%_;bv^FkUx54y&*eRwOwfs;kHzoZ2>4`6_q&P5x9HDWuNN@x0&KL z6a1v4(kqp~q!B+Zp2Dp@w&k`N@e&Aa29!n~4Tk0t41i74C=Du&9?K{E&%EwuMEtoq zS+=cWeIcyMO}10Ht5u=O)~!eu=_z+zx*u9uza)v(5`|w@$mZnzwnb{%W<1?nHUPa zR;7vIQR>o#76&tnOhpZt@O$dO(O@|bH7A&Tx(A^`-s;K;9)nc-*KCRrD{!uV{=A9? z+=Z%RljT9B@)Y|5Qeq2@jWK@^qIMK%O6RUFG2vz=F(B;}0lZHTqCxluOQqly`E)9d zwl!Z{Q`@Qf&;oV*>Ak>RqdDZ_Xf1CMO8W*<-s`uK0+5N^}<}0jt z-t5Rd2=nM+fraO>aPJy{EEgCdgM`&O2S!YcZFDgPGEb4si)>Z4RCZvghx=tYP6IQD z+eo&AnV##7x;=P-q4=DZePTbBAU99lby zBwbSg&0NPmPy%uI9+8D_}i)J0u99f0z*qknIqwSLCw=X6AJZr3DQ4~W0i6QhC+gXuluZW_K1%(4=R_#P!r zf*fI_S^^E}+(2zhU;%?Bsp|-pE6w?78bEBwDZcW4RCcLa(^A<>|J1VFlDv#dApM*& zLONon1o@YbCwB3qJJi_44o3kE7d|vT3izQ9T_x=rtS69JIjB5f`t&rksJD$edbO+x z;`sCAMo6Cblz?!m8otUYaU>-fgB%XHvb>1OUv}7JMZ)al0iAEY4$IHQKsYNV;HYzj zAHX(#Iucy8nx|cXXav}}nSCUm-n!}Lz0%VA3|qizsKuL;7A{ALx{>%B3qBz3hux$; zQ4#f0tokvA0Kc&UHt>QhqSYY*-$QwT2 z6>uvwwwc&NC0m`tinS}xW+YY(50{_hzTcR1m$1j;6AwDEW0oM-dK|U6Q<|ZS04sJ* zXM5vBB6rM8u&gJoSi0afGymW;UBna+MTASMKPR)Jl1F>}a-!$)kzo30Hc4zsZVp2a zo_`7(*FeRUiJO0Z0*5n`ln&GsICLe^R{_njSlR68mXJl`MIUbyLllwg6TPT%u?ptwl7?3a7 zzjyS6Qwb>mYT~xbu#z=!&9EDfLedSB%rl&}ieZmAZX|EM!X=QrR9TNHL{eWNFu}>G z;!o<9mkCEkBdm)}dx^`T!KM?sTmv<*bG!nyXFRNUUVHG-uGeLcDJ8P`fCPWkO*`qJ z^$0s}S9WVWAXZOsJ)uZsuHW%l267l}QepN5I8;Hrf7p;|#Ruk85@u>AbI$BS$YtH>ccD_-$si{;@jToMv6awNPP&&wjPd>o@- z$EyJ0VR^8!(g?bQD^;4WuyAJCRIfXNr*SC|!!4&6X-wSf7ViowIfUpGlWjoB)#zbi zARz*fICoD>1MnboeD-;f2+1t;Z8av1P(?y}gPIa)Fudmtv9mQ8+@-`J|L;rWmU!!raK3X2-|V5xU+av2)OJt*-#a} z&o^Hq9X7zMi&l95Y=^Ug5uoTQndQm=m&;~iiYw#*Rjzh_ygN}h@g<}tqvVx+chXCt z?$=$^K}|XvdNw9eQ;z-`Bun?|$E*$EakrCe@380vpgly{aIvAXIn~3DurRW*b?T5F zVX#^7#3Sgci=2$Y{k}V%UI<<31dE+B&LY?*Ss$OG;X_B0oOtYt!w)=*H-o&&x3=@t zY5fu>X_G|17^5T4KN#)=Gi$xnG1t8sE60a)JKBdw1(=9Z|LR819X?f%ko#aSI6iG> z1A1g+?FZIod+M#jqvN|d<7yOO3*&Q)k4s3-gT(=$c@cB4eS*hl!IWW9O z$*)W-DM@#gW4{BI>b`ev^JJAFp=dD*thdDmG1#}};uy*)pPM(G*J%l-=qcSU0K6xn zdoq9afCWwh!2!Uz9z!%{qMC(~&HKrjbH$kY_m?P~AeSRz3!mxy^5m27`OQgj^o$!i z97^Efz?2z%)kxG&;!DK(U-5H3J}A`pN297vt*rNi(mN-E?hhq$&61l;eygOy^x3I2 z1?$0{2Q-G2S64pLgEX{~5u=|;-5b5ectPo+XAi?s_zpT!?htl?`@RHyDIK$#-`eqw z3(Feh^W=OVxary&WFXU2kjw@k8V((PkO8PWd@^JXz0NhVeYyC)FbBuAXt`s^D;zA;j^8Eb=#`Ecu2}b}WJ>Dv z>sK5sTqvv9Kr&+U=>EONy#^AV`l}Z>!VdVeDemLxihV%f=o7*R+?d0@flh7YI5159 z-#lR(gS!-yV`PZ3ksO{RRj_OXYS0)4NdPI2C%tchdm1k5usZhyN|ILlkcQqNt3D3Yd*G@!fPc-} zNrG9Um!YEwU8Bpv3*?1GHI@#LP%N*3p^$JPga#=W;_Z&pbO|_u0;tP+TJ5fVw>=y{ zivY95DGajFhglHQYLI_SHm7ioUpx0Cz$6aRd4o~XzP?qv0|`}02+N4CWvT;>zeV}* zN@<~kn1e`sY{F zqu{I%XjFI^fuL0^eTHn|$xpf3-X;x6#<*2&*PkJxRHsu&Quz+0lcCCk5n!|qVB+=0 zPN9h$3f5LjQ$-!$gPL&uWWZMkRi5lrWDH-@o}yq0SBP!!icg}JXKjMTaqo#RZ7qeY z{oC?zV%eyT^PwDaD@$AQ^ZML@IBH_QvqE5Am z9kXuqpw+R|(p3TopH!Bp`<8-P8G?PxgE1o7?nROS;-GWBJL%@xSx^( z2bwLTt0oTN*%dZbB!DTAjyyFpu@!=I6J`Tc7f5gQO_v~Jz>__^pf3(8H)Zq!8T3Rh zm=N4q%92SVZCO9b!||-DTqjm2qfH7>qzn{n#@ik(6oOoh`B>i6GhxqML z&3Ig~BDBIHUB(z9B$=a~P5UW$-V`{geatcymF+||K?p4&lJR7C;VzG=3 zM7H02uOU1KEEaF1PvtG*HRsH)izcwml$8W(#nG2x*yihKvxN)Gc;i!}IgXe$CGE+5HCt|4gB+racIopH!#4Tx+cZSHm6isaT(QGpG!qgHUNrD6vme87N^O{+4;qgeC@F-&YfQ zIq6Ilzw6q70X!}Hz#$$A1WN039+9~COl|O<7fu4EhsL_QeA5RCW@LxjPMDtc1mtP( zSZc2zpDa2y{u$OvvD$1HELR2vYHz!d4>eT}fbYd^cgaq%Atp$l*NUYCE@J1QPl8w` z&oMW{cJ%qc@33%$=#_xi+lj^fhPZq5aqfP|T0>@P9)}daAUfUu6i#L04!C#UJwpF$ z*rHHE4h~_R__ycv#3PABNTIw|JXprPg^a(tAc@Br3%#}q@$*gwEsSYD*8v;~OoxD`S(j>+7x zRg6ypd-dWQT_}{@1^x})2dL)n$=NY{5RoS{v8Q<-*x339M-qiK{m^e%*y_RiQ+XtJ z%LcLlclb$sTKK$ZZAzA;*-ZhmBoA~d%mr?2KZDO>lgrcvK0!a4q>dokzxJXhqizxC z#<@(8B)tkP7kT81Ho8uCZ8oYE5cFIQn(C#!6W}QckK|9u7IO@ajxHrV;x|J3_~b`l z?1my)HL_s93B(*flVGGQHLCs8??^L9CUp{9;O?KQy|uzE=Aq4Y$v(gDRca;*T>>c; zHZ&|m4odN8g0u2f)X$(}!050e^su%c*48uKSl1KduOUjs~olxFuZ^A@eF^xVc z89`1g%f^Ah*oNd?BM1!NX;>n6OY`lyB$f4CZpp;Eel^aK5C8}VSgBVk^HV``D&)d^ z`q<_`csBDEY8zBEp<09bKGa*Ij}76H6(}}lGVoK|3#=eGi_!GOb;k~`YALP2dBx_yfCgd&kI#vKEg9#`36 z#s0y+Y%z%BD%jc`E8_`llsWK~>00-s4krA)ZYEfH45cu{{STTWo2Ru(Y*rf8guS8X zRhU*Ehg3=RW|1t-2dh3*3xJGNT6B?J1y)ZYj2}oN)XJ>03e~Na{#RVyUPai# z+Go6(t3&E*3hW`Qt}bwD^CO#)Dy$;=AX|?S?3gV|F+w`MtNGEyqyRTua3OC@e2cib zXE)7G4cWuDRo56NCp&7}OW3Lm5js4BL2hCE=Noyx{YeRO{`0PC&}BlRr`=>;thots z1U3jQFEXbzj-je?xLrz3CKD(w^uQao#!s#5J>v2ZJsF#+ zNH5@C=ZOH=vczL!@`-y|>xzYKHEAgDFbF~a)gO*iFw(#SRC-VEXF&;*pMj$R$EBq7 z?5?b&V7>auGId1tEi4NZSOG3tmA2qY7)hE3SNLk2x4gi7J_A)JgN7tDt?g9SPq-)&?bUe&V5jkWerlCt5>z9UmYlm*XL=1V6Ok8VkoZM@qtC zfE`~r>{x$1UG2}`l}6Vf-pf*PFFvXtb0&sI=LtFpdDGkg;e|bw&db|ECtNV*1-?J@Xp95wFmL9TxFa@8-?TU04P2M3iI8^s zGdMkjpg!To4%8nTIo9(5_JHgz_gkVKL68+Df44)3a~QYE3n$f$BkE8ds54wTNwQEsVxK?P(J%c{;YL@ZUxf zTV8E_FnEklV~Ye+G-ybm-sy1Yd!^SKG?DU}x)_~cit+-XjY=Pxs#YaPQ!1yR<}6|~BR-c4>3Wh@84~Y2 zL^0vv<^Z71%fQ<2EF2{T@vq%*{=k^?`9|fu;^V8@#jnCpoNz^aSVd?)Bu0QmIArd2 zracNumCfXb(regiwy zucBYUg(pue6ha)?*Cb%5=pz-si5Air_{%Br^?cZ>9wtlk$67Ra3sceo^8A1Ur z5I;6-zqX3vk>{x}PFz^R4NR;(D_p-A$ngn;cV6l*wP=#d)tdS|L&VrI?<@@q#vS$S zM1fXCX1t>T=FpKE#!0sq)XhZS2x!hno&F)~HQ1F}>f04q%#XSYJ+Tz! z3SC<+=GxsH1#O{qaZ5UZcr$OVV+3$0#kHCzqg0rR8C0G&++NX0mB+aM$N@7K(F2XQ znlS4lg6((x1~5#qZ`V$Qew+f^xxaem~A@VZ$vJs6JN!t4d2f3lj~kCw$q9J|E~jwSTLEbR_#FE?oQARt_y z#)eZ@d|joUelX6#){?BaBmJRkBD&{8jmdLEh(En2DonX-0JnYjG2;+OTlP1x%1yaK zSp!FJZJJo(wDcp?H4s5gcWo?QZTF@AFB)H17h@jFfM9VL_3;v$a2_K8&I4-7AU%D^ zW7we+5*D)7y~eV~D(4`l`;or;X6;)u0K??W8fp|tr19)^mmUXI^N|~pZkC?=x|`Oz zLceQ|52AmdH?;&mKg_{XQ<3H}8{B26_k@i9!tx0sL`p9# zfeTzrQd2zKIl(TDIX0sUT}G+pFE#6;nU2rxr~C7+qhDWr9h{|R-FX;8kGfO1NBU8E z6S`sQAioLu(3Ig$J%N~TY5hh*tA#KhmlW3tgyMiJ^Gz-5#Ymp0xQ5K)RulEqauW7(!$Sdch?nu0^?5etQ z-CgHNf5s?l3A(7$e1PImuuxxp$f=8mYuGilDd@e+j?yh7S?d(>m(T|9r{`C{$3om^lz%7CccWM zfVu>0qy!5cD?gM8qBVP8mQ8XTM+(oxcsx6vSWWrLG(PS;YVAxMn<$=@8)^eF{VS*E z$H)g3h^<{lYpwcF+aXznm7CKWrfO=q8ryQ=mq(gMyN)p?SF{zQ;q7Ow1f@&F;O<$! zVdB%+2;?YVyLOtapT?-sDBkjXu0R=NS5)oFlyY6laATb4&vgmJNhl_{@7jl}rM9v7 z|21RGVt_rWvZ)BHIn4KXu-H$a6H7`m5mx4}fPKb32d}ub{ogGFv{mK{Ro2e_@iAwd zzX^RlS+J@*XGkpcbxG#Uz4e+9M5eqL9$x$FR;44?+l3Z}MiQd~y`{7)iR)Sb8G_E- z4E8Xi2AY#XQ(<1*Ak$R=Y83F2LFY5;;TN z?hqG9QOslw&UxsorW2^b+R@1tf`C@A3SZ(~MVq}r9=#q7g=OEc27Mb)LvtWr7UEYJ zY9tPes-=f$dT9V*+jOVRw1d%Ie&nOOUoK6tz~&989D&W9S?_3pJ*!qDhWyu znIfZo=Dp&UO4v`@th#r?d_rjE4|mDrTLtduB|~vpqT!6${9T2tP$AD6YKuy@FjO@X zD;=8YQ3_YSaT^bjqHqQbkl9L_g!#}n?I%9)Whm)kHRp0Ev;nqIH5%<2m}jZZp5bi? z31&@0Rw%aG8~FnJIa0R!DSkVKEO>}oyIZFmHlo5y#q}hf8Th2Z;TP2%O!_kLm=Id( zLF=GB-pT`I{PpR--xd0Lg>y%ZOz`*u4}*CGfJEX2*U~f5 z^hsv-9*->a1N+xN-@8X%Px@wsc%Vy34vV=7(}_U=Amx9je?hUhfl|?_Zm(`cZlwIx zp?r{xWL%fUD<$k;HM^XxsZMm`B{T!r%EWexUiEUyBPF4QfdgTvO^%dE#*eaS^`e)B zj1&2XzJ%DN;-AI%-`e4cMdNU0s?Q#Q@a?aYhen;uP$zUi@@U7_gj0NJb(}_uwL(Je z>u5s9s)#~Uyw{-1+Gi3bF(;LdbBx}t3V{?%qUc7BL~{+q0^otOdo%HVnX_nLKhZ^d zOhuKKa!}WB0h}<_=wAn)?U(@7uEO)p-_^Iw3|U9JF%Q~E(ZOis$;keXov}A>K^bFB zb1p0n%|}PW?pW)+A%TFE>7DzbWn1dk9Cz-5Kwq|Kck$uOy+V$z1t&RfI;QYEt3@1U zh=OC{07$B|?T$fAMm&mcNSBr-F@2gNr@zJ)qSs->AggRqBPo<E+oiG!>Ps}yaS32pL&by&D!{;QS8g-`sjY;2=e$9?8I0YzkND8Y88?uD64iR3 zAEs~(pkgi-OkP|>&#xyZQ`I|?9urQaO|akLuD^Iuzmr!kNj%QJ&6jkE!GB2dq{`{D zaZpLa?mDOyB;spC!cR4bJ-^MI^qo0P!NBCf$Ihf-3X1>fP;yQ7mg0 z)3su9KxDr5j#NcR{Yx4aAV?))_{bIB8ae27KPy;^zQHs*9zPrTu&N)i6r!RoV5sPX z*GWe_*6!;|1LgQPv6!2sI{bPFB7ofNugZy;AJttO5SBA z+DL08!&N-(cBjA4JuPX;PW7$IIgq!K$E)5e2s+!mc~3wqDC4tBev+o@`VB)lvH*gI?!iMff#PVJJn z#nfEO{Ye?4uG5_RBN#zhu36!QRo4a!Vko<5xfg(d4P*|F=3;7-J5Anb?lj0j?3j*Q zPO_SHl&gQGv;19=d!1%eBKi}*ek3(!BoH&~l z#y>l;VdeJ!=sJs^NaUc;z~$*%(!j3)o+HbA;`ipg+H~#!_{Zj8 z5^Jtvpo7lPeVnmRE56aLT9bL|2|IN5KR(8sfRfT<=<_b#8wS_A^rCHxb?66($bAPpkULr!((mD z)+@88q+K7h|HBbaUfKN|=q4390)*>$+lWOh`9?3j+uNDzNJ8`0WgSiy7{3RmaxROW z+3jNWIEld746Wi4!((?ULk_7*`ZB@j8{&;=fSjs3dW1@E5!s6XIuP~l6t(PVWFZpC zI1{MiKFFMI*erMM)#d~+r=5!rac%KUGSK7qgOkM_ac4y~x|XIyt(!Zoom+kJ z1;+sVu-D-kJ!lzVtfGqZscQIu9Xajl3nFDMB>Nc9j$iWM*k@i=@bBmg2%VGM7F50| zsMQQ-QTIjg2~Lli-KFn#x@e@2rfZjQ8?SQMW)IW#5-a({LT{WtcT6js=p}rPDqNis zlW)uaSRI%%^cvmx(J1=Fw6q_B{tW>FqhLv1uZ}T!r{aq+&E%jTnE8SXF_;LA@duj* zR(yuHm=Eu;mFq?f;cBHE(p9eCX%CV48M;Qon;lp9y;OUbEHa$tMi|GdkB$Ba=1o&d zhGh8Zi1;$wk{w$h+Lazvmn_!t?{hbdhpRfA+2Vb1+~dkuFybq_^vH8yUyF@H1qL+) zS5g5z>LSJ+|7(zM`~Kr^k%lhXYbko6F7L#|TTw`FhnBGOXVIZC)31U1Ie>g}yHE|~ zR#k8X?;To;ODqI$wikDm!bp~0NxMx=L4tLFQwLYr~dF_*1Or_hG<~n-CefwV3fZ z3o=}+8^Il}1&@t05ax>7etE2#f|V=!YuhEqBp8I-@ncsxYhyLU_|tKW>?M)G_hI?l z3xd^k#U@QA@jChQQKbgcaaUob!mn>^Ok?kfTpCPQjyY+)?Z&#Vhi~E7=v@yDH2CBf z2#~nuo?L>?*5^Bz$;p(A(8d==XUl`*_GOf?u#2~H%T%hKF&<0TC6Is%0+%c7m8E^W z&cBb<)>zgAKLww8Qz&m6GhHX`5GzD<*TB_Hl&*?Up~}Y44g({ngNCS@u-X6x9?V6J z{qgF4oFDtu!6@B$4%^ZrR4OCgBayhoL0xim34Mb-nThBB7|c4g_I29)2h)rE7iZ!gu z=T<*^U1OJ)=&w>tMP-Q@ENP_Vxk>|rPylb=>Axri0S^6UP(D$CZQ2GI7t^!$93^`2 zvgX*OUN)*5bsqnI5HoIgl{}4v z`+u+=%94y~D`f!wWdU~F@N>ZbYuj!Tuh)W*6)Ap7tEu~KB>}ihXHU54)SJ5jo*j??>9vkz7r68uZZ|om`o(+IRl7i!MfSCaNrf%E{$j{gyZ_(pj6?OX(&ApzfCZfm9uU_9~u(d3;%(P zT>)8NHW+(WsgGB9`@XAQj^o00%(Zg8YH$i>v(!>P6T0j?nT89fZUB9w55m1zH=t1S z2QfZi8sHK4_mgl1gCII@f$~{6_VE&Wb&KfU?3koa=bygX?i<~`$eTX0LS|){KUa{I{tJXeydc%?%{Va5K?Tq)}L=+G1>*M7*T7_Ox(9dfmG5OO_z? zPOebNI_;7AgQx@%%oKbIie1uO+e97x8eWr}@jo<+Ze@}1p@It=o+wrW*X?%lv|oeZ zfPM(y!1=Q+!~f_6hPxWTvADJ+CIA*t&o1x9;AAO#vMT>)+g4;eYYKC9GkZ%Uhkf}} z0#Nbbb3+D@c!gmWb({V^yE6MP1xusFz!I%2?I}MtZ+BO+5oh`xgxN9AmQpu`x?nuDZ5AY%h+ZnDW8?Wt*EtrNt$@6FNAa;mbSMUrSb^U0AFV6&v3ye! zZN~k+AXo6Fw8B4!ePLp45)r8*Pr=jyH24FGQ_czZ4tJO&8=Bo8m`SP@aQZ71uiHfB zi&1Tv7~8N109Wg4A^WVxYKWaCzhT&NOh|9KV3iK28HSYPnb!h+^naQBdnj0PB+a3dC-&0vbSBkvt8$GxAaktTAsp}(D11# zz?lOysC-+XjcC;2MeIFQFn^g?f`>Mxaz$Hblcrb^(`)1!<4iKwAN?<7-UUndFl`@~ z?59r6n{r*0Nexk9eGBhNw!6vppzihY0Hg*rt28i{qjhjW@$DR}$4n{ei&9!aC&NuA zB`mG`qj3j3YrCh>`5;b^!F??611d*x;OIbwqd&Jx< zdgx=-nSzsh^4-i%zvo^~aukl~VO)K99>(H>Q9viNo1tH~%7s4a3{b+?l2C--$r?Kc z^$VytTmREu?KuVC(L{GH4e0tzo9S9Ed(WX#>z1zJs1sKf4ok)JUs_fcly0-%5PxybmXsl9VA2|9A%*3%Njws@Ee?u zKkze93Y1}_8_LPf?wsaB(2l#dQ6>`u3OtZ*o%$d~m#{iGU(>C-dJECMQ8HBTnA8;f z-n0!K2v-FNJlrRABwBMs&GabsM;H3sMQR$r2esg8IZcbM60Yk@RJ;^0FkuJh(n4W6 z`f3;n83#9IH>a3FyK(3S?O;tv9K>d5v~C3lYf`JqcqcCNbtQ+Jv?6In$hI z>52E;Y@rIv#`tVhMwbrR{v&{&@mKs)kTA*eyx4fkl z1v}XQs0Gd(@?&3(fkXo17; zRY!Ec$FD&|6K}(B$e2f#z_So@9)Zf_QOPSrMb8}&DZWipcYAzN;r7WwWqqH)NRI95 zR9C44p`Dfw&2JZz@|{f#Qa=5{HBZ3acFVDN=j7@KESDfx?6ts^%w@1oV;xYoobO0g z`yDqE!ZLe&RaD<)`%&Fl=wo0-C{p)cpKz-A&f8_21V`lsk$I3bdLALeYFX#@sQ>!L zYyh9v1Xp^a09PF6^>U%Qd;V=-99OnUhL%n|~{Re~3EyY4b`#M~aEHxT|~-@H)GQ5}(gGeB`?T5MaM%ZGl#UFXFNAav8S_pK~WRaUY1p3mhA_ z=$MrwnT~GBiiKUa^+yQ@2?nvY5=Aqj;??I5Hkwi7{$HNUaXA%8xx~1jlH5(No>G_-kza9ejGW*=IrklPKF&Wb*+l$UkHp7~)sx|hE?e$x zqw}NMuw&PAzK}G8%L() zSeiqOSFPZ3^eY0G54Nc10gS}C9aE2oADRmm-+U$|%%OIhe1!#J+*Wsru&ED1Sk}cI z68G=J`{_lMdgc5RvgtYIv1DvQX;s(5Phm*~7Sfk)27Fo&EQzg4|9-tVdJ{LazGoiG zU$fHyR^|!se)ZpdVqOL}oXIMG5PhUtZQ_TThe2NS$~|e8H^&aBhzo?qOuX3SYdv1q zb(nJC<9QODL;{H7{UAE4fN<;0c+?sGL$2G-6?u$vLu~R*3w~3hOXzud_0hkUPwXpd zJl6Y3qWV*b32KpxJ5ZA%E(>(PsLX?D%d$cTP&nBkzu*bGBcWdcPQYL^11NVtfRMcw zMybhoa*d0q5RrR^Yn&b)SLy(G?I<$PErL|>0e3bt5tq&3Ik#5;QhZ`Pa>nj_!d{1F-dAo$=W-j zq#+!$35pq*>oS~vUzwpva}W-mhq?lF?)B9HokeQwuQuD#z z+4UODC&ghUj4s)B3Tmoa2qS6Dnv6Sung~&9Bm-De?VEF22oZz4 z7y6#oaJHmKi`Y+qU} zX5Z=8&~M^=K?KACAAZ~0Iy0`yLaTLIykNGAp}+w~X-ViA#HYP+>U(J<|92S@{`!RN zPC>h;bUy7^`!n{kWUt108WH6Zql|O1iJ8|c)I0huLB7yofyv_700d8~|8IV=u?Agv z_?z;eMUyU7Hzwj5u1)l;S0|Igj8HR}G!UE^8>M*FnET_-GOL?<3w!2 zfW7GYKu|!ROw5snI}N|bax4c_61p80kfZI+PX=tPrXhA-%i~GgLre&nI`f;_=u(#X zI!}XsjLVh$bM3~Hw}XXnRrD|%tJF^G$9m0DG%zu&c-#h4k{ulWtNU6ykBkrxc5tyJ z{t=PEG1X{sAk%jOy_rqv1M)C8FaT?vV3JwEU%WtrV*%H!8VhkcuRJEQXov<`F-7wn zd-QuZ@YFgp#&rp!m3L6+_~_60hU0(3<|npS&B&!9dmkWleH|I`pseTttp9MNY1a zi~vnQvcJQs-^A(kbMxWs0QU8ko0|c%fC~$71+OFph1mToVGLA8_JQQGEh1q_Coup} z%*NJ$e-*5G3PCp&NtmL~8^>7ZiE8dq(h#BKy_%0CA;Xq;FRE;iLogE#ZWtl4I(%_k)0jfp0LH&xq$dIz^IGys~|kV>11k`@9$+ z^@N`tj+qGnrE3`f2JQ1`WXW2r4N4X`aD>G_vaVEqp*D1_*~?VG5N8)Fw|Mg?UVSBW z3j_K*#?=-}Yb%c_7)zD0*wq%e1PSUpBYh{s8e#1WzaOTbxP^NKjz*ybSB^^^BtwPvM>KLM_1z>a3NSLit&E6%(RbC)Pz zlT2kSBKr!=7I{8G?rdgQnWqp;o2%ZB5;nXBYHQn&s%TA!!ke761StI z&sY@1Pj(&#ZjVi;9}`gn5xxO=xi&yQbd=J3*i%&+b$QaBPzWN638=aW5fLI)NVt*e z{MS!HT#5!W9{F6}r>6U4q1On=PUHyzb|8~1;<+@G0i2+e23pyA#}@R&OrD*LQg5(b z#aL#lnno3}&Pyj|a+N?YP}8$Ld<&+3tg%W2&T?(1VP%4J*kmI0PkOeYp&wE%Nj=~M z>78ZA`nUMeM;s6sBro$UIv1Q6h$`a#bTDrZrAL#-_J=xBMtXm&DO$pQ>$tf=NkHLm zW6~BZo`}(nclxxo9JdgV=59JQ=huXS%I!E~zH}^}_C-w&9k`SL2@?KTLU^dheXC<1>!cfxCE&8wwE}G7U#ob61@n9`8!Klvov)2z)3pQou z53brg2uJ=E?xZZbJk_|W-M-e~^pz4>ZiL@Q>(1kuYAT$-)OIu_QN>fEvmva~G5-BL zLd2XYLY)&C29S_I)sY%qe;onABv;tEcR4?9Bc>qmE*<)WP&NFUIpUxLnk(+?ZAvGC1zW={yU(>WJ6vJc5lLquqJ# zbZC3mjztW76-cHZkyZWGrHhA#7f%$QC!aPsZyILbr@Ka^TnCXr|yH}kXlH!A`T(d z32^kOb-oCD{=Cr~dI3l=%VBKsL^bskAO3E9xdMFCmazdjV#qrsH=50=YE>x30Lw=4 zf!+8H)$xl9eiaR>^tvt9{_P3SPdy~IHuu%WeFItf07VAzV+tXICZoXLZ=nPCTD{K$@jAA7*0FSK;U!r2&XdJ&%eWd z<0@x3g%psj5*&i z;U12;RX=fysU|VNaK2|sJIIF9zyH{fTyi3r}S?(P^Pu6b{hi&q|gc%n^ zlA?egbVE~qbG2%@O3f<*vE2?gG(!PL)K{{i_A5s;&=b`uC!?}3R`U7UR+l*l1FaWC z^l($j5k0&q%{-M!7@Tg39s}rT{ z%}2d;B+JSdV}VPeyo|QxT%!KyYa6A#t+M8TWwmB>VT#qB9C~i#zH!N0{ZuyigdANA zS9;qVF*?N^ABjknBtY4asE1g;w~hpZ`chAZ+9n>SFf;FqpX{x3ggET_l~U}3+9h>VWinPupW=|U;>jn_U^K21@Mfo7E& zP0^eA(lO{-$DB}5F@%Avq7;InYP=fu36seIf041>ubl$}Pa<0@qwDC~5_F(|11n5_ zZ%&){zn&yByyjj($H@kg-}>-8*|`nwXEOn}jS--u;^AtMb^H(`f>YulfV1NVI@*Wa zv*(>XYAH}TN%S1}-qr>f+zR#DS$RNsxr&z3h2;Q=vh!r0bqFPyK1;qG z_QvIeBqj@ptHWU{B4HEXpY)hayk3xIwYamX7^K8@Pw4eGDJ(n%=)Zl%YVB;+3+h~a z%qt4yVWmLDBc)n_d_kA;d7R{r;%B1acXNVveX$oFO^KK?QYc@Qnrj?`u2*B?xWRE!-MYv ztNDk#hTCF}q5}WyWeFyg?RM;#=4hwerE2T_8d**DeI9eko#}emo*63f&JOYBf6NvF zm7Pi4{od9sF{_lb8Ntpja27g{UP=tDB4JM*(c5$|Za2x$1{5HhTV|DoF2>8e#FL=g zX%oq$wn8_FV=2IEoIHz!2cbm|!udk7Bus5$Mn-;uU z5$uvv)aJE1;07r;oS~@=rf^Bi6{VV)DTCF#acRN!+kamI7p2^SF?$4E+$-Lg(^?ah z^sl?&6ZvqNQB8aWcs!zqnL)nN+-#_@b7ybGWN< zzn#dSk~T9wBPH%Em+>!@W4I09IIy{j1DrAqRAo_Ct-%Z%Q3cw_-ee?ZDq8rQjIt`l zVUYewWu_f^enY0-eU$Ft9p;DV(QK~Q+=~AgCb0V}S7!(V_Mj^#ct3A2^s&xggahFH zKd#XBEoXbEknDtw&;59cFe>)MGp2O+z!FtzQZTmZc>ezn%)Kh@^bt3Z6xI_cFHlX* z@;6^;OHDE^*MHc2;=Ln>%ifpz+3R+%Y)6Vqz_)AGYnrvf@+c|lE}_Zll28FOrnmCc zL!G|Qb0TqO5!#=F2Ok%V}exaf7P?$A)Y}mAGhy$#C&?QOOgUI$*UqY3k$Ec;}o;W(s zZv%}Sv#a+}fvby{*S89<Zoe@X+Ylg={7ISLw*)%4dR%UJ5kB~9g$p**YA}rjpZB0ZMm<>Zqk-&3euqZ zfa8SJ&5KDBO=0i$ZL{6NkLPvZkDW37DbcX6&YiZD--IPR_q*wJfi5A~;>G-eWi9i8jwVrec&q{n=!Cr~LtUngz zQk1mB-QxwGGEhvCj}H0_1%L?P8aQS-ma$N_u4+Aia^SQ$sfkY|gX{GwR-~83E3q1} zvjWOBW0}8Aa|jPS<#){@15In}t2DWQ{#l($6&vT|k#oH><}_%}Ca82+;jL%K-iU?L z_AfS9yWGb4Id+B4cl1$v#q^;Tv)Pgs^{3n*_0**VTZ+>Vq}MZLK)(yBc$Fm&tuYX$ zgC(Y9A(ix8iPXjA#hWs}o`oW!E94Q$&K;0+XugXG3JW&Ia(1YkeaP4|FbKDJiI)dj zE*4(i1!De|NL**eAGtRU9PNwV=^+D&ZxGX zD5=%=&o0znvMabtSihXN_4(#Vm5QFp8UaQ@8&NC=<^zfupDF z4O14Mmy6ItHQspy_pDmhQHoWMsC>MBtRHHMFP)`@j@I$Tl8*N8)SlAGU4RU#!eFvXjVjo{{1ZW^FrUrr zH&QqQc;m6j_YWSX(o71ugD6#8gs;b%dUFlpFK%arWZ+As@d*>yrX+_U>VN=E95*gs_YstT3Qn|rwA!qL<{ zlWgUXvo3>MZ=b{ggt{(z4dmv+;qk4fv6GE`)D9nhVr-?opP2teoJ_D0&MBiQ%qGIJ z^&Qtn5F1;&SEl}YK1p+6QIHV(CXtlZPvrud*xuBE4^YKN6FzXa?x?>xi6ZkRU2t@r zF9i#P1rD?v zJ-FS&Yl~*n{Ux2`qaY9AXUBiY1T?I5a+>~tN~HNFC#RBFlTdt%p@6X-2fe~{Ktl9W$#?v+6XYI^xwRG zd>5JZ`#dG0aRE$>NV-HWy>Pe*EpZJlAY8{(IwXk`WySBRXSUIY;f8FxG$ zdl~wPKu$zt-*Pug=wK3C2o=6_l+y)B1Y@0P%yko=6=6La2^s*%!kV;1;8N#;OZ3Ntte6z4oRl_=hr)OM4W?CJZxf@hzWcp<50RZ${ zQ{wAqy$CV2u$l~v`1;>KGZWI2=4Yo?2)e5+Z<)A*2^Bu~VLcqqF^syMXxMZ2-_N+o zbRIHW$Bjli$V(_f70e;_jWj=nLR+KqPbQA&3+kzV3u}#%m#1fPAM{$d=v*oRNq9(y z`Mdsh0Mt{P#=Hk@^HGK^7+tj98q^JLK`Uqqi2fO)seK!$Ln@=;0u(fSVAwy}Bx zhN+`TMtY_eHHL>@K8rX}&^9|p<>=_0`^=|{9r29iM;u$&I-Iu)2!Rb_&{knyZ=J?b zByo2TdsCzp0&y)uAy$IEUdY>+`zqvSh#g^MXfD3hr1&A~ZhB+6=r)@k#=EQZ!**#Z z8N4D^EV^4I+j?j8l7N5dv>MnC%EGLS;WSrW_J|xx9Q_u1Fy^?S05(ObSsN+OX`gn)J)HzFg| zEWA<#X7zm@s{OW_f!~P);)h)i%?NXG%rG8ZmpE3Kc}HDb63w!RxlMrb8gyy@eLbLaw z2GM4*F@W?$T z;lu=%^>`eUg9pjee8iz&y^UG-78rQllyo~3g`R77vFVWp)sR(qqSbrfdxSiuag`Ij zOM$5_XNqZ_{_t4;;auPs-o2BJJ}T;zApVcFxDruQwvF|&lW~jkjMq}zPZZ3CyK}`% zgYY!O5#+zYT93i6#V`GyBLA^KA=I%O7`oChJHg#Ag>|)Gh%}F9-o`X)p@zn&&{$XxuQQd#nx~Wk}X}*tqIUwwog#Kl0o`)p-%9DVEVIS~2 zKyus$*aq4HD9vl(R}k!gNH#~7SR*W9L4p&<&WLDOAzb)coCFy=J+c~F$!C_3hDlI@ zj*z+M!61v`KA4}XHGRg;#0cOfZI?b>pkc=9A)dLd0zv^BTF<(k6-t3^X~!@IUB+*# z@)ci`+dt*_*Btbx3(0t;*+d;2e@6JmilPL!?iBofg}=t(Ng_0|b|mHJa8kmoJm`6Z zu*G$?(T9?6{MPq*f>E?cpJ>4~aiZ}~+ndAQ3>WZ?^nkk+SjrnEn!B!t`6xpXCW~97 zDi}9Pm}cE?B}q?a9Xmj0xdmw6XjP+THp3DydM9g?;;XF{nN9;6v3=Mt9a3+wL!mq~ z$7u*l&Cy+8Jb9(J&NERZX`a}?FhMAHD7eOz$LEgrs%GpSKGU-EcN5ynOcD{RjX!&OBdKpmn|`<~FrXtvr8T_W|L&^p^aFWz=aL?YDXsjY6U8<@8`Xb>L{ zFQn_S_GS?j@X^Ml;4N(_nHC?147+a(UL^6J4auY*!l;q&`Khes;vY;4xXNF?C0~Qv z{Ojh*M%CY6;AdG~uwu)sr*EBNJav_mW2=ozVDPO9evF|H%&|_;{p64%=$xUZHUD z+;p<&=+&;ghM)zTWU9Kna|6H@hvO^946R5r@Y;C=r9P$;$>U%j zyEIOc%Zp6sLJ9V7U31m`jq^o3v==wSx^;!u5?^LAlPXDt9oyB zw8g_aWeyt=LM*SbPS4cE-MHpQv>}`FnV_6U)%XusISfNfUTdvjGukgZEt=@Q%Fh8Y z#6Ja-0VM{8rL)HzYD0AiA~a~X0tW!ibr1GjY7BLsiB@rSMq?dkRVo3SwEdr)`gCs+ zR4>&@@@(Kg(B0wBgqPlwuNkllD0r?-cJA$kV>0m*-nEnC;B~=?Y0BRLkV03(vHVXN zmao-Q0sLneNlA0QsbMYD8K{_2YQ!v|g4+{#U7SO~s7trsM%1A1b<4k+q11>Ak-mW`#%naB;+Z3 ztpU@-YxPS?Lm?8F)kKzjDvCO4T$y%s4{WdTn#}KETvzBbm_8VAcdXOe*wKhzvq|-2)3Q**gm}x4rF*%W`4WaBM-J}8@@V(4 z_q}YCy;FCQ1y#rPk^9YtsiY!knf-z{QukB3vK`a>#`l&?$KFGHU0uHUs_K+%*A~3UWe&6<`w?#C(qI8I|kfbv_|L=8G;DE4Eo~;>eguLpDWP>OmBo z90`M^WL);XYWNRkHYmbBZGavT!AMl91GJFH`UOB#VTjd%ly4Ikbw@pyIXBi( z27^pEVzHESVRiU*SFHWO`ocd&t7{)S^iokrUqu zJZQAqdfG&6Ze(YKM<7gpxO$m_rCL{(rO4laSpu#TCHZ`mXyCC0p^uOv@CNpR5vIfB zGiBbi*BQu5$g5d)CCB&o4P~YSR8kszz_leBIo1-ALUYA7YSPGU)Tz zRQLF24#{#Cwxhs>lCg<(9wYX+4DVH;`)a$QmjLXgMhym(7r8zDxO$^04MyFdON8#9 zzVy_q1Bu6@n|TR{7VfDsm4|2i@`kX90GgqC>YDBr#_m2{Z18&ZFhvx`**{Lr&Bo4l z&`sB{awNdYzjo&i=9Z+~z39AbB0#?(wwcH7&%7mrAMTkco*^Egrg>Jp|3kHOrQETq z4jxiS&CEz!NVGIuxKWaU8I6FP+F7-Cd2k?-d5G$H)2W_*G|p2jpN>@aNL%A3&{W5< zEp3l=r8Iw~GzYWW!lQE@OxjF!q@FPAFo2To4!c-8{&L_#&6WXQ$M{yv zB*t<*Flx)K6LG@GEWuyUwMn=tE#7d{+%yeC7^c;DMl3gK@f$Jul_>rJ9u$(O*3XS8 zC1c^HKEZkIHUl)h6;_EJd{c7Eo0}#^;t1sO${J*uS{1Uj-&#fqGeSQ0n&;n&vsBiQ zJ>{R~{_e!g#&vLt8+{VqeL=5pm0q`a*UKIrVK15{>>p^vS+l)=C#_y?@42AjDYXCG zc`M;wcZh>dZm@=@Ln`c)o1hm~n)2g7iY7Dh%RQa4`^Ag!<4T|>Y_gGn*fwYN)_-{< zdAPXHxf+t&WL-?=souMRJe4*L6v<7i7hii`?sqd~mZWN(GNwWYh&a0SP0CbEY$>ez zY_zv4!@B>sLY9(7RC3{!KVi|hIi8DWJjC)nv=@m``KXVZv`9OGN$Bd$D1J0cjr zO`X*CQQ}+e`UFlq2krHsfu0|ppy?;`wI=raMEu7rWC-OUR%_j0S49Ffm!LbggEyUF z#a7$EKI~F0&k^@qgkXr1n7+G|BSLWqntjRo+ExbwgzPSZrk-svrNPL0ODvP_&MrR{ z(r)AkIW0CD1@tG~K(ATt>Q_9|?xGx^tA>>DyZs|tVT8Ikp9cR+y|j?x4cpC74{OcD&Hy^~*%PUy+RlZJcQ&D_ZZkQpJxbi~BZsBRht+rH_oq(` zwcP>OoYOy?tfXc8zW{3}bWc&JPW&q)Ufc_Iz6-}zck~c1sOG#Ffa9A$MWOnQgqJTEm_n5=ftNcl)_maZShxASWoA~`6f|Iq(Jb%!yZpU6 zu1p3DEC)=5k9s8hnvX7hrClF`M3*%fBnZqJWFrwfgS|GpnkzNele%PJef&;L$6dV~ zsd;ui%do9F-^jx!7)o=^`WLPE9n3PAI-?!_PW!-cG&P1BMpA42kunTVb>Q}4E3c?a zm^}!Wdkc{`WJP>7qNk_a8I0ydT06`DtPsLdsncE)Rmy|S9#ZCPI3DA0zM^;aD~~?*hj@~Y~)heI7vlg zx3@A?jV&-RE=6(6!yXm}dAhHK4-3n-#2)wb4Do(A6gBuPze0D|GvOa(sV~S!doFgO0O{*+}Ih%Px5NuAH(ibcK14GmM zr!qmhhIdOdS9J`o*3R5{yN)8FQ6WWGQSj2zKHNbRp6!cO^4Dn905CEH-uCQZ5O8Kk zc9s()q>xjx*Hwu#QaN*PPPtXcxBc!Q{7=k z7=DE6bGG%x!{XR3a!Kt%lw+`GL0hJDm;L`Im%gAX95&F`N_mQeBaJxpc;-+)TEg}t z2HZXOZ3O9|=&%KVMj_`|+U}jCr0ni&!;RXL=i|09Ww~;g zal)K353HPw>c&{tA+*-YC|1W&syi)Na3qwmCjUd*i|fTB^U?{LK-_2&)GIy%#{T0v zwJlIC^n+4QJyzVz``fCKG7H6Vbo5|X0{h?y@V9&<-f#$$Mzw^43$z9RP?^ey^JS0u zuP;EMaM7wga*(>R-(r%?p~D4fYO)#{!(%~0MnKyc*0*{NB^>X4}K;1HBoy5e7m$!WBI!lORenFbD+`MQU3p}VGOH*nn&iBqA2@+mqg z=17gB2Zs11wLkn!#KIJE>M0Rh9S6sFBri&AUhL+1aT z#NC0{I0e&WtG~k+-{LduaI%H=UYFH%?!l<@P_eroEDrdYqlj;880}2|86)^`cjLuG z;jTJO=&t2}`+ZW%JV6raOeI-&(k&k0iIvDB+frKu2_m0IJ;BrJAHv}qMH4$G5~x90cwj;mmEwSb@VprlD%|i zy5dN4%tqkcyY!zOzohs6GYlfU?w`voVe2F=3%oZio(*wS(i+XikOUuu9ex!|G;oi; z$&#IU;Mha5#qxB?;#1ydf1Td;QfC56JY4k8$rQ2go|Y}IcB71{`o|~pNr9( zj&SGN9v>`>jSe>o*cx&~_U5r>wH>|W{QJo&VgzT(A$|y36^F(m1rIBLY`x0$i~zG9 z^mNCKSeaRQDUe$rm4_GXcJ&Um$d-2MaB|gDnA}1NMNjbtb|^;;<|*$qhBR=vp1Up7 zq@eG_YYj*?SIan%LI|XY_|)lAC$VGWW>n{cr$o;syUXA;T7#xw-K(#7eKKt3B=`ry z&WLrlV2b&Al9)y{D1>9*&Ybw9tIN4wadxec;PeaY6PpMo6b|SxVI1!%3nOXmH^!Y$ znKqH8G1&lT6@J}bTX$Nns}6A+L&vEG3y$fVSw>S~1~k}VWW2_HGspu>qQY+gu|1So zTH#d#pb5!NN+mV$Vhn*kSu(GsexUb{MM{*l_0r(yY*y=DS-oT!0j3v0z!yjwf)Llb zsML9DFk#mZ_CW>Vnk;nzl9A_XUYXReuLL8pYTFM!x!+iE(NYyt)s7?VI37zxR}U`c zBJMnCL6(;c)d(=lBfuD+G7zI-F2`o}fDH6=+?AFjB{nq0kR+_J&tbNUm+G#D`7-=s zy>g77O9WNOd6YR6w#Xj*OnX@`+a#1!2k32Z*&JtWr;ljctHG#ir^G8 zCsT=f0>)-2U?Ke!0)AD9=#f|D?U(Nn>AHAn*;3yELbAtmF?+WepB)Rb0YTI-u?q)> zv-3!X`cl$~S+xLqF`toA;sQO!9Vx-|tWID4$UJM1Ita8iy=ALLbY@^Th)B3c6EsU8 z4uB39?e^ywR!OG7sqN0brc|QbIG74~CPq z_sLIZAYaVnq&&v*S~8#KH3-#w8w;@_$Y26c@`-r8$f^B>SC|;*I&dtnfmc#&JG>?Y zewTW5HnvrHQKvOb=O4DMLX;LC)!wZh$%ZQ<)nG~NX1Ej822Q-W&h-R-woA7B3;^P#nQLyK}Asu*0e*nR>Lom0B8G zSN_tH+_ntn;ADZTM)L$L6+3+i*k9GNIVETqU5^%q!m$WL&B$9dfknt<{k_!{34w*A z9Bze4BH%9FtM;b+3TEOc7j&s7`nU2FLo9unJ(PDM+knpL9KyA5D z;~qt=l3J{M9|bQ7d_rBhYLo7pN;! zK=^61c@biJ<4>8=@CEChwSx4bst;-aX7H!gR<_ zi3NMy6^xVvhICP;+}1~bWKI)=FVg6B*d15}4PY3a7yP`lYU{D4-#cd0|AZeQ(yu~u zF679p$ZRI=a1Gou{ut)FDkrP0&OBaZ$J@9W=)68xws&oYRjOeFs5Cq9d{-5TLb12m zYocH$Z37yKg+Ha#A){*$stw#fYm*^DcYBo%`|l2i%6NlY8sMHug0F>#1xMR}PV-T? zCe3bsapQdzvU6hEP=%<1zhoOkI8lX(#pbGAh&SRTf&Qo*7IfN%lytELZ1|6x0SWe} zC8@Z|)l5_e=8~-_Ds^bhDs0vnzprVawf2X8bLMI95u~~%jJ>udyb;Ue4kblYp>0xG zW3d<2E2{U(#y5@h)yXYBV4zac4+E3s!vDfj&d?%v8qu*Ol|I82@5)tMyx&xrJQQX~{<;PGMKYk!G7;)%CtLeB4q)3*96LpX4 zNTp}pSv%LbMg4ok`pN*&V0GuU^u5f@PYghCJFkBY6H{^1h*tK#pW<@vlI$N{Wth;Z zJbP=GB{imrPy-C7zjpzUg~6u}yXvj-{vhf88P)VsbMl8`0{wEZBG4wmXugK)cSY!9 zw|g~h=7X}l;)spnIKw)xErX|k$9eyMI39$LxT-pJ&92>WU$J2?Kfz!@H~@%(%N!Us z(?^HH@d8o8JusVB3D&mYmh_ann}~gF+r>NsY9^lq*QD1OoEK3*^sMz|n#B|N)M@U| zI8U5=662jy7$~uFn4YHhNfW+s(aApReaX=E;1-Bm_Wbqae_Hh9 z3E8{L&&I&*j8OHP9x5;qcsWY^mSiM-cPWH3Ehg>#!L$&OA9i-qu;jG&01;u*9c$5; z4aEBxaqTkC-ugHOc;^{kDTTy^fZ>sQA@O`x1P}^e+|YkB8HKWQ4lhKO(BbUYl#O@9 z+dCVb(?N;#qL;RVlE6aQy0#4vyxh6*K(C3DM&0DCdd<$qTpCN2xwm_!LcxR^G0PUB zOX*KfP}aJJzd~e(ozuw|Lm@{tM+L8fLA&^!6%vbP%B(|Zisx&G%alPhL^>knEBn2J zh1j{GNFovMHocSGwrcUqFpcU5BV+GmeeuI&$ zO;Og}(2Ar7#=uv_5jtPM9-1i|#EmC)cdel7QgT<7JMX3M1gqfq7D6i_BW-tu02uHS zADlXK!t?`M%!dWn#>^zQwTu9q6t6E3b>GPCDv5BDqZ?^Hl#uaXlWUbB2bFStWQ;xq zJWow~k)m&P1cFHN`|6zbbWG$k05-hLD% z*gq(jl>8`bYIvTamGKWd2G~$emjLo?ATYAOrM}fhLq|R$-O#@M2b(|Ck~+lE>hMh3 zSqv&vi$NF?DCktK?H}*l9S@C;*b}F7kd`j`?DZ}b1WjU5I0L;4hhDoxJ1VS)9p60n>Q*w!u)5K&u2&}$sJm)5V) zQ|_Idyt<=gq2U1k4z6Cf`GcjED12Bz%>=dJcrxj!kR0}FkkbInkZANnA&~z&{Tf8* z@*#g((|PX_<>!Zjr4suloz=?};p2hj4vDRKom~m?nqfL=o3Vb*pT_q=y85m#+hN^N zQC_XMAvK@VK3-HIT{%@i+K+V4!%*zoSubGQ>c|S7L7W{TtYwHg3dyHKlnq;{&>_<* zEP5@h^v=hG!{t3>*09c-DzFW)>x;m=c)ol|*q8f4$`{!2SZ0kDal&^2@|>vm z4~@k++@eN%?LG;wRCmH%M7JcXii+UYALNrwHeZ6CU*mRK+{vsg>s-b*`IrzF@nBc= z18B;?#2G&84c>FtXj;ukj9;pds@6xzTJh!p173j^H%I%BtNO8wj6gbUP!EH#Fzj=; z{B}ZDnG2p$rGKn%#Due95~pkepCmBpBMmngY7gG7#`OSeidf9% z^XSncY}uoIX+=b_oKFx@?I>(B=Asq3cjF1oZ+qDkriH}HZ+eE!g9hj)nqmyA4yc~O z4&!8}q%aW%(Wi^9tPS&4G_mLZ$=XJnR4G~rW;Y78(27}pS{&MRPVp*=4k}9AweF$O zbc&=ib9*lV7QqKs8kCwg8xTko-$4Jvc#|rEKvqa{H^dX@_>*kOa9_TT1c&LxYH%(= ze{!Ui0{-q1|IG41XW&)Rt!F3!KD4|a`;l~ofrIV@M@_*M<&55K0`pM~NMaJS1xzGx z#rbDZR%1>_6>vV^!8x|f!PE#pLCv_m_km2Rf6SI@UZ)5HX^1>iMnHid-uIfV#KG2F z!Bqp+AQmDCYd=eg@h$A4Rtv#Ni_9mVi{-qDC*=xi&kt2@P4NKBudxuxK3U;P00u&@ zQ>_uuZV4;~y=FVuU_fffuT@nsDAX*(qLwaZ{9Pbj;8dUvCJEx$w_I{w{96hqpaVXZ z7={OGsBrrKh^){6hS$xkKH|7$2F7qs7C;q{9A*0uExWccP+CsODDz~5cJMul)7FUN zNJzWm+x`Mv#KKo1eGLl=!1Gw5JvN?gtx^R<5%H3*gcQZ()Lwhxo{_R7+XU~9NhG5R z6c(I+ahJ;7d#nGu6bvvRV3EEYq^*Wm}ld@ zhe`7M&34F)3F-2R6(cO4V1C_itXrW|74yr~0WL$Fn95`-mx9q|iApg2;qffB0q>b3 z`4A-l(PW$T;=6M!#8qv|z4WZlab@Q$YrIgB?dXWrUcNv^TzYz$ohbmRWinMyFbMn zAlnaFWW}|QeH0xz!xw3glX>O9)HDkC_}QIK&5Gh;t#<3w4r0@v|GfG42A+YtBc*OgU3j7I{=s% zRmR56nMI#67fqI5)>t>PF31PhTK$bSf`gbdBQMQ#DbInwBRh|ejR(PDb z?umd^M>r31EB0v<>i1rAX^VO|DzPTLpN`0a0kJD129__lTEml>b~og+MLEOHF+lMj zo%?2Zfj;hQWr>urzY)bBRq_17dHU$=TJZUu5ls1-c^(3<*B=Gc_-ppaNBktXwPIza zW1m`dVQJ2+NLwjO^+zu-HfL3^<(b#Zd^K?D-V3POFgnC1YSo$j3SKPsK&p^OmYcpr z4lsbm*6ADd;36{%it+Mqc2fW|yFxl7rvL7KVTIryyjYKC&Zx%h9K{{nVUu1HN+^DP zB6@eNdwqyPd6)(b^a;e;D_;z~(cW^tf#35=6WwAh{7@;iq6}B)pTgN-I4td+NKF z6`%^uIcMwTKOuxG#*ULQYzb8?SI>sWT;0d~`+sP_n7%1|os2wF?+W%vZqNc93oXS{ ziR}?;Dhn$BL_tl#0jV26Sb2#551sn=C8D?!A^`UJ;e%9Rwrg8+*ucnE zU>>QJSB?$q_YD=oMS|wt4oOGa92pM;z9yyn=#42p0r$n_4D;CSlXQZM=(f^O1R307F!Q%=4) z0d&m^P_m892{#nm6vq2<3C}xQv>fv2sS@J6!$Bn@e=@*hBj@^dzzUqi9vXyP!w<1z6DY zdJ@^pUll-&P@ao~rap4s>F(t{)u0@WL^!A%e$RX&B5A^m4R}VvvMKYVN$@@5~VzBuH{t-6fPF77ovi% zh0BILA~!Og!EY#4R6y@b=vT%{e7NOo{Bt~1dP{F+OzK+%tlv>-0#PA6)*oJTZFLJ5 z3Dhc-!(hly_+b5E219PAHVKCasdv1*j%nMHLw1BnIAk-H*=6F?kQ#>?KRx)%3yaNP zrGpIct_ieAN;XWxL$4OY6HDi|og`Ea-P}A~a-hV}b;=!hN`Od5P!cr2*_ z5ca5SxT%((ARyJ1*6s0M*<7*JxsG;0|Fu>%#$QaiRY~%t`w>0GOPL6}9uca$!^*BR z))<_Vo1b{7xkC;_$s$5)Rq&AoHvS8&{wc{Ir9 za0dz&;EjTs4ezC`o{IaHK65JduzV}t^iwn5I%^VW84W>qY0AtPITeEa-N!Buy%t$F z+fExtcz+WfP*Wv{)74y-kWPFR8r&h0V9?3|P)t#{>c2l29GwM=yYI}c49mHu^lW`!^6i|gV`U(gkf>?ML3R;g}NbZ)@+lUWk{J715h`^75hvu2O~T7Xm+ zE7F_lehgc#q%(pzWI5%V5ouNLvppdmM9AI`ZXPVt^%3ikk{;d;x#`K`pw9#!nXOmM zvhm%t5m$% zB$L=)HVI8>r*E0(tH!2U9@;ZozsQkA*u@+%GmTmW)m#6GQQIQcRmK-Hm10EkZMtCN za6>urf_at*b;tBAm^z#Xag3+rXcflk7CgbEm=yn(x48#!=+)j8Jv44$asc?WnJVx0 zUU~$LqSqd!cZ^tT}9;_Qp0_tpqfR`vyggqZjKYm2%VK4IlHE1qAb_2Vj znaX(dNXv+4C+4CaVQvEIBGJ+Lc}N&-dbs1kZ^CI9@o#s9&Si^>?7yTLBvk>bvH>Qf z1C-+yu3VmlG&w*11DmzaiVre@yM4%ihKtLdYPkpG9VJ4FkO1GJNj9iLnnVyn0urvuq(kOE{YyDULpm2UsS0 zICY6Dmh=N2jHI}c9x5OpOJS5x7`bZJj{nj0wes+J&Bi{3WZbW-dYjw+ZX(qoUoJHc zUxy{O;HHw!;%=PRpWMYNj?d)tiVBh`C51oO=LcIRh{_61m^GhbIIe2+aqhk3Jf|Iu zv4(-8xe~%H8SGUnmLIF$IjJ}3(te+M1v`n4Pd)$jOwf}*>5cOUM@+)k7Taryd>pS- zuo6SIhy?-va#1GY9~@J!m4M~m<8?xKB-pbY=pvv%`#cN)DnQl0Pc9>&gki$gz~s@& zEK7So5hzT^jg2el7Mw;d)hBtiKYYYqJg#XKa5ARJkc#pFvhUn!y011#^r8b03zC>}JAQA&Md;#C&<z}_oK}9YM-B02bh<%D`W_I6n-{U)Jt;MhR#hpwVLI!7 zt3sGjiX{vy<-z%~3XS|i{E@*xHAC)QSXbt>Gdfn)IO5yR>W+EFF`p=V2IeYiTItaa zNv%H@GvkL^3Dz2-|7oUj!hiQqvp`B``D`~Acr=&+n2AZpxo-~&9_=GAQduRN9?PVja|&GR}@QpDXq> zB;*wFH;bQPL6(hchVSp-)FIT#OoiQ(=y1V_`nrf>~fF~XWt5_3kl?0wEI(8Gh2}14+QVAeyJZX>N zr)Vp+*^h3+kg}9RnhgmWf)<)3jXaf?CX(*NBK|igU|DFAGf+)QrA6?t`@q0-N54T$ zRT%B}l!~@JWiMJlJ9^ZN%BTJN;yj%jp!CPkBDd_^!x3k6o$2T!4|^QCPXqTrzrdx% zrZw6ZH~%&7EW*l|xo?S0zS_xz?g|Jv@)X3)bB3Q z)x@v3j2<<+jPFEKLy(hudZ`dLx>^)&iIWc2{=G^XU!c=YU_!Bs?9}4{tCqW!De&}>jG=QHrB>K5joDD%*F7*n@df3RBm07Ss6-uU zHzGW7BpxcbO{}fX{1d_p6}AwzIywk$kf82 zli_k~Gc~}v3nL+=iFxBcMW{#q&L=BP*@ z=n`K>nQJPg?n3%rMEn;#^x_AxuWD&=>%7~Mhks`qKt^t!AmUF{ zDPA6ZhsaqXj2SH(^ulPN01Iw6KrjrtNEW$kBqv zWxl30(DfN77C6u6V(RP7`gNzRS&yq+OUM;EVYXlq3#y$P6c_WeDB45{aTApXRu!tn z2qm+rBq}v5XnhcBuN}YbaFYS$rhTT&s(T?AJhmgsz0n$HG3VU?Q61Gg3}mTjxs-yU zkAzk({wJmb!I#9kMSK%8+8gMiu~?5aT1sN_Vg6dINGvGr^KIr`-&ag#3dP*=F^%tGb ze3_aaABYvD4}a>(X<-k4Yzm-N5=}!^Xqv7efgI^xxQ%+hed*y#a74YUIep}7;(dRS zHX?Hr7-}Jcx`C>yj>aa4?T~nBGhyVwi}RoQN(3>FAT+5%NtL&ucex&=(9wGuv(rkC zvsju8ol-re4r)Ynksw^ijS*uYGVEcB*V`;*=$p~Df}swk`F2Nn&z~Tp?t*{#DsU3O zE<>JNw28#}mfLpqI-%l`pK}B=K3qXgnuDLWtWoQNhGO}R(79{`T3*nocx&tT0GqnV z0}8^KJK=7U$mIzuLT8x}tNgZ-74_WwOxrpO^L>2; zdTPxgm>wjEStYbCBK0*&p`5H2hH&-&-qN)NK|BhLOF$ePE0Oz}Wf`|Akl2!rVzuHVP?C}Wr(_ZH zptH1%i$ikEC*|7!{@yh*QF?s{(+O7A{L)qrN1x`S{UWdtW{HU7-wQOs?zSp2l?wQg{wtcrjAIZXC*^^ zJ-T(jHGRPdZ@^;{zdc9yQhIsQa0?_qk^=_OhvtgMkTZEC02mgklk8!LUZy6I@X~N- zECWYw9`)UuSI$t2EE>0=jy#()o@En-B-_(p5oPHb!XvxtBy&!Elv77IGY{?)bK@)B z0~=+YBWs2P|C^d=LJw?hPZr-eW=x4QK}TUAgbxYt{s0#ytU)QSoi+ScyU_D<$C|Kf zQK-UUh57K{HZA7*ifu{QV+D$9?zlhqhY=;_!YE+cdkaGSu@am~Wi5>@=a z8=>}Do{^?2xRTp{;WNO|wZS4pW@d3X)2HQdn&!)`xqKOJKBYBG0YhHXsDr%>>d2ua z_glW(>WByM0ItvX5ExD{(}^Ork@Hx?>%xvHSDmlk`Xu=Fq6k2{Z3eu2hDs9&@{?c;{w8Yd9{VV|W?|?C0zu_H@XKFEmoXt#HMCJ!K+gySACud8& zg+?q2J|6&hh&MXsfGW>7>HPRm1FM>dI@-IK7%_$I`dT$sPfX5*ruu(Q$xG{t`A-K) zpx3TIVRo@leGOJ%xC*mXZbfvN6fVu9qi&U0GdNo}Nf!a&mVZcMwWB`mYP{BaY!{zqTE z%~rQH?F@VUtq33i%*f3RbRN}6nhCahWiZojBa@^=ZcW)!VPQ@vCUM^4`Q$IWS0PX! zl!;#CtF=yOBjx&Vn@B|&KYF%*l<+$X($xcO~VP^rvVz|_(-Aj4qo3ENTR2$A*h z>vRO}vttd~i->yB_{F^}M{6jUz{OB;_SuH3gL}1b-HnQI1pUU-6Qb7bicj;esG>OV#%AP*%;$ws>W#t3zMC)RXU`GmA(%)5D@ClX?!3=(b;) z3D6i$r$MZZH!yC2T(2yPh~y0EdlkR%mxrI&tMBuVXwCLM1iKRhJ8|c(0fQ7wQUKcY zad~=;Z_^FC1*HsaeOkB5bZ(~;|9!iU)RA4UI3yF_hv$TRG$|)n23C4zc8k0&K%eBhd=kWqLcLbX-#Ul0e-^B)M?67OCK z*S{y@;;kFh_Z6^uTl+~2Q#Nz7gLYZ`ggkXCr9YPgZ!v-GT;;aQQp~*-4{V^xJLZGR zX=&=W41;_aJYEpFr_gQ$+zK8YwW%gFbi+26Zee}YtJ@g!w-Go^X9QV1Ad2>vbYy#s%mqA3JbR@OL`Bfl9XFGQhZPj zCfJp7H|WvW%#l3%a)Tw%m!S;%=HJ(2^*wxNs&yixX3zneMVBxm#^52THlbuBcW@@~ zS?MFtfu!$+>abONucSq#x^ryKvcw$%_3@+HuvL8XIPYQy;h{xiKps#Bgu zJK`H<+r)C^U|>Fpj?hT;QL<`(Ql1JHAocM~LuyRuc}f5!_8w*9GbT)(sH;B#r@;2t zm01tcQ=3 zjjDf2Tnqt#SI~sD`5{pDWg0vir?h7ui3=>{Q0bkP{{fX>44L}fCTz3GcIag`mm8Jl zSTjsi-}fpHpKj*#P(M@*q<74o6BJ0{@F^_N9bhsDMc_WYtbQfM+MqQBzH;mzJ^2IO za;U;dYDQScOa5@MW5|HxZzahDhpwGdf<>T=kvm6UI+X|XX49^lg@-hYgqxKu0<7K1 z4B|#{fj7v=q!M%ERgQ)k7wWM+w#bB&ze0oz19ceT-d(YNVQ1|$XUgZLa_VN7gr^Ys zH@@D*fe6rgujis+d}7!%KC}?At;K?fVA^Ung`PddqxJGH^C~Zw$v02!@1ZdSxDZ6) zS8;x{_IrcRP*Oix4=+)~>;3~UkC*JkJKCzAF3>d-(YPljAfu4UDSk#>GD_YQ{|Bet zs-0M^SENG5_0;z*=^m9b5luo?peP#Sq_u262d2K3Do zkM)%Es^LB?ftlm0?f9IrhVZIkQe0Bb_YyZ&6`^d365gy9X22TS0&8UBA2wba`WDRg z+e=&=&3Q(!sG{HJUu?Aw!zN}Q^)XN`SWh6X3$BYz(;B@diXqBy8&8S; zFs7cPGmn6{m|fZsfm$K}-~5*Uu$qUc#am+Jz6+{aX1RK!L}RDa@e8LzP2_0Fq%mK2 z3jybAGcCWvg7C>u6ZQVFd@CvW9e=O9`;TOHnp}Nr2@;{gOSii#)&r!|3! z9*8L!83U6!%#N;%9T62bo$9<$XM!%QyUlbgD-SI0aWL`%$I8K0B)uwBuf*lQUiAt* z65~{|-e}CV(5_f*0kM+*Dfl5|bVzF)dQ6Ro4yV*)E8;{15?}Ky3uK~WK?_1sFH$Z% zzP$q3j@KqRD3o`jJy0jWxhy|ry+roTiO~?UV^#oAYG9c%xb7J?*RiU?I~o2hcAb## zV-@QI75&z6L+}EcTliNSYDO~ zjjiUvk`LXd>hPT0%>;GNt+{??C{;`Yvi z69VqjS{ws9Chbs2j1KPi*g5&`wcfPOuJDC&p<`~d9y5)PQ`k0&HxI~I3eF?7`xxD2 zf6&z4{_KWH=1OwgvuR`Ke!t<#l6rA;pc1d6Mj(bRM&)>me2_+CV9Tc}6w13Z?mnqA zUOp_RALC|R#s2gJu2P7H^obytLk}$DI~oD_PJRp4g{=<_?u!UlrK+53ApnAlkYtD# zvbo$LHF*AwV_}~SETyRnP~Vo`q+dw&hSX~k*Wj%(u#u`J)Y8bx1_TF42e|QUZ5uTe z5wFWygs8{aq8-@90~NkkIi1VNy&9eVdri6wrLh@Ko^Q#j-rz->4}IQxy zf!XazGcUEHB!vBSN(|fFfl7NHBo=^l>5SbRx!( zV~ZyPiCcEAr1fd+o$80}N`W|v&72OM3lV%xCGw~4z+M12%Ww(b?>wxt^}Hs(PQ_fR zTayCS77D&+ePC^l9uU5c7|gzy6_-!!=Y})GI*NtJ>}>X!dTDAqQ4CeSGSDPKg^4&? z|8qnVC%iX`@)CcEE@1zzIIp5;sQX-UAiEW4hflb~0Z1e3vi?ZMlU!OTL3l=$h<7fM z_faH45rZi(Hf9z6;JKoNkzqGb3idD^3rW8{f_uIYyn03GjQ*@OJ1=lmq1Je}a|lxo zB6Ti`(Ki8^#*6jR)AL5+L`dN#@h6DeKcu}#QyYiMYHdyrH3sR@nX-yq8_X$KF&RYG zAX7`SrdQ5U=%-^`nq?UxGuwVlpvBeY}!+%o$5M$==YzuluKoR?GMZ7KU zL%S6v{1S><=_T#mB$}Dosb27bN$Zy6pqE(gAb6h5QYR7jV&S?BbKRT{?k{yY*Q0CW z2aI~#{#5c+sK}Eajq7i#YuvZVQP2FK!l#FHHeoMms#}tp^E?lONfEV|v^dY9A0ACw zfh3XXAWenH{kGk@F}px0hzMfe;IdBb9&}Yg64Y(A#Wnp$cfT^BPoO+;63L6ia`Yl} z0hhvB9ocCITgJdH&JM>`TsLm?)GagzcrpzHLN$7TT#p=k-H1NsiM(&d`mhVr#88`# zJ=VlK>5s@iT3Cy8XkS8PkV;mBAkZ7=rugxYXTgz7te|^^?B#&1JqSk@9TCbHQ4iy3 zxj63CmfT=U|Kv?o0m0I@d7#{##a(O>wYPR{-;)|CSr5%!Eny7w@;-&Ia~0?_hfEWn z*2m)GlIbiu4V5o-8-=YI9Mhu=cJSChHdtg;>k;~P^&-H@WH9u=ex2aj8Gc?rNn^sV zzMbz4lll9E5!T9@ZQ*mlETRfNnc-2-*xrfh2Mq%4lbm-kEC?y7oJd&`U`xtoerMN` zIaf0S%$3ZrrkRuDhK$(*$I^GlwdN_1+jHEP&%ZnN(Ti_ECekg%6qEW$XV?8^x6wv;)QB!`OgCLH>*{F-k@;iQ4cUjI#C>jPB@ zBUNEiwnDGc;5CE2(V7ALiu;U3yLVSj{D21`tU=h$77cW<^|zw2=beFeDPXM2zR&tG zTQx>TGSinGtDbLq!E&6_Tk3XOr@CIMUj}H7?qAH)jx5tv`*c20O7R?w<}XH&LxtMB zy^Pb)e)7_a6D7cdSBbu^8~HNl3)1X7vre$1g$5X5oJG`)`|7%2)lATdSTlotACV-cE5#dZ8VvNaea#ayl3D; zlD#s$s6$Qz^v&yym-RXBMH4U#Xo5r;0ewhcBKfaPVJB^_LQE~G7)v`NVAiv6ARL1E zpb4UCp5X_lz2dp`h~^E`_v`_*tqwM&*k`0)fd?4q0p^N3c(M@DZKHgIh1H^5l94y> z0R7DdkSUx~C!PVTRQ$J!o7s&g-v0-Z4te54`{M0+(=T^OMhc9yp?97x+WDY}G7-~s zAda*;1Ll#nkn6h%t>Z;tFa+4&;XENZuAnoHWFBxr!JCiiVUJuJL;X9B6oh0a-0uR$ zA|eLkI$z)h`Nguc?uuMBv+hA0&ZcQ0c93f^>~TI!Wol(40bZUS!yR1~!m&B`%ozK!(^77e=^gGf8ccr;Q)}VF z4kL8*^n%S>P$nmDX{)7UA5P%-%g@9^!(1yz)kR)%r78AO;0yp^l6VJ$R!}q*m{ML5qxv5G=&eKg{7Ms zo)XEcI4~oay+n~?)46^vJZC!y@4}&sRPaOf7{zpe5qi-C46sH1)6by=$;FnRPT7O7 zHljU`AK}f4VttvN!I^c!T!!Z?E^ed?9jtHH zi95lgk1A`X;0Jhzq>#dcB9NfA3=;}Y7QFiSc44= zn;I<;xenkT^Z*~&UL6N}04xm#Y4mz))>8-mA1(-boFCnUvm)S0v;l_5z!c)~+m0!U z07qrWioO_lQi4zIuiol}OIiXeQmme<7zzZ;tIp{trze$FR-T)+WK^_^UfKWCNU^wr zXa>htUv7Q<8pQUYD&CT3K>}3Ab@G43H=c)m8dydNb5_a)jun2w4U28!lX-8Re9 zlDgVMqa_!^s{6l8^z4xOMBRzk6ow2s<_&MvMOwzlzL%Dkek}uSD?Ql_*z6fkz4z@L zNHYQHZN6PgDzzK>;gQx)ggR$nuch|9(O0u=@~OvSMKzn3lX4#b92pg#;M z;c`TEv;|V0j4(oOBAJnZj(*tJC(&=>)dj)PVuO#LJ%%-U?VA3*bjd5-g>G=uaycfm z(@j5CJQ8bG$xDT4#e_%_;TLQ6x-4X6$@|wvd_G`o=r-zS4sp-f?<=EJ5HZ}q8ZJgk z;xgEeIXp(29;%SR$v8<7j)!{AJ?*qqT*EEiaRrQMX?d5x#n9 ziqYYupx=V9#zr}tQ`!UUE&v@KGj8Q5<3KUU>rf%uB26_(ACAstO=NAY1|Mn?U8XA> zA6@pxIYRfy+1wy`8gYgTYnQ26?6}zfwa!8mK?;w1MEEU-?QOQ|)r$D~f6K%rRW#4y zGn)6pPq6d+>EM6qCOQPmfrH>3Fh}r*8?&^IBEy+Dk&fqQ;dAEmQ2*K7M5*X_)};A+ z{AYnY+05;bIU~rh1I*hVV8vNEBaPyEW$7nfD=-)Lk8`1CLLSgA+F(_r2TG+)ui7@~ zFjzz+qT8NNL}kz}e9mc`GsF503?_xC|ClFy=7ORHb2vA-P@MrD-Li$@Y?*AWLU}F0 zaH!7!m#}nP5|wNU^t1GFU*oHrJB4o{If!33yQZi86X1k+3ZLXRU&}@Vf4IdZ*B;gF zWYqY8VkDyzV-=a06C>fLb_R}NvH3p#n5xx06~O=V=L4i@R5%VEl#n|BPfrWM%3i6ScPoUhBIsCEO6L zcQ!Dp$bF|uZy|=^0Zy-owno!kC*<*F=51cmsM$$50`62PKWHvglHE$`{#aCc8F(f_ z3hG@nFjuAs9vLpATIqZ3CzU(^RwvaXys}b^8Jk2H87tczC23eo};I%Lh zz$TL@(JEB(n&H6h1EK)<*!kv3D)}B4Y$6O`zK|AUbq3d-P^~KuR(dRLsmiR# z3)#Jbc`c;GIYhRK*cS&YrrHL`kky`MC0k!UL`Qr322!H{+7$QSVGUXp8BA|$)7U=L zQ|x~UNvZib-$l?;U8khY*60{p@7R{BZ2PL2<}^C&a$EBmjBhMcxsZiO)==J|oCnYv z4wS!X6&y1ffiNJ3_nNRANEZeGj=Ib1I22B_4$d|Q7Y8ra44>XrMjiP7rjGua{ctsT zGe(m%#_^2`X+aYiK)?>w6Ws(d0gn=wpHOk)*>;f=r&{j?eUK`pbwS02nOjv7x+kDE(Yc4OlxA7*&>f_MaEp?v12dwSBAga)Is0YVz; zx0Jh1%6Y*h{j9@P7_WyR4lkXNK4AF9ctjQwe+zrIG|4*K*@4*djNQwjm?yJjGUtlp zw}f9H%?>q5w(`Yftwi#I>@`}8geHtsd~+-j@^3W%Om>I0Su|jq$zZ5fSIZp4hJRi@ z6vQtV9-2bE1z5ZGceAbl5cR{j*<>eTT#8_`488-3zX=X9c8VywL2vA4e1`Ou_zXlXQvZ#~GicXpm8AQ2p$slM22WquE8zbl_BqRFRZ3;-a=JdU}&07~$O zT{}(C8Ad%ROkYvs(p4eUyAqlN$8`=LgAMN>4J}!oU!Wn2fa#^9f2DQ>R>oVEQQOL8 zCJ1w`6jD5S-pBf>4+(U5$hSC3dc&;Y^DIBfwLu*6=*=Ub$Ek$KrASBQQYdK(@LYJn zW=XHI?Q!;MeHp$KQ3yNZf?$h0wyy5c5p-ybtiCyahzzZjDE}(nX_V4~6Q=oe*=_gk z&+1p@4SNcZj0+ka=O=NA5GN~)^8|nSR>>goS;tBY7CKHf=dgTA!WT zM+N6*W6FiOJ81}f&f=-4hHLPF%^wdxfqA^2QYQE&XhmHirMn9!1$fj8?;#2wvZ%sz zFYPi!tT-X8`dokvQQ;!u(C^(*D#ak*!grRfx$)uRQy9!3mBg#}g!JL-gX@)c)>IC~ z#1s1QGy{-CaVc|XSCzf)9bvH{SCi=E`96^XQY!2JC9-2(S2W+@FaHEv^a#;Ja_`OR znxG4ealgy*%9^>Xi)7Er-9iV!RbJ2uFv;M8Zg@?wY_OP=Ym+-tqRqbsv}p*chx%4N zEDy+LA-sit-SFEpyBA74R&fG>Dww*gclO*eu@L?_0~ZfO2J!Je(_`ZPX-#s>BY?K` zl;c9ja^t`_6qYi9gafyC`rKP&P?dfO!J=B#X_jN?4!T{9)GB!~2(9BRH zm$IKWLtV%ik>iR@m&rk52vfl9R5breLQ}3N?g4H?7_%Pw&ah4om~88_$VKx4no@fhI&OX`;D5U86rHZKg`Lg*akwt95_qCO|Z^ z=>X@A`Ao_CK!Z5AIq~Y)dzUUaRZmvJjpNhvRBLhHKx+xj#o7^5k*s10XIQ@S25Cgy znBUEiIf`Rh>kaf|+4A|gL$`E^>*Q{F!ABy*yA;sO#KUPEF2!KG%5#s0S3f$I!UiA7 z%@eXUEc&N`>CbB;;4JV`;WT74RS`{JC(4Lbt+gA?7)n@-2Nt+&b6L~C3lB2XrvV@N zzeSB-P+YQtW7q|mLnY#<2^wQGvuPs@3=jKatPR#@VEn%@{JacMi=anb)HE6z5jcA< zc?CiRD&{u}zY+rl_!@Ssu+QR*SYIN~8OSOQ7Vlf|KreF2_5k|gEx1*ic=sbaCHQTq z4=V%)#KjjCI<0bWMU>vC)pzM@kkqvjUO_l$AJfBFf}fU7EtyNZB5$Vw@>z?@3UV97 zebcPcyqqC!xe*;y7^HHss%|Y6Q3TgKEqYe>Z1cG$w;D_Tq_S;|t9#0g&-2xHXt_*+ z=#rD9;JZIT#XkIq7pr8xF#q>+r<}@%0>bv`mY4aCiBFJE-)5uH>aU_i$&roILJakG zNY*eGs76`tAV!kFDen0 z_%=2^7&3&31skGgoX)izskfM-rYuW+^x2PXu$&xFTY)2UJpsjovzpd24}P5k_|^gD;`AE>CzAr$E%+C!5;dO!-N4*AkIotS(c`9lj+Q zk7PCbP`f9c))^;@b=!t%t3Gl{;>*$QOVtukkb?ol)3F9)v>UK}}6a~q2vl)K| zRnahbBffhFyZ&nl58X9Mm9bH5WqEP1Mt=v%EqGh9bNrVq=VK6cFQpJNnSj@+&RC;7 z24M42>||xE*5tt;r8~zzq%so-RTF?2p_pEVVm0^@2NW&VdSI!biv%I~YHDS_= zk2l2dxx3C~@F*lF8E~)S#Vjm0?G=d#&*WFMx9?rjfKw#<55Qo@3FTm~e>inkq1R0R zERClS-_$rn&@keYJ|iXcZI4^pZ$$ger$YJ zx^>P>ZelY4v86fhq(C=4Rw*vC;mJRK#c2KMW1rq3F7*Aid`0xC2bSPEoKclYfi(WOBmVcw*CMI-I~szi03g;=W_B#Y8s$ z&8o7-OJS}|SSml?)he;kQb+ge($V3<%x?zQTuNgll%*VRX=R0?=rgV#82e#+85x+7 z2N)x1Toy}sjW(n5e^W7~dbE_B)_|Ah9pD$dPt^@H2=m#)EP526>7L;Q{k_-0Szx1d zGeMIKn4*8@Bu-rmown~@PB6HOhyUYoh=4ZL8Yx7TziXMviY`EmYyk9&u*Qvbkjy$VCr*#opt=bhAV-aL~~T5zH}|k+y6r786QlE(C1#8bM3{{NJ^LC zg}PqCJd>Ara?040>7on0U4tdq;h$#A2tAb0{WF5~W1~>h+ew6t2i1r+h9mlA%@>Og zCG^dK;RAc&u>i8&1P^4`{|vsgopG&KD;egL9-!ZK`M1)S5`PSO>lp=_T6>8PZZ*F>ufaP(7>G? zBgJex*he!UC~;4H0jwZ1Gero@HSIaT{Md$T7wT4t>Z{=5(M^!>)Rd!sCXxy3NQcnl zn}c8Cxl0$EDLnVVJgoLoXtT^1Rs&qy4tDM2Uq+y?ci83~5|pERh)}%olB)$6E8=G* z!@`6AbzI#|X%zJ?y}jzdV8O(Rg0(CB75G-T1X)AC}Ck zk{-;K6nIGDxSwP4EL<#ff#WH>pAY(-w&AP6M8Zx&_m(pf*$#Dv2eDbOZWAtvY15>e zJG+xa)$&P-I2=ND@Bod6*82~Z;-*EpYHKP6-=#+ECIqg2y>zlwI#&hvpb%RsM7USq z>QSd|)7_KUmJDDPSbmXi3^I6XBTpaNJ z?;fpQIvurL1PTQZ>nX0R^vb(tCVw^TQu+|S{$IzdB`CdK#f=MoOyZZ+OgQzRrAk?H z4>ja1A$H?8e8SR1*_afk-~%Fvb-0G6Gi8ZIuk!;14orbyhlb3bJlSBN@|qwn`72~i z3hmZW($_x?vLB~|Vedguxl_ZSG<* zxpjh(EOxRS+y@|n!@o;3u4tOn(PcRh$j&EiC42U&7itk$3jDqZ7tiSvy2ahKn!YVR zg z2%MN0XsQfoG(cwHK2>7~B!;1VxuJ@V{le4%P8vyb_oDA=6VCG^Ir&tb=6x=t*^nB> z-g|-W1N<3XKJro_6TfCn)1<;uZ9zB2Y8Gj7X;3=vuR!{=1GMF{xX^Ey200anx4dGB z1_h8iFc*CngOLt_V&t%rw;~P?TE?EDEJQn9UY?hd{EYws8?(<$DsgrBL{n~n$(Ge8 zue`XTQS@vRvn}52Q8Iu@CW@FY5!55!$|f66vTBG7HCXAj!+?{c2qzRDDtKEJ3afm+ ztM*KNsnhUT*_-o6glnOl?pTg~4-80;$?HJ&^x>xY10!PyqL< zeL~uh-&{!!5YxXQ|G<=gK&x0b;)eZaBGt^WdNb2_=V__V z0pIVan0M<1dUYjbaD2u!cz&?`+dcQ`oMXeWIia_8l$>{v=$F? zf^2CZ^2LDQ?~l`u)&Lr|8L}j@iAp^rltY~*@J*_*vRrZa&M_=zsN)%49>RZ)XB0)< z_Sp%bhc~p`^KW8_Tw0i0CTxDwVkc6V|G<>x0qBFFEVM7=VRpODAXrCejH40?EL(-m zIg>SAw<_v-GZjPb5dEPCCATh5)VPAnFEGQP^-Z*QLotP{ z*;NDn&qk65MXOZ|o~9GJ=c5)Qf;m{;f_*ZE zd`&zu1ZinFz=`AW8I!Rqi{6WJ_kz_4PNFm$4^`S6h~Ll3q3*&HW-GC6z>Ql=lXg!l z2aW|oTxrp3O*+eBa>yhaWKk%Se{WI9?ru=GOhq%!e~*0ZMMN*X0T>V?k}ZKLB5D)# zaZ3X%Bfg1$GFL{!VeE3tXvn>A0L^Wz$Rgh}Z3N4rhRfJ8h3fin^#IaN2POjHXH7{J zCBIJD8Jh{gqiouaK0(bV8JX&^^yM&)ktwmsg;ux7S--f9Q*1AW*ARJb5XRcp70$Ib zro{hp^dvV!(q|@LV1Jg-xu1^5K%uu^!DXR1av@l=p37j=!ClwfqADz)a(-6SS(Fj| zLfGsc=~BE^&)(~G4YcOMkJE<61Bune&6-bgF0MRHO;M^TfAyUZ`7*Vf(kyds#D{o?p%m}|))TZ?DDOOs^Ye=h#)I9H`xakl zRth=&Ce50OC1*<|4c)`X4=|cuccn9z**pl*dUNBr-!2Jgag`fBvBW%}G$Zh)N_Ud#!NDOEcGu<5*xxgBHX_MQB-@=>Tsb~vd`ow5 zHfNz;8P(fM%#*S7-btnCuC9qx2vD_to**ITkpjdWR$;v(eVG!zinxF}c`Mj{j*QYW zKBq12a^WlFk-T+O%k#{#ozr;jqz^`xk^K@I@Hl&p+?CH{%xzjCeL0D_Z{hsJyT&}M z&WBITon!|RwFYcj9i2WyM8;7z@i~C}FAK#77}184(-}Nv5` zv5WuA?f$APQ#<#6*(Wf5<2x4gdn>y8CA}k3^xu}1;3p7%^)~Ga>naBK|2xg+IEp9_ zO<6gWwqMJ}v4-I)X6!Z2CG!bACf>wOyVOmab4%4Fo|dqnov64@$tIwe0rXZmfrE@W z44Gzy^a7A&Mrp;CJ({7RiHc23A9cNeX%lFYQy6^Zm?Z;Wdd|Xu7p*zqJ%^;pcX!2r z#pc1*`D-yB*e58csU+kVzO{=%hNVSz_J_?6ZDZJ4c0lvIk$!%wmp>YV`V?J7gna@M zKH``!*#0S_L;vB0+Eal8Dwfz@@McC%UYGG{e60iWm;Q{j?+@&zJpR1L`IyaAGFkK# z9sk^xv2v|6c=IV=duG0cC#glh< z)A_=L9f$Aqxm<9xr(sZo`eVk$067w7~Djp#lf;)KwGA znU$UET`_&ZVvfk0gi+Nj$xXJ%7>agi86VV3A)!w|>Y#&1SFKt9s6%A#l&|(Tr}5LZ z>jBvaVqUQd_d{WRMx^qY6d{kjHmvoA0sB}@+`KV$VZVCu&mer~p+%B>dmZ+OIjT9A z46FKbp<^%iY6-LSAMPm`f|rJZnOAaxT4o%^#}L>*`|iD9{IT@0?ppt>h8)!=FJ-#i z(0g^(q_608S3>`p7GWO+#w=uF2%%ubc4+BXvifJzB17uNA6?{E*s4iRM=K?Fm8Js9 zX>r9P{G(n_<`xgc%<(By?zlWstofK~l`i!^uO62dR-ird|5I{x3M>QaKQgfEl9!*P zL6!YgR=CECsGX#apH(xLZmGP@YMLJs6%?j*CSzP zBuoR^;gcPS{t=-rZo#>>F8If(P*?y|@w6B3h`qKifzEG4=UBf2%T)+M^o*+qowU^mr!#!FQeq$EeYGMdwhng|@nQx@*Pun_D+SgO=J(~DBPxHX9 zw|eB)iQ08B$1Op8u$|ZgAamngJA#?$Qt{1!Pfsz-*C?bc#WpyY)=kR%hegz_7 zd>OX+Z@$KcnawuVXQ&>PF3v#Z-l>KkAho;he>{gnNPGZAK)SzakJklfL?38deZ9p* zRq}&8RLOE>?ci(GvhOsuB*|r5cR*7+Au>)zOyo)iB2f2nCO7|g0xx!{cqXR#Ht^H5 zS3j8l*{-pnfSnBiS03QYDO6+a)5pLr8Ij~6{nki0Cx?cz6*`#S;jsf8P^r}}gDtbJ z;_!D^HH;@+#5`Tg9F_V$28zGR#iR8K=#sI{P4xLrt#KDoKWgIew_0Q5@m`DKaS6e+ zZ&qXjT|C0fe5N`G0<(6pk*^>*KPsyE7#@#qt2nlZeH4fJqV#I(b{5#HYZzP#EjD)InE3LMepmc|o%5ify%6%usrd)^VZ9OCV+vWaGgnY2oPVcUc$dRmj{tf$s^ z+o8tJX}gkdI0%FMq}(xc8yf>G{oL%1Mv>KS->6YN%OLO{EdWo?s^T}YGBTp4t6b(Z zu263h2GMiFS*_pl;p`Re`h#kT{0W3OE!s5!-y^JfWbT8KhxYltvn>f5Em}8-bWDym zgq=w!(~E>Drm?hKzt@jJ$eYJav|P%;YFz8vJn;IJ?6_fH%m%io-hPZo(r>LA(?7~O zAWxJKq>NHqL$5FD*^M!vE;zk9Kq`1^WhfyamEB2EYWCzaxf(Un(%UaAi>m%RlC~9- z*9wrG(myock&bYu*Izp2&?>u|gU^rkceV0$cgNt3UF_!>88#>ZwPwv+v!fa(5>q zuwSk`n3*;H^iPERNpzXy=eF{O0rzmv0~vOtX=`8$Jr1Vde-0uc=BM9T;yhVv0Qd5) zLpjv=1rIQF%IvrR98;0PFYVkInW_#*f-P=%{whS^X{#7<46Prl2>FP#hojf?RQ;|X z&~_PGDHwS-9cl<8&fz~$dq_4PeU{LCanFl(2D-PKQqDrs@?D9)jfM{01c@O-6lJO6 z4fiYiQs=7g+r6`AZwHB(s|DYXV^^>2`|h~bd0WwuLW6Kz)A1RboRb)|LDi3$?y*li z$CNwo)QBQ-r#r+vSp~%Ga(tlI{qvcsh~bOwd&AHVNgr{KFST>0qsMuxQuBf^lZ5H{ ze~)cG7!rk&t*?3&Yct6sC=qg{L*pi{<|Wu|V7pe7r4f8f8XhE7z1ddk()aUl;&1N9 z*2fNR_eV*QPt764jPtq=GR>5wvnf71H1mhiPST#qA@oa9qi6rvVF5lN0zJ7iF-avs zn=p0Xf&Ja*MbtNYuc3rj+e;XOIP6JPl!(g2zn6e4*q5U$Cj(OI5ElRmIM>7r$Fp&23`zy{g|v@!f!6R1*xWRXF;Fa-Ea`bJIodX;86%k(fiG+}C+3<>0bn9@ zLldt9Z)I9#TkC8~)!?$5zH=`cUC=jY6&T7o!2TEoaS9ihLkd2=oK(U=gnb(bs^Tle z1XvDroB^cL)xMFFD{+d=1nVjKlYG7_%IAUx z`7NBH9$L17DvLKTn9Q#l8nPyhq^<8#-zk-0vYiN`ED$I`Spj3s%Us})zZq9s>7ye# z=M<|$agc^{b}<7ZBbN2GHlzrOWX|(8^#Q3jK2VOiE?Tkvqj9=EjWO8vCy|Kt9h!q`(93>kPKt2@C%5Y&qUJKk{|@;R{QLYr6hV zl6kQAI;=%&_)w@6v!}hY64sNafkrjJ7G;Dm`TdGaxG%0MUUerm(?%=t-R%`6a|O3DXmYR`W5A@j8U5cOHSo`(2i{a=YpBrl;Ksj1U6Ebg1y^Hiw>@H9rnwy>wr4- zdM&x#nWAi+ms;w1ekw_YCOc5gW0J#2!eb(;9ruj{fQ0Uw3iZRPDH3SBmi-G*d*R$s zDoda*&su`*OWCuvXo9NZBn(~L*$gNT61E3fvgy9&#GaN_bS(sLM&3ktH zMb1-+R+s$=c()-;j9(9&`hzy7s2Ry)>uqTboz8seibbLr4D}6rsRw0L(7(#pIGL^R zk6^-hA<|Wc`i<{)h3#NP$;6=+`INNk&GAhxYlziKO9sNxWzT9t)NbX>UVxj$-TCzy zEjv~Kr396^>I=?NZ`gC6HaW$c3z330V?AQ-YoL`JmlUSA;QR`>briCok;d(xKXJinnWjfCj>c9rre$GZ0SDBOu!TPsVIg0%Hef7;YJg> ze_Khg@0{3f*)*kb^xn&3O`C7I-m$E;lXWSF(<&0<9=Rh8g&mB^fm`gXH=B~s$QX*e zd%Ekm;!eq0?4oF$-Mo0kCeQ14I$S`W*Pb+z6f$+ViX&9U}x-APsaIp7kHIFaK=j{8uonu4bH9f&hECuJF{sn4h#HYM$_<`qSWsp)%r#@?5 zdTQ%nI2db_5;$NZ1p#7~+V;)ExZ7t1{+K zcZaC~2Y#|u(`Rzvky>uFiyh;i$9w!}TDl&W$v3}qPv`zr*%_d3NYf4dnC)3JOH%xK z+3cok$ReI6T6oj!PTDm?`um~e;=QjHW3FwP-Nho@FA6H26T^Yv~wxp-w^rk;+ za54fzzrl#RyLDZRrhq<9qL&t(6qp#$+`RM#+vNBp$hW@~XNcP217{7$T}ECE4ptH< zbblxr+>N4ITNp`E>xiBSu8?ruk2TB`oIg>aSKvVcK0Wb}p3v3)3m{ubLTXv5!_IDw zXk?c%mdHM}R#$o+zrdxluqyNb)D94m5fp_;n&zi04vSxaCriM^f8-XI!mU`{SFp%& z#>bu& zi7h6i1iph1Q5ykn;G$Cw2JRT(nb6N0Q;tIb1Euc2T6{eAp?;&0u#-dz{XHo`4Ux>b z)}cfFP1JeB3Yk;xIg8Q@kgGKHOZQ+o(pk_*&1({WR?d-eT~xqZ_Ox#RmH*EtU=i#m!g2fdtHrQ5R<7DLBvx9;dq6mX|smzc&|Xt zhuqAbl&~gH^?8pBdq~MGsmg0-Gle3X1dX%BtbCyW_BC~DiQ!Ny#+6i@z$fE3#u*YO zG&GUB{j2P2hCBu0eggk6gZN9j8|{HG)L8EXD3CN5S{NxdFZ;TZ#slaCMv9CkS%A!% zC-UKT&F>N-?S~A{d~wwAVVe%}%?(o5k|6Xq2<;R6mX_70wmt!t~0NKKiT~B2% zz4Dd^GHHxP19E*=mc%=B?6J8R<^qdf)l1dt>U@8`0Wf^!uBsgcXI+lmwjm!!5*%zi zY1!VinD`;#@lLN%l5Yk^;^)?UN4$*3-CHy;qZmxJ z*-`6`kBrxFlTNvq_c^kv^D3{-7 zxL4ZZ<`1l+t%9p>ND2*&hY{n;^8NCI;RRI;$8~~dyInMM}mS?p;+NuqS@O( z%A~HHG0W5tds_m3AC;{TTt_f%()d2fq=vF=>3ARiwJZ%&-mtSkxt|sjkQTZI_l_%K z#a50}?iVy+*?8Jr`*?>qp`Sr%oqI`1c&ieLbo0n&kR&ks(`CC_h z_=6b6<VZ|Ax`OI$2|6dF{i-F}p@* z{B<;%3O&9!yk7OT)W7E>;K|KsU>G`K73atAItb@efA6Jo7Isyt_&^DXw=YFuV2awN zFOEl=`NAN2l8ZV|v8B8;`M%@EBkx@=vfTMD@$rW4gmS|&fFGQGoyk$`xCFJZE7(JbI zJ_QYYccy&~)ZI<+0!#bEs=tC|wl6zic2FVsYZ&4Ee<~iYwqmxtZdc&eiOd}^xlvz2 zE68Ha2>Hg!NNj{3 zFi}D&(Q+m(!P;!wIpKt+KY$Sl+CMBrK;H&xy08nh5zhY(xsQ~=5`{46KQ}w_b#n(;k z0z*fOSw1n|VcO!Bwz~&{{af)KP!l;4^Yb}$n3GhZ_h6Y8ckA>O&SK%(1Qc7M2V3Fw zhikx>`v2qGL+JQWOaZCay%OiyhR0w49a3X7JarEX!epjYUL#}H^JnlM_W~Qw)cpDX z5@F%>YtFls0Fc-2?Ao-xwF+vOH-|1~fkf6Mc1!$;g%Gq1N#kkRF?}0F3}2fT&)p>N zttQ+#UA(XGwa4{}SH-_V&@s+Ja`J4XG&!E1B^?T$Je3drmCwqmUd6DT@&Ys?uHDEX z*@~D@&rJy8g#(V5oVm0J%izxDwOsaxIr-P(Vi3UcB>e%3!^oSg>g6`Q#0EU!GUd+U zd6XB7jo*B}z>ZxLkOu{te1Y~DNF9&;4HGUy;~X+a0qFYm5K0t`zq69PFr&rMhDOWDF2w8eTVEC23$H#EB;UG$?d1Y0#W@dL>Bb8=p*1cT>h( z&G8X3En82ng29P!c8F{K%hHf_r4YGDKMpn|F%AxLBAut8VE+k8GbXh>7pJh+xsT$! z`R}7c;G11=AjxM|Vn77Q>T;eqVU7_BuC4umoEywaf@dM){oA}=Y{V=Wmu-!!=WLjY z?48D)2Z&wO$`YvX{R`1iQ17Xx{u$m?-(2D6msV0VL-$p3kb3+RSL^Yl(%iPZhz2}< z_X^VG^N5YqgLcTVVJ)XI!*0NGyt3C^5BcA2oZ8sK3vDbY0buZ=Ob z?vJ1ZgX}4*uET3qi&3wxI2)|^+SS|V-A`@@heBf$}j87>R&=ZYYkVhu2EWTdKp)}v6w4DEDI}5rp9od<6 zS#fvH2~pnGQl8BNpai-=G1yuCk7xn!p-$>CLUsFNe zbX4H+H{&H!jwLbaGSdP#td(Gw#o_ba_6^L4dwwLLEO|YdSTs~l_0*h$FYOTPYnKw7 zk3^Ajg!lOFChy?=bjQMs^Lm?D)2RKadgG`S3BbjEJn%O@&FQax`+KT?x)XtuyC7MM zVspqPWbQlaoy9Z>3G}gq&rsCYo?uJHGoI?-lNkKqf{W>~Mbr2{gFe_u{!Ps3)?!;u zA%MXTT?a;WW>!T4g$f~W{?4yR)&t$jX#MGQGT)^8K6w?7QsE;F41M7h13GGDkRt%z zrQEb;rr|TS%OxL9(h14@u#auA_F|MgdkF91vE^;<->Rv)gq+_T*Mv>Ayg(GgotO!;wY>OD6kj80AQR#qZqc&NvTg4WfXLEUV_HOV z+L}y6fI5H5h{ehX$3nW>6qvIeMW<4P-E7z2*g=(u8cb(P_1DX`DN@TWNrEwk^BuDV zgw^T<>Adh)EFwYB{f~!`zX3G1EEpVczWF7w%|DHWiKton!sG4 z-eO5V>31%0jkBhv{`d-0D%jUGbGJ(&qGQb)7va2#a5}n zwlUtz;?B!dCw?YE)^u~^5~l+V(bY0gFoWEVTP?~UnJPZ^yLv{^olm{75?QxDy-xG_ z)8`SM$inYlJEZ9a%{^}RB`2gW$BBl*2 zz}%^Pc56$-7zVVGi@rLxq zY~=Ow4cqOo@5!};c{dZKfKhp8on+BeFukxuYg&!7rT@^98zO$%C$k}o^tEFclEEch3ExWb9j;4?%7 zhPAgPO-s{gKKzeTi`|OOG35+s>^x=-S}C5?2HlD-&t0%xv2zFc@X+t9$jtaP`;3&A z)z}oj3ifVQVBjzmqYl3rGmjCt_&hKJUZ_Q1F#RAz5+3+FIHP~>1fK)X14RQJVK^h` zwJg0P#UPuEs$|xN+(G=6mimoGl|ztGADK+3l6S#S+**6P=Q-lC3gQ&MhgSVK58)eL zbwMm)Fb`Wn$lF!wp5}H-*p;r}>^&sN=rq9mvl6Wd27yU%tefBPiZcn|;;GPb-^tZA z%haqK8tt6WC4s+j!Gu^^sh$RX`k;uQqXvyU3zM5??xVV8n6x0fws^^A7PI;p6HVaB zb`?LH@2!AODe^r|xJ7cm+02SQ73kxk?8Zlp3qAwG>yUz*r*%v7@HmmG-KD?})vN*8 zXM8o?mo&vr3=PWqk6bIE9I*qhUiK41y_4k*feR|$m(xpnfRo@jMy&_IxH{kf5BFEJ zkvWEWo}&jrGn(G~1H7EvYZWq~iG^}b=CL>VrVF=LDwBB0dax#a9|nhrwoNF?lQbfT zm;XI1AcOPUOgCFuweNr$(^aDAQC0}2VAAY#%aMXZxbDypqrrL89m8GKz7{bN=JTtT zUm5?P)r=p$doQ;sNiAl&ujHMS7`@m6AZ@57(oc8YEJ++8BzBe1N1*z0F>P8`&$W}0 zQ|W{fH5%z2xerWthR{MYSQ2@1bvlI&H?tTabcfQ$jHRKG>W(4u4eEc>blCi5k2}A0T@d7qWW!5DudoX}tAE z{OgWJH>GVP2;yYonv247FH3_9%RgGG*w`>_=-BhGr0!Fkj$A?L^LPe96oOb6vGWMG zV8tbwwSV)=&`Xx*CO9Y)>=0dS*pOT)i(N;zP?nkZCo&W~c4Y}jAkBNskJ4ZvRA<$v z7p9qSr5Blkc6|&{3^e4&Uu70$`ESSbiM;Mi#=I^bnvy3NE-fdAm6HD&%ZZDLgc^zF zPd%vsLf>{~uetX{Ki4%15?CF8xb|;%y{&RkgFk?Oa(N2oa{Z1%5S$K$Dba4+{13$O zO%*vX;Ts2kXt^VD1w{YaQEYFm8I>H>&`{x8t%8%79!7tYj(R`K)&nfvB?i3+`yW;bII*sDvX1sikdGUo9PIU7#>p}|b_X5Lc(Hx2N1Io`r z))gW}hp4fN5)Qg3LlBh{+d!yun|f23{fob};9IrT`lO>g4HO%K+O_y&2}zk2mRB{J zJi`!xIacsZR2l%7rb)N+e+e@WocHN+Q4x=J^$MCu`-kV^JKazQ!P~6P$IfR$!xJZ z<}wocG)|0R+0vKpUayIwjwQw+%$m;ukmt5(C?A%M_hP(&s`J~l7X9t7epbqp-sEQL z(I_Zoa4gwk%9U!N!Tqh2WUJENi3~srN!E5llT9s{%MP_v-TCQQ)QsKPK(Ld^I-qsq zU8?MTxr}3X)-S+xkDc)Y6;YfP8Nh$=C{hTPu$p5Gu9#O2Oj6&8m>!jCkl=hvKbs;8 zj`LAte5}YGi>CpFiX%jEmk55^Ay00S-uuPC^^1nFe`-&^I+w8FA+Nt5lXNhYtW!2B z)9bzFb^9v0^%)on$IwA?`@7lbsDPpwCMA0dq8wE`-+62ftehHXcugk)n%vr`ORbh6 zbEEY4Cn+OnMjC9&WuGBqTmw1BsWmR3tR_SGcM0b@&bRRvH^nGY|3`UJSYE`&#NEdO z5F?mMDKgs=RwDPPH1d*kFNbIjtw)jyxblYIsn+fDHh=VR6eqxj^jy7?=4UE{iGpZ< zj~9c#{8t^SQ0(5j_?u^!@NjL25*0+O)WQN>FC$Px*>9;eGGV8qfVbr2M)eCeNj){Z z@|zB_%=K7{eivhz(B8kX0nj!|IU-&E9Lhp{6GYQvdY~IauUa>V1uug*YD7o}1Yi&O zVZ=`2GFu4%q#P(;TVVoZwWcxFsrE>MehjLQWz<0^^hhn(<(FzPqSNp%DU=SDPUu?63cnkMrAHt*ji zDbg(xXKKD~A_(N}=kYBE&_cRgsO1uzSC!9$tT4M6{8rZ?P{8f4+w50GCkLUL=DwM| ze5)=*Ua@wOviyi4=NAHPE0Gjm)AUQ}rqd*FoWVzbi++mCDdsktbElV^<4D+1_Y8T( z?3Z_GuOPZJ*k}3-tZf!8X{Q=Yk$?f2G0Er8FBnCvKix|{Y*(W_z9<8Tu^Y z!=_bZ3>xqp@*7#vf~n0a{7_lzn$5(moC>R|G#OUx@1-H}*JD;*>ZQ$-<$BN7R643m z>RWhEd+wWA%oZ@3hxUot@PSnrqm@v>XN8&~w*w(T81<1Rjr?*^Ge`92>gVMBn&*jw z=}SkLCE0OeOrFh=O{_}gh+cxD+o}dRd-$ge%X{_=6&T%2tojmZiaEKgn)P#(pj~&L z37Cn;SwJo?5C2RA+s!7Qpd%2K?+fo>ec{@Y1ti}fvQifam0-F=rn>$Xlx3^?sPEN* z!#~>=vypA4^Q#Yv`X)r8Q?9d_*v>5wgaj!9vev<|cHq{o%1MyA9G}PiWH>uaK205E zLp|^iVr=pPnb)*@SHYcD3@yTRpneDO%IAt5(G={t2Ip59?|Gxxv++E~Fqh|HW0+C? z8j!Hl@k%sOO1zUiz3|wiAMSkO`*6iyX08cMXb5)B1VBaC6{lXg=EGr@HN?!QxQTDSV;PTrS`YD0dV2_39IFAn1lxXAn7F+jPIBFQ`V#dff|_Bls@Tz$ ztkjmYd({Z9oquE9gOdhu?0N>V*#_h((5N~B`nxeF00QTT1ySuhL1OnskY2R}e0L}d zEw`7@qiRk1^@u5(r|0^LWKNfoM?)yNRd}j%9L%@`$kzOd)h5+v=3v$BE!EsY!7Xa3 z)od%bjdC+ATVgZ&Vpt@;LjVQjnXY}X)KyZ7wLe^XofSm~ZTh{^*YY|}*lqJ0fZbar zEH3i%&Oe^0_KA?0e2bAXBfyn7PDP;&?$@=iT7#uV&b7XKb>CPg+mInbKZz$_RF_ny zFYxA|AS4*%yLG41d+^l=Vr0`TLm|Ky41D;>a9!2Qxc?rY!e+;@Iqj}uMW&K9J%Vldm=Cnn%|*1Z31KV4;gvqBTSH;&=v#v%oM1n z{VqAntw*S>5RSg1OT;VoU(JEJRB!+PI-Q0JFC}{tdWI)Y3yXir4porhZ%k1{j)d`_ z`hj&T5$(3tH$kcPAR&COw;_4y%E&>g&!rZ$Hgkqa4rcR)LnP zf6KUzER{rmJaeGP4V5Uyjw0z9z>}tL1@YM4A!qHg;Pmfg@p!%17gEwodM=x24~BS} zV0oG(%RL{B*uckZ{z8z%MsB5~iX&7lL)iP*N{!`hd8ki_b(sL%#K_4oOaLC?a^Bsy z(Gzd1t*8)$Sg?MO-IE4V;r5N;6hHYLF7g#7fb!M#A{{AVmJ0iJ3x z#mELQIImSduvI7V;C`L}YUdvbp1EhOy>)ReW1mAf7u%UCUo6BWc5m-J?)bpeM3a)u zI)CUPCmBUrCDf099~kHN@ePK|uTyN5ulL%QVKZL`?JAg$gI{)8%E^)l-R;ov-WC3= z=lRN&H@2@bR46Y-l+jzW?j!Fnt?|!|o_tTNEf$+(WjS?!rC2|ft(g?2a#& zMrbbeC^ttAyhIh-i%abWyupO_0^#-Sh=18A(fZ|{xKUKJb`J^ATEXM`L4-OAE$Q*7 zCYiUlxinjp8oYY=>tw^}7y>n(0`JA(htbDdG%7+VbTz zTF-vBwjp&P4v)?-?X-QBz{8*rj-#m5Y_IHX?68V-Ifw5Su0Om%+S$)dUYg_u!4&AN zceB>Bjl-%BzhDoGmL4g;L4u-BB;<<}H)bf5^U{?FmXG_vxDoK01(+akG z0IkT}5e$y&6R0|4eI$fJF?fn#plMCmg1`N5Xzg~A-m37(d7f#0-^_9z+nsk?eg!4X zilS76kyoR|7^S!ji1NfCOqvO`pAx6=37NVjOckH!_L0Q)b~t z6wJ%}g!p8up_&rB5C;;0a1$wl=~R$KJw{riw;N7B>;g#tQN}whg=D`!0fonxeVSME zpSs2OHAM9_`T*Cj4~_oPm^}+sydKr&w=?y^bJ7U6gJ6jm%hDa!v~p_;MxHfvj{Fee zDD*_R2!3UZ?_ijts44p4FWk9kGRd}Llwe6RH%6NZOoC3e>H^K! zuqtfY+O{}5$z_?bISU^)Q`%~Hy~v5+<_sU2+V{X+v1e(1Yls1u*@0qUO7^w1;<^9@ z(hRlP_P{m2@4iUT$>w>OTojkzfR2`6+n44~U3i^}Zaau+g-;yqufd*nfX z&F_*sdEr%<8+oTG3;>Vd_i$W+f$(W{nq!Vwx%ZJ9Q>;Fd#BEIz_g)h9uqWB{Ak(&^kt*O!kN4P2i zk6B;*JHg9u=HYWMXFIS%q4}xG7BSePVLg!fooH4D0iZ+iyl{exj20Q{A$<-LkdJR0 zm18y4-|hENl}jMkYssFAV-uAGdDOeWCdtzG6dYv|)8j}Jt2B+LFlv#GHnyl`RKJ8* z<{zLu0TE?2Oue;9FXD`cQZOBjh4SX||Kv)wDnbS@JnKqHlF$fsg`A~Xy61$T1$GSO zoMHq#_7k}5M9#8s)hB|n9iN*gWo8*qq{btkPqtPdXe zee&(#(Ae>jc0O%IlS){NeCG8f+iw~!gZJ3)`rv7`SKh0q-He1^bW=~1n`-rR)NlumR>_)b-q6gWF7t9J zq@VTihAbLJ9F&2#jR@!2!E=|)Ej80q$rjBEDmx0d(2Y6u{oQ2-CKk+T)!*S7&l#ND z;SpZT64lyUG*Afmt5O;#eV)K@+2q>VmC(sGS2(np3aIB9eHWIbGmL>o9!l)7lIIPm z(xsEoPCo;D-AqH}uCEI)kvAG?4I+RF+%Fs+Mfr>6tayef3;#uD^uqy_H|wS5ojug;>#ob*D(A@I z-yFg9*WPoO)}r21X7C6VCC>%K6eK#D>XEtw6p5f`+Ze9AmCO;o>Z^ zH@qpuo}z!v^^V}(Ox4MGF_M}bJ2eCfX94D%u#toj-ix_jX2S^0;vgv!br$j|8aNLSWpO(82Rz#|{;aVw6UTH{ z@6Pcd`193pRV9LQZR)T^ar3D=MI&Rvb>UkHEBRG0ns7lxF601$JS`VC1`OPuGQ$2@ zBfXqtm>%0p*XgVEf;aK2Uz>RvmWDd5WLR0gVuzmz@`8Wf$P4PM`rKRtZW z-8m$#RCn2eZSXwU#%`o>M5u7*Q30p-!PZ4FG(=?#cjHLM!4pr8hs?L@@mD&ZbDS(a zN_lmS%9_xw*Gh|!axl<`WJ|ZQ*|ZU(3Wq(me=n)PNO{`CUx`Bk&|X?30Z4G9f?j%~ z&nvd*pI`>Y6JANcLx<|iwE!-RHoGcEgGzF4MjCZW65V2dM;$@GHmM$~Y)Z=B8+y3O zx6@jX11M+r)>)UmzDxN_NJRlLdxPDbZV&;>nsrUd($)YPr9_)4Eq7>gSCWKUpw0%j zy?zUy48Mo-bUTkR3C5)QW)5AOs_;`^74%e-i%=>k50GwVA?TGEHwsbH@W~ux4m_mcE zw_%|dvUI{uoURA^@@nSNKbECh`}E6e_$=A|#Fl>q>C$f)u<{YXg?dtXY%tNoZfe&} zz%|^((c)_h}tih=Af|uZ{?`6dTRLuakQlFY6p5-#ri9M{q^&mF@tGAKHbjJVIVnd%) z!88fc`uL)O*|L)7h>VOW!JRb-H?zR>veIR%w7u9*33y;}4Jg zE>ql?Y_oRxROUtl$k#T#O7kK3$8r%a-mL>ThZEBej?SM$CBXK(UsXcdMRZy~448$Eu)W>!)o=Tb_l z;}B_3*$Gu1c0WSiViqKFjkGJ+cn-!fpuMP1J8~tAvqQ96(6^koqh8Q-pL_$(#N1sB z3NmeSLU^B&0U+?a8iIldi>ReGLwxf$DyJGdP5b98=l8zqv^$Std^2=|6t6C)eP`Wj zHM}x#9?a?+mM1#e$Yy!V0gqti`jc`;$ThzG*t%*z5pt2n)=O6jz4n2Hr{miYX?QO( z9Cw)U_D3lvyt@>;)afP%QhM#r?j`o_Ba2No*6yFazK+Xu_HzXm{DB1n^X?K{U9BMy z;|6;daMjMZH9bIo??L;A`HlYB_miI^$^vBW4Z1;S_Gn}k7x?34`KlCjX_l8T;m`5S zY5sS;>90cy`NE2us)K5pd4`Fvr7h(HA#R-qyJTioc!82nAhzW(L)e6q=6(N8>M?$& zz$iB+ynrdrz%lkeWNG`=0&$KF8h?NE`SeB4QZKGg0`RfFV&jUY+9 z-N_VOX5H(RjCLnKHCuL3rQV>)Sg1BI47=@iBi)nN5^$}S z3n{Ea+lLrek|K;2w`gk`=8G%L^pv11bQe2{a7eW&G`b^G(1b}4p4bwE*7=Q`vQIL- zm)7@4C`oJJ^0pX+nLDZ3;#uLJ(n5F@WZWWe9NQ9y1jZ6pX0EzU-R)%S?kn*DJrPG4 z7>?(}GgdX(kgUEb{UqjKjT1i=c^{v@Y2A_4NLuzzHp zZ2aJ0>({7cZox*s!Y9s1FNVA1=6ICOD-XE6VgvyD7N$rHPh%{UZk9}E<7v+r%w`cS zZ-kiht)KQ2Q>nR6Pir^tyE}#9r^AQDuf_kj2j&|Lj%*o2yYWr;^S6)ZPWU@r&t*x82FraCK5G!Y!I;{mQ+W&Ma?ejz~V2 z5PyG+?D?XPIjI+$Ka`$SDhg0Oiw*qh9(WQP+5h6%)e4A}vpgHuDdeOy`;eDhc$OHK zYY^}#KU6nYtZ3xswIKf&S#GTvc&!P%ppQ;Zg1+c(MyM!;fv)wE!5n>ul)eJrTQMN+ z9Hmq`A~tNR}E{+mE-!@1Mn1}fqj5?ZZU2YROo)LWTM9fVDA6KN&9{vDb? z^T*Xmj|=x2ZKBI=Np^+>lb)C$jeHfJ8^h<2HE8K&6t1_`=zOy z&H_dLq2xU=ZwyfPGnJE!f2;Md+v2%A1z)>D_3JzVRe-NExhL}VmsZO^^KiC*L{-vmgS_P@JHhRq4`j2HNT zi$rY!v1Wuac*Ta*J=;o=cr*_Ut9*<5?eVh^2r1t>c!##j4*A=V*+dSI=h1AFypaHT6h_c*uhg3NU zRdl~hOscAxov>zy3REs$hz?HaZeEcv2@*f8W|GA;Jw7FIkx@;=x%qiQ*8_g!K$m+D zBP89KN2Hc9EepU%CQ!}S*xb(fbur=Kx!39;mvYNn6bfMA7WNv49qY^owA(HuY5Qs$ z&t~S*m6b&SPQN30C!OtZTtAy*&OccyLV4{(mPvr5>qZ!@nO6>P`T_aA|8__=d>18$ z6J3R|@;9Gm?Xm-(os)puUgG4Ca!dik>Qq)u^EsMVMVp zfOpBmNfrimMG~*x5@@(_FC+K$O+@)A*Twn6a3DwHGtsNto!5TO78um+s-28Q&)MGt zjL{R6=1!V&d@UGBkr>3bxW`+<19FN*M)$2n3(VQwhAwo`RJm#AbwM+IuUdksPS^XDKP12Zbr5 z{yb(=N)H$MDvcM3s;01(-RSJkW-Ax2b7X-UuI2ANr-eX8HQd0 z@t*JdU~)Nd5xtz#xz|M4kIFmy5QuC9(vtq;Nb5ESxymXBgex=5s(>``Nt!Y}Z8alj z>)j7j)GRnSG$~lLKjdgbws`rLsA;AWV9TpZQ7%z!N_2J%9ShWC`q`7$tPKRAuL$m} zUS=B7gBp=vh$ET#*UW8@Miq0~;61C-ky9|fS^#5QNyd19YFCpd<^rCOw5|n^dE?L{g^Bm%qKF1^op0yj#FADB z<848r1hs{px|3#9B?&9dkXMJSQ9Bc=tceA$=-=h{#OqIXLUCF<+Ym1L1!}0X#3P+= zKXp`uQ)5Y3FCxk$uX%5rG$XrcpUguDN_0Kit$F6ClTUr3c82)iR#8@_UZ;Uhs zBmQq?oP#I)eh9B1PuQ_0PcBgk;<}hY0}Y-lN9u+wdMLC)?PdL{N#!(PB!ZIuXbi(v z%YMZ=*bz}AO%)k&9KfzO8}jVwulA(yO2JY;h6Aj6kTOs z$_jAg?+%*Q@P>zidl>(!)<^nACgG~sKH+m}&7Tc-K@>2o{ATB@sy*hj$qQAgp|ZI* zKF#i(>C)jhO04QZLU^AW1mP(*iOt6ZIh&Ru%JJGV8Z_m(gbqWi2wyeIq%DjEMMs0Z zskC;`D09dItG7B7O6vC?dB({!O6dg@Lq$+JiPcHV61qL<#n%*%+5bq#P!fpZH zT4ZStd~IB+1i3102@-WGqiNXVL_{cKx{GE-h$|Jt|~<#cZpX%5+sT{2nl;r>iVFY@a^xT?5tOF^Fp;e8f0>0y~(Yh^Uh5NcpV0)G=5|lA1|=?F|${yf4`q zfh^rbYP;FbSh5Zt22pjI5|P;!Vva+{RjRrad<2hPU1M?`pRb2-LQ&6@{3boFdh*#h zJsW^O;{S`Wbf1#32LUYkf5m3$lqnA9ERj1%nrvBA+fqE_yD|i8W)tRV zQ6To!bZbesWnRhOj-wx?6eUChpT3_1d{axtj6Q_T1?esY-?FZB7?|2hvVvShJyM1F zO>r>fpXLimO*@xQx;=KlkLVH0`Lu5}Jq{;MF<;0Ktqe0;&bFXzI>pSCi?PYMEy@r! z>~KJWTqE7bDsjFrE-arx!6hV87b^Ryq;+-glPP&84G{K0Miw(e!>E@d#A*$b_iYEqy!kY&>^PrW}RlzN&HT!ddfn`MOi@aCm7mA{G7O|Ubv1F3nC2s)V8Lu|iIFs1^hqP%Rn;<@8ScOGAhzbg zcpb1OtT4tQ4bbkL?4+GwMpw~Id5RX%F*8S{b~V1u6>V0koYgF#O$ohq?||X(4p5J1 z4XfO_1pBYZEd;?^5yFJ4@5)h>$d^+kv+-{_z~-dyB~@y#1K7@T{!MwTC=IOPJ@qm@ zyw3A})K)lw3#-A3JI|kuHtjPX>od@wcm?Cw3lqXDsI?C#CmX(DM z8_Fn&tut}nK!ukl9WY*%p4zTZfZi)r*XmZl9K<10u`&no@A4wYdyNS!K` z?!z52mA@+Mi-~r}DKN^X5k-fw+)%qIRSoMa&jXW@)`D~WL}%v&#L7-RB!$8>wayAb zYB3^-#ot{ZIp^!btarOeN8X9einr{TczwOR$N$~Sagl!d5Q9O9EHh}LtXz))AiO9M zHcRZQ@J#bu7fKG}HkKj+bdez<$Z#6lt;(9^C;Y_d%vSgIS&`NvA!4TiTC7eb>Uw%fZRBkO%kS5gh!}Ep^t$~Yhc@t$=F``!Vf7=Ga4`d&1C5wKrIpO^ z+RH$pp;;?=ZI%%y?no?D$nfEOg0e~FDkfAT@zL{~41r~s(?ycK4s<%Zi@>bat7G0n z>pcM>l`6e>mMh;todVd`V7_8f=)XO@``-+aYT$IK(@cRYw$Vq(?17XmhnH5Fj%uQ| z1~8oA0cThyPp(JjyYNZ+K`8G9E(dT^uqGWF^bxs!lOa(AXad-1Ll|MBv$oHl>1h!l3?P-%z5EI zFi``x93{Ae$AVWFQ_`;<#+{0Lb=JC4SvOH71mh{oT}*>s`*-%gQ?9V&%G|*Eajx9j zfwCQ@h*Km(1cn>Oz)6i-KFvnT{tm8SHoygS&nLxRv-V~b6LXF39Lpl|j(`|x02Ced zh8!Bi_AHY^Yj*8i7VX|8YiwUn?5G1aWe>)HFW5g`@kI?HnU~!6*>FPcsbhU$DCOXS z1A^YipKze;$x@%iX$!>K({2pHCnf%(kQJunR63PU8ScQ&OBjsO3)eHH+l=|7qK`8s z8NtuJhg@hOR7Bg5BFd(TSRa({CCqmBlE{8DofEhf(x4}gNZUfPW(oLUctQ-4e*x#uWZ3X-};co$2@0eMYFJ&73U zs$?e$aQ&W^$x>;z8R+Gx5bAaoLV*fAyw7^BW9%Y-@9x6|Cz+ zn#*$WG@nhdy&&`!*e8Z};cm5d&uMx<=5ys*N}8bZtlkaZUp=N~yGaI`6t4{Xb;Gqf ztmJeH)NfDm$7BC@R?1=vPfOI{#s7k!(X1-ibDviP5i+hp5vr{Yk2ewXz41uci!=$d zUap6?Yeg281vQQB(OtFvI{LhR8m}%atbDzAw;;t<>9shYXN|AMNx3jJW)EtQe#jJ~ zfuiSbYNY?9YC2#ijvCuP)c^W43WSYj?62DUHT_TwB(#`e1Pp*m;A}_mKl>FBGLw;A zds#b86{rB4a<4j}?B&Z)|HQNVjcD9Zo+uWLSsecSYWqa4-fhk>>X*97L2$Z~FilPA z_e1SJIZQvU5Y*+M$m{m${IJW;S`x+90`v17bi3(_R8$qTFw;AaAAbUndc-u>$!+J? zg!|_*=^|~K9&Xt&rOfvwGWY5;{aU?Wjsy~DSeT&v_CBO(f~-;;kbhJ)A*Hz!ib6D3 zB3rFkkm@{sR+4LLy*Wz-x8?k}X{C!tkaTU05ZiVVn{D3Yngw&)@9oq^+H7wNsXPt2 zr}5`D2if*^Ny4L&SK`o*>MHE>MGG&Kh;Xa0us%H&x7Ta<1qqdSoV>VZcmL>@eO;#v z=z0!7LvU0A%!|fiC(^NxV%(vbb?<@4ci$S?p?#}^$cI=Bg-+R}VoAIqfe*5AfbwF@ z+cAF77eB~M_@gZxVh}HtRt1s!n3%ItDWhjt zw%cAjc0{=O+M5DIL(fGJUn|XzP4TET3W5{oS06yRd`F^sel0sX&@4FTeTp;h;wCR# z%bkn@(d$jP@K&=&PX-Vlev_md(2hb3dx_gq8Jc@yim-hxgxacoSeK^7RnGp^6h5fw zxTsGy5!O&cj?aMJP`j0q`1SSxw#8eO&E@1q(>o@bbebSu`^(u#F%(+PV$1yRM0D!7 zbuWl}E>XDEuy<#PP?6-}JwMf)^(qb={u~lAziC>lGW;^Vin4L(VxFJ~jIS;z5e5g1 zAb*7K6-#BC=jLquvYz3AMW1a^kEJZ+N$ZKysDeTd<6!m*f1H=B(zPn8A7)a6r?f9B zbzFJMytUL?>=YP75~%1&Gi}eqT}t7H(RVhEJkR|74^OJ_cm^~lDx{W8Mkxu;$oOSK zwV3pt25%LY*sBFJ0I1G90UJw{v~&^0m*|Xw7`h&@WprTucQ?xrAGChdP&#i|olE6~ z;*YK>qpaE0Z6fifywM+2(@+ zjZh`EeEF>juDX6}eKs6=68Sm3aI_|d`{uz5m67KVdggVpM!?)etXXr$kj}PI>Fj-? z5z^}UpC}>*Zqs!Dco;*w)~)FU4qbUx#B~gZS}6e&zkIF$+!V&@`CM!>!7rt96%Ase zUOmJOA9SiQt2vGsHkR;JTX;Bl6l}H=`BR=N%;Dxq0&D8ZOCC9s-^p}I69_2iPT8C2 zRWzw4Zqt=K2{ho5?b8fa>)bV+5;Fh{7Qmgrx_8Fb>)@4j+cqKu2i^SL!izl3W1Tr9 z5cf<2S}H%r%3liP2JOJH!u2$2l=bmizx}sNxLI%9omliDSo@Y*+XnFzx#a?v3p&+T zOqKGY@ftUbC?bfA7JX9nd1Xg5>%f!I*L*}{(dlC8pqs@MdP3~|4$pO)Woa|2iogM7N*M9qJ)m}XuH0`Nwo zA^-KwDjom_jCGi;%9KzEwadiaeTJ;&gLw}&gh}PI$UNDuYj-;14=8GxM0Fjw?Hg(l zknRPSMOr}K>6R#7S#-S52+etAB}-Syr2!A<`ag92#+=gbkBYyY-7(F5UcS_JV<#<> zIqF)#4hp_%j%g9;q+u$vTpwk{#7FdH_03;1@T)%f`@tXV_f1~`_Y|V#{6i)s{KceL z?78X;JvqmW<$7Dv!lT$7OGcP^iIJQ{_s10zLoYT>K2U`#A)F=cEz;*ax&&P~N!y9_ zt_V~NUkcC&54!sBWT80SmANzxXnF(hBcfuKa)E>9?MtSJK}Wq$UGp=foUQYs0P5AO zbXMnmZKElDBByNQZ5%Bk!-w=vGTu(0=|IT5VHx-pOdE&Iw?`@32>S^5736w@U$^s% zVzv(RKJ1yHg34=UXLww;AjnF zPs(Q(({b~EcH1ycbG?D6ih{uGYrMnr^(z%#(0CJ8g8uob=-YXBES`WXvG57UCcaQU zZX-p_R(M;29i0_ynMGlzmc`xNxW2uSEehKpiCqLx4OqIayNp)Sf}cl#egX}IC!kaI z7HQo3m+FULdf(46ZAGh=_;XH5Sc|B_Kydfkhn$|3)cMm$2HbrF+Whux618Dt2h}IN zqmBb`GT~}XWSBZd$?L#7&3H%XI0PuKH(J;b&eHO%{v)pqBOHPDs3~5}w9>unoVjf4yY|VE-UD@%L8G&AMgY{uoGjv*m$H0%=Y{CoCZ?J>&uFb}r zq7Swx!bJ0%#TIplgnJDR*&#AMg~(lhr=IFBYi2CU&-+I8rB3u?{=*bs zH*E8*@fbq#R3U4}$LXHPgf6(U>9~h>`r(L8mS-U#*Ws6ngXB1YzMNbbY$T zP~S=olDYEaRf;PQ>7#YKG9L3%VYovb(3}G`F^|RAa-l0~A}i zpAfEq3GzP9ztKg@Y+6_k5JS5I_$~~PfqOEr+ zgXH9moa8d4vX3-uH!W^9FLL+|WH^q4jDe)EAO~9ZkY!08PKgL24bKZbi23nk52?fG zy0T{*s%xyfs|LBPtCJuKX83SD+|cwaERo z@R-=G=I8ka3;#y8de~E!J(dxijQ7(Fgf4i+ze05+8H(!ICXLCoyhRGks^$%}xW$g~eB~p8w+4qja z^*%al{mSu3m``O@Wpt?SfoTj&@5Z^AVo|%-W&&)n28(Crl~&Z z%j!aqk$yylt`y1X&Mc4p317zK7>ut0p<%fSM7Z~JzD=w9IPwzJ&4++vEp9A&j=o&X z2&yX+Mn!Wq4_4+G%e2a-7o+5QkvNFpf|7w=RaNRzBzT$K-pqJA zEOzx~!uk+T%YDz7HLC_Lc`iQ<-GT4N8|C5`l`ymfeUt3b2J06;PhYcvUoY96YFpf) z9^}Nmw&S0rY#OZvo|e0l?#IY_s^rrl?;D#qd*O}gQ4wMHu=Up*s8n=p#w9X4_P&48=#c=IFf~=-`Re4bwPGe9s*MxD#FD2uYET|sa9cJ#3Q)~v&MZv<_1>pJVk}44XP0Xe1#HO8@TPK7vU&iN`cRl zLLg(!x@EbYUju;pGcjHGoBS8~w+hGeh#h>c45iVGm}sE_mTLH`SD5iVp7l|TV-6X8 z&_Q!vn&;xrii54?xKF6{MW)d)8fh;C=?W!Mp!hV$QbS2`=G-i{m2xhwmGtT>z#JuQ z%8I&DfkxE--IH@AVV%?@1Hf8MH|Isq6W_ol4P~3v@5-6CCqe2?>=DuKL7-lYc((8i z2097w_)4wKF(?%25q==s1i~}-BeTyW;n9v+Pu`_{E5twl3qR>rA@kPTt94S0^7i{8 zN1TkOo(0X1`((eCoOJX7;B`CyP`8=*D{E0@$e#HX8L7gjScnZuAnBfVh$CO4H+ma) zo6~evqx39GNLAWLIG-I95%~$uCDXXV$HFWq;K$w9L2e4AuV_vOWV022WV#7U-Gw0t z?~b;1L5V2%T$zj4oB^7PUlc4-!Wo3*SV;lY#1JbG4Te7)XFZ3%=OZ=jVXK1ToL_b< zwvZq;j|!sISi>wxn7H8+^DE+vNtj?**R&`so>Vbmc%-5JjM3&Nd;m`Jd&B9N(xk62 z(7`xINT_WZHn4xPQmV$nTbuS;0VL=}njJIO^Qg{UtntvS5ZpmJ)XAk$u#Ffc5t<3t-- z8#5kh@n|6&&Xq7{mU~xaHHmWjYOD#sxaCd zBCeQ!2i3`rq!LGWn`E7VK%YRN(FZo4c=i{yW@5M%*ed7F-k-eq3m>rNgOvelOtt_}spxXiu>^_<{aI+7LhXO)OD_J=p|YCHmwzt6sZ zj)VcgQ^8N^0YqX1Ym}3uKIak6C6X!3ul4UI0N(M*!2g;-()3qV{H9jY&t`M^ZT(Qn zCECer@SXoe1P4AmMvOes6?m7Hl7EyPxGR~QiQH4zK@%B5Q3JRk2CFyevfc4a5ue8Y zw1N&}dvV6}OF3@!j&x1Az9XEJfbcV0;Z7y$WkIwn`TaI>j30+|H>%XlZZZd2A1t9x z=P~Kn=j^=3V*w)vS7Y!+%OIv2H`qs{%(#G#Ji}|=8Ae&GLQVvH#oq~7n2#@5;@Q71 zfXDIEo|Trou_8z62^JcZ^`WCd(QyWHGoJ*L9dhw|v~{FhPLKJ3KY~`I^zXy@a}c+1Pn!`& zJbpREcCvMm;m-d1%mMS#*-%T0_~oY|lX9}|UFgO{Wfl(c*=6$QJ;9s*V>KjJo+Nua z*Z;lK=?RVmh%U>4z_BBNm)mGBf1^%$DhH`|WgYHl6J9t#a4%TtWW&f1@Ygjf-WJlL>l1!L;hcDmz9QwGhrM$43Xx;5qbKJl#I0D5K=q*)%djucLeO zcQg7|E!Y)H$B@!^Okmd0DP@0y{bgvoz);45BMcV+pGoTz5-i{<e%E42TQJD(@Bs#-MyEa;pbLnb{HpC)if z&g5zyKBx|RZc?fS&>mW`wD=Wi?r$2xgBt}jy~Iqis+)O)F_SWN);F1`z@Goxj!`!# zyPHQ_#!3qiJ1XJYZ{Ggw;W7fp0kJc5*DnS`5mGR`boyWaJ-P-7H4tJq(H?B{g4!Uc z2qPl$AxZnXC`qQMeK34h2f~0>zMVH&YfGaj-B_a)8hknKVU3Gz>mYz_lF^{tx{Mg@ zzvK^z7CanXKw#!8Fl(ZqVq;bPAmlM&#novJ1xQrT`$?IBaXA&NaK(p>!+W8W!wpE) zXqgbXm-R)WN-CpkCs}Ob%2DE>lOB4u;yxu-H{={<71TGH6u>_N*?O+MojN$*@?sR> z`55DhJlvKIRUDy-i4j*idefI=Q6!aRt5X833jql6>KkF@kw74c7`RG04z}Wof!{2U zQ;O;FlAcO8ne(CO?Ms`ncK;`@(($dcE5A%m^=$Z8U;Mlg9mSBIgO}gf1of%O<_xwc8n@cNh9LC! zp;FEf_TvMRG;#;lqzzR1F(gWV_o$ZiGXHL|hT_kf{uu3zq58|)s4HVG(+RBeV)&{0 zcZs$@(sNLO!ymwmP#8SN9bEA!Jq)QfF;=y=nmKHsrME+lp-mCah#lZlG-nt28`?J; z(2RNG!-@HPeF-Z7Z(-c1QS7MbSN*}P)Q0;T$*1i+9Tf>_60LZ$H^U6%3rkb)K)VOeq@o( zC#(t=#Ayp$`)N~hoTK%W$J?&t5`^Z_Yxi_epp9@Q_(3C8Md}owZHF%AjZIyo8FtI=0P{KbA0?X>L5ULqy%Unx%Urz~9eE3LCbK!$`U>5cI?mW9Fk4AVI| zmHzlSm!S?=kkmH*iKrScCQeWF2j9|Asb4{}AXc7(WCij}O=lvis-HiF{<%e5cA5_j zXijgdD34T~rmYt>_bOyydAmJ1dDQ>f16*nE#G^cKLU`cwc;1P?`xr~W$#=xwnjmF# zMzh^zo}HfxKL$g$3P)ro?+>25gc&`-fy3Rzy#;y&Q}*b0_3A@p`C%tLPZNtzLn30V z3d#D8$*p5oHM;C0X>r47WxGS7;Esv)Cg*hR16QVeEf9G=T)xFPw!h=$BN9rCv2fym!7kDNXJ0_YIUQo8dSRfmA~ z1+qI3k{6VUFO%L8?=5kQ6H^lLfwbovieBzvD59Mb%t1zceWl29lVU6JKca4MjUNW- z3DUac3NELrZFgaxdDz{@K+YFuzefo3c2<@+Cu_{B71eMi7H#+r-Q`^OMFoeCWyysK zXqTP4)U8crVdH=C2DXE)|w^=s$QXr{zWHf5NsUs1FeYCrxVM+u4%FY4}-iL zj64<@=`Q{kc`*B6Q^xK-Fe%U`ApgOr)ME)Nf?lW{8Gf;sYqU14a??3kenKma@bb8S zr>|tuv=R@0+*mjsq!%%upm>K8*}{Y=z@ZfR>&b+SCbmF%F3yvvH@N~SN9-nkrQh|+ zbvCOuVx?DITUcIic%!Z|Stf$8*}ec$+?x)uBYrX3kMi8zM27X z{Hu)BnnVm&k>{1g5)Cv4qEuJNA@6!DnLy783-csxsy}kA4&8;0jKZH8J!E>uhNDJ% zJSvla8A|eyQarlk&lp={lM3#tNZok{2MTT3@cq)AM&9=v=D%RtjPZstr<}B{-Owh# zDC>?im2mFZyja|Of#EqCU{*hFN zc^zA1I!AZf?kA4ePk-Z}a)_u6;1=S@*aJG+qJk2Npemg|&KDho>_C-LgAd*YBOKYY z9{l22tHOGpK0_31Kg&T!gsdaUq~K(r2mGZxr?p{#?$pPsC@9_?$haLl(-k=nh#tkTD5Uz;qUkv7(+_`BmKD z1PX}R;k6)akpA7@p1xS`C{Ww?2kJY+=Ni*M>7+_cfcXgp#mt1^zRM5#mtv zpD-YzRM*E+{s;vd>Jk`Ms7<6FW%pR_9OE>xY%#OGj|^bDv8@jLVr-5W7zO*P9;xU53kfjy5Gz3pr*7*t)ut~A-&4rO;B}uoPO^XTYSRcz?xYaGL^XD|O zNlD@%5z@FvRzSRMg|1Ew6|Y_t(SZkT8nLe^*R?$SV2ai3kWmmTdKhpC3ot5Rsyla- z{~2KWl|ndXH|r)74H5oKtz%;1Np!@!sncsWehT6zm$H zPSQwZsH&sK3jX+bS=?+e7bA6W!`uoazV-3u#{~sM$6?_vn9pjLhwm8n@P1l59xS@-p0thF){tmBDh5uY|~< z3HShX2-y8U(LL5g45C9FwnNjevpYkZ$2P(IDnIbt0;2tw)a&^Hmnq6O9Uc|G#4^^5 z)*Eel`ZTqFn^O-ENAv!Dj7}lu@ks-2Krpo125aY{PuMua#BeS72C~IuVPRZb!-d0U zy8uAAEVfRHUDv!k$&#Y4OyhGs_-nh)`IHMMZ#(}PWeR$F7bIhDc4bd&pbzZ^Mf}?iWiX)5+YsY9n0SdhHw~eqe6dnZ}B`FXTZ< zh*qOD@vxZ%E36T)M|B&{n#{S%e1Sz1qaYs)N`-&C&xF{Wj}EH(0JoAq+eo| zH>DrufIzc{CO7CC=LI+Op9k>WZBbK#d)exMF&ymF(!;AkUv6I8%>ET08OUV~)X)R2v&U;tGYV+lc{@G?!LbK85fo%e8%cMxC zxV?$RRP(w}rTwTlJ}VpeGZlKJN?rw2vYq9m#>lSCaH2&03#jAG8>&8zND_!X3Xm*C z@VmoPoHGTBd6T%A@8Hox1u%WLz@` zYCs1k$p7t_QZHK6L!QyB`bTQ{DCJmUDOSr$83&2e(ymW%p^@^Q(no;avRHHJ@7ZX6 zF=g(tYkQeYhr=7y9a{->|I-(TYz)SC>t$_H=|b2%+2d^_>U`e|ui__?bnf!ZP>&%Q zuRK{BOH2?A%hJw1h?4JQNH7Is&oK0(S0P5rpnjzbie!$rA^$WW%iC3^V=~ zkQK)155y^H@~Zp@x3*v~l$uEM-T3(~^={4-Am;N#{@&GRwUa?XeN{CHuu9C@6klpMvp}}N5F@0x z!Mv>LMyo{6yhmtXMc>b1_m1mOO>LDMPXjb?BZp^Z;-j`=bJFi*ZQ>3)A`rY{N=B6{ za7UTLLj1;2!wn8OtFH@5Su}D#`)Jwg7C*D0CliHqr%zhwhYNr$kp)-P4mlX?u!Tsz zzq(p@PuXzY(X+*lLts7KkXUx0gZtbg?LMGlu#r~Ktk>7Yf!NT2nHIH=d7nN$3+7DL zf$V;@s|R+iFpa;F4n&PyMS*vAgRG@s~P-dO(f zp}iHXACgqfcbi-3@|JoCVg>v@?ICUYIi@{^)Oqx4v*HfN7h zA5G3U%d-Orz_6u|p5_a%e_$BhfuCZ&?tM0!QJuXM7>Ca5%9}z4jXTrF;p>vLF_tl) ze^0e$tWmR6^%bTqoO5~^d{ZboM<0P8XPgtDo#YX~hDN@3%h4!|9>(S9hZy~4VSDfc z0dap|osSW)bJB6QthWa5XI5E@8vkOgLZsW@pi1Rc{}DV3C=70=IR7E|?2fYjGpqC& za5S6V2}h$BFJd{<0Jmurl5AqVjA311j||J9Yu$*qWgGKWj7g_0`SJD26YBiHTr=up`tc8)`yaMr~}Yc0`>u5&D9RAPCi{zCMn zSNEBE;8i?u?tsDPIz*Cob@q?HHWzZynq+~sjz$H;{CZ`{80j27@P_wmM8opUs8YnL zVJ@jSRTD+Z_g%XTU>&m<7f;l*TZA_6D{~QMr>V8}iN7Z)KWr0#^z^Pw_u5l4{e%F0 zf92Rm_<0)@o0L5dgTI_PYAN#A8RfM2qwJ$;cYw&AP4Z4?|MtWfQTIG}RKYP9=lW11K zqqU;+{$5XB%1+TfHtjp<<#w%6UxZjqLVRukv=1ydbZSS%;YLS%c8mkqaRFF2>3Kku^wljC9^lEzbu$GYu z`?qDB)z{YNxBwlMonzX4U$wD-46}o7BE@a}!CS;+0N_s9ffc-C11*G5crVAOr?d*?`S1{t08g{414lSct;^9pg$4kGUDpP{0Kt zk_uFKY0?R7W^-h@x;DO(zpq6@2k4zFj3GQSLCnJI`V>(E!5lMdyKxNCe;vM2u=}{~ z14!bZ)O52d1v>-eMfCh~+O3hNy2kh2DnKz=E84pSvU;fN^1CprLN44xol3o>!}I?+z3g?v3*-`}|y-xjVA4(g42} zfzq$CYmeOI;1#9)b|7s8z>OWQyNrL^8)bT&&39zE6uF$%&xaQiSkw$bzWWd6>$tY8M~4T;R#$42UUhvEb$(NF=)z zwRrOBheuVaMWU5;D?asd@4}|0qy?2H;+2NACOi80Eiltf00eqaN&28@hDSk!Zq4kVxe_@G}Eh|E`b{v?W`@;veL%j$@LKs=I7a4QS7L z@_j#W9pR`xCbeu}9R!WW$ zqkP{dNyR1@zxOFBg`Cr736PnagL}b#mXX_xi>s2jj03~8`H144ULA&ly-Rl2VqSu& zz$1SlCYlr#Y(sH2YiV|0VOy8PKJ}~R4pbrpcI@Ck%x{GQd-~QuEPF_Osoj*gvz5 zP_ivigLlUGrLNs?~MG~w}xohk!2Kh8*f;GN=A+EC;l-rhsh|9%hnwot6Y z0T30<^OV~YWu$}`&uS%(@$vZt)*a)u;MhzQ9(E4EnCsWp6)3g*h#YA{IfweAiJqQX zv-cl8PAX)0e9B~ZteGFjTs#Z_qGEI}4V14?ZtbhU56X8T$uqRj&#)!vprn^=rf14w zg@h{Sxy5Gd^8xnZTQ!58=}4N~i>(Y?XOB{sB6ZA_Airde_~Sq4r4D>oyfPN7*e=X`A89AYrDBk?(!lHY6rSgCwi%3 zKudJjR8A>lColZk=&r7(=gPbw{`IFSkzbrw; zi;Zbc=>Z&Ky9~?1f!ICg0s3_BH8om|yw7ifdCqCP$2y&mJ}?Y4c`2}Jh;;bHk1n+u zFMxz)NZSiD0%c!?cLdafKz8B0`C(v2-Kk>e;CwxGY(#YN6iPT_aigPrP3IFoMR^LZ z+Mfp87AEO{tz&fYA+Z_O_B2s6?bkMm7wWN@`AHaCi!*x!>6Hr-8OQ&*I{SYW=V}9C zY6D$guh8LB1BK4Z8$WJth>$pq-*TCOkb0frm^Sa_USL4b@>1w`bS6QvuRdKkj3r$m zT62QeDDCyEDxr}ErCafc!u)`ynt}1D*u@`z%An#pBK?!?i;Q@ClEwUGQTooLCXqlP_UlBlH}{AqK1SuxQc^S*u*!tK=&U}aLb2zWk%w^YohvMnfd+t zCkmXo3)H_;7+JNw^Gy0?A+e!oU4eHx(=6J$iLKg_1vfrbwuh&g`~ZgJE}2AN_trs6 z`WLl2dVTlM*aHfq2C1<`G@RHT)1dFFPB)?j<*&W-#=ZV2rwF{P_1>aE8kZ0nH3Em~ z@yTwVaMTFmNM#Bwj|bVU@%cq>MldD^7kZ7;byDj~5wUomZkTWD*;<^USXCJOeww|7 z#a&2$;m|%E)TKhojaW@J_K>!iiqsOeEX9M*q13J7hi5i6A53q_G&zgw&ZR#3flC1^36 zMWn*f!3DTOwNqEQ)>cfvS!8HIYCYGMPiM2Q!0@o2Rv25R)@`y#;rgQ`-T{?Kczy5h zMlO<2ixmcWgJF{LUz1>FR0TUh2Yz+1c9T7ZLx>W&tmkC%mh%se zxl&#D!(+HS^DGGO9*1t?n@O7w%v81tL|h!@5`LtcUR17RM&I8vFL=*-1sy-+UNczt z`)?|^Vjqp`Z?9CWUB|dGYsHFS?+sQRsRG3xM8?9vVmxpWNZ!^tlYazhz~3H~4ufx3 zgJ0M@EX}uWrJVNMU!h$0s*bPRtSumDuw|v$z0(pKPw(+*PIuG_JSxYouEh#x6Na1H z)h3_eS-tMxO;~vSm?KBkf}3Phl4JlpK%@R-NCp;3&dvWUng?ztja;Q-$zqjF;o)VD zmhjVXx1~iZlfXxz_re8!@vQSF#>OTauw3T9@Q&sGwy6N7p>Pq?i)y# zO||>Ov?tt;PQnOkF3t(2-rtzj8n1AQ|uq_u7u+M^Y2L$Ahs9X&67d={_TxKPxR zR%?P`TM(-{@JfZVI z>_j6zvajAz9wUa$);>%ut#nc20t5i`HU?<@V>YRq{BBB00v6+%w5TIaxGTp_3G;!Z z@dRWeVF59onCdLGWcD2|czf`HR>lrd6q6dGWgiM3>byA%5;lx_gVd%Cent6(bn5u1 z6q%jRw@R|uFheTm?9{J)l5|4P)f0XiqBdK6$uE9YMND#Dw1o*VbECyu^m=c(Rmcy> z5eA~+N12(Z9*t4E1`zj(PwU6d9crLmrrZE!YhoenCE?F9m=_GQCc%9kM4ztXmKvL4*5W#%K;|{hA?DG+6jB`LL%t3dqxq7>qz#P7a z;=!PXIQwHtzHfVmI4>{Cn1!T9ddKn^6{+?RKC8}|X;UM6vkvDuYFhzK78vEd^YY+hlzRrTc4uPQ_fDC9M(A9>w-djqQ|H~dP| zq*>86hMjDVy}BncY;eKE>K}TySYr_VvY;gl3dJ5SS!9Wz2Gm3w=|H4^c$o(x$HJ%# zla0$hXi=}~Xiwm;zHFa|V|wFoiv7|!4KLdgH5vX%ym9 zr!uC&0|Wa8?!Xn|xYzsYbRl-ghkB!EY(!X{8Qh`H2E<*(H4AJ%oX|w!jqg?^96&J> zcjNNhNX24Ii(18fZ!1pYOkH#CCgzT`{?A4KTg<^2d1>h4@GgBMNqu%I#k#{%HPU*Y zMqaS|I@L93a`($eWuq)C=0_zS@hP8!oEBum8J zydjvl%@h>pl%T`Q(|*AQ+rNQ9eFoZJKTBA^<%#rsJQMGMFO*TpV zHF$4+k|&!VGt{fLo-WIAE_90Y91PlD*pq(LE)_uwF0xbq{&BZT`fpRIONF8~PQ{N3 zuH{bo#0h?+^%m4<#RuMbLC+76xXe-xxsGw)XuDbw>u6Nf$n;_X-iabPKb}glACHT; zE^4PPlb^XFz+k(a?|{)($;w}&Pk!QX7Q5pin!WP$H`MIe{{3)rPBzQxTdlso$G!}N zc5x;w5NOF5^@LGy1kW&po2@@Z#_`LpIl3=)ASdX8_aR#Lu97FfBo0Ni0zF>MSuh#6 ztl-RA=&EFq3DpPXn?1tE*@46`a;*tJwwOz_pl@YR`GiCffeVQ4OHAOdO@kd;*pXtw z8?TwULv{##g;^s{nx&+TAA;+B)a5^0W|fEOec=YJW!A}3p0q_o|?ys0!bWJtFjC3cDOt%NQe>qjW*s<<9goVWCf6p-CLyMCheE_$9pA; zUqN7s-jfsD>6m3Pp!BlAG79^mI~kum=kT<3Z(aq}7w4ZcRh~$1)Z=ed@q{XhK-z-)Fo0m`EE)-IpE8=vU7-XF`J2_uC-L4G^<`Q;Qu+dr5e0 ze;8b-q8ZXEMDF@HdkyS**(P>tZ{faAdw@%=l@Iu@Buobh5wddY+X$LAx{^~$aEpN+ zh>-35NCzJFxU2?1ewx7)x*pGe*nX5o6>Hs%<@9YEKTRb~Y=X4?2#BjbPulsnEpo1|cPvk?j(2|EI5uw}JIp`h-x zrDGa+t3-i=R(bS+dUe^gkeUYjOPsdIQNV5om)mOVPhU}%@Gd#x&ZQ}5^e`5t-p$B? z?sASe_b8!uR2(;zO95TP$FSt;qq^o{o(t$s@X%M~NmQz0!I7eStSJewxub~-OYsD| zLpvZ&1%nqO71n6Cyb$g0mUkbDrn2PTiIikOmQ)!iP!UVeG-p71|0d=gQbrFes&gSDTM~0vn_y-ybq5< zM-?1HZQ>Drati!Lt1ud2^SN4E3&*0xmKqIGTGJMIzcAe;Bo7=POGN4;fvL`f}4$1dDLQ|d%!dA-v;pJT)m6lKX zm}7mp+NqdzgK;QvxTjg*5TRSY*_(iYKJ3W|Ok08Uq;g<_$a4O+(8l^dU)+}$>ygw^ zBgd*{{3OwChLS-l@as}8ouS~cu40_W6oIbc2aPU=f~OP8#;=Yj6l1FPuO0?!p*i7< zy0B@r?y(_pS%>7)hD6pW_`QLCki7||@>aq%pGAgH$28TQuL}*hZvi5rto>qPEABn3 z&ON89!HkFz!%Kv0MIgx&_mqRNwM*DD5#oe&NJYL4J)QU!#>uU?oRo13R}R8n>IZLs z1`EePla<3M=I(Plz|I?2q{ET=nEeXAv=}N6APuJQt!MB%5Pv7^Oh3tc;4dh1bR{F3 zW)DI7cFDO+SGvBMCNjsF`qxdxZtaM5t}GF;HHEoa)XUcLyJ==1S+%h%Vr>;A@=|rI zB@fw0Wo8+i+3j9PoTj#bq>kaZs6C<%OYe>3g=O5klpd(sP?PkN3mJ`yP4J=nN4iX> zk!acgO}U@kThiXpD|6xWrq|5t{O+%euW~cPL806ITGlNl#tO||OQQ;+v?qJM?^w{7JHd8tv@9ddr^q*OFZl$@~g;Ffud^h@< zzD$Bf)^!4kfM2m)-2TuMjvN0HY7w>^9E0Eia`xTYMSC2`{$gB&6HejrjbzjsV-T*}L!L?-qTKR(w82w+=TCz;*sAcxwt@Xis4Wjg7q@RyE9>29 zqh{mRj*FwRZsJ+-n`zc#!xS7ESqodgc{^HfC$0_EN6Q@6ogigT)SjQJvf`4st;h!$ z$b(9Sj;Z~B>-*7xtU+E>}Y7v4wWt3 z!&QMrLBkM5!nO-2Q<$HofCy~yBjwg-V<|cXRy!3{DgF^rBi_V`0H4W{ZDQ$@n=JPz zh-tv>NTD80=$i}qLlOv>)N{#d95!G0V@*(b`_Kn1(b*#to!#7D2fpx3CiWEGid+0O z{J;J;zAP0cLkxfRtHIxv4q5j!z}*2s4tC(|PYEKtnC@TGM*^fMlElv)y~B_T%etTu zScp$dXk}tAcmZ9KdRS91?pFwc4oAYYjnJ?ITp^DA3^^_i5=ZCc?{dRLAPn^4xsvVOjzqsgqdn$J+MUk#w^ z!Ymj<<@xMHb7S32!}xJ~f>{LNJ(nO{t1_e;m@eE~ zS>bPBrSXgYtNzuGb-y5nkZ~w?QSjX@crk5ZOPt_~?6&QBBDg!jSf5!aaZq6<>w3!p zU&7C9(Xn{S`|9qK1#VBwfMmO*uMO=@!T#KG>apT-M5s_Cz2Yb%0T&?A{?u}FBWTEN zAF>(wfJzmBqEhlx@sJG{mTkjN8^o5X`;f%qGtN<0TdfZf7uBycyWR5jh!5`RCe|_;J6awst-OM2)?1mv)^#^>f2GOvzaGb8yEE? zu>j}*9)-)m3=|tZ4f1frKvZn1N56zWVtv5(>11}gce-d^(4IQsGx!Uc-ah6L9wZC& zUrJb)H(0#V%i+=@dS;9&Zhaj4kEcl#07@YtKMWR6%{syG zq`+LytuqP8I(U{~%FrPUZfR}tRRWun77xz?`@ocDIgj&Xg1Ku3{>Uf2IA-fmORm^j zej>}9(!>7$4}4?zu~et|5uUJ1+bh=gA{CEIZ0@QplDMThwtb?4<&!Ou8OfzdPb+@T;)7IopSCu~&J zhCGwsNh|D&a~%Ne$4kHbVZ46&H;{A?SrMVi!uRQHmgNY`oO9CWk$abIJs(iR9;QM8 zTevPA%etDlAINSvu-Y0P*2TCCR!^6J*j1*Er@rzG{%u!FOSJnlxyhOA$a>I8B95v_ zjI9C*2@d2zPV!-(z}vlUdVTo*JGceJnCC#L)qADn7!p%s&<)hJ{nk~H13o&3*`g4; zfgCu+o;a}~2|oH!4q`o+eIhfU7UzAMz!deZ zl7%6Bs?icPoi`!U3}AsBa&~YflvecfK-&i%*c?>EkpaKX3)r83t1%q~P34?1T~GO2f$ITJ+-SHF=(!^SQxD0X;n2=?zEA0WAjLvZ($JE4;EUOrRow4A>b#W7+W!hi1pOLFh{V zSxu|Y#_H^pm`>u4o8}YzD+%oMT^{*w0I4Y-ap*yM`_>eL!%)owFM#9ndl_<&6q@FE zkL{-V)EUN7B0+v-WuNrg{fkCw)3Ta$X6-5!gf|VF$e5nPL4oru638OyR3zot$(n2h z3=RmQl(bK#*dNjaRz3w)%Rz(jSkF<~9D{(GKf!k$#Z;!UPD%tkKv z?D$|^nlnZ7G4B8wm9x1kK|;?1ywmrl*Z$e-18yNOKX!~t>r4~kUll~rV+A>> zU+L9k*BRqxHt(~}+`HHB#Tlj0MP!p%A9|Yw0K)HtcwoDQFg7cm$+yiuqeL()7KKIq zgr7f3_W57AQ;oNd`z0XH=7rKt%gJ8ZL3P=aBi$fbA3uvPQr2=N5){Z@PcLTSl5Cex2<5#za#d)FVm z+-<#P1SJ_d4kX@}gA-j{0B;F*Rzrgg_kI(jzXH-O9d8rb|As*zFxM*)V3D6TJYYY# zPP9M>jo|IhRk;#zZt1S$%;*{IFNPLb1|?@ zOqwA?POz~i#!FfM+`dGSlrZBdQj0|-1*m~)kBD}1JMt@bMpkYV(9SFEzQ@UV_I*&JeOQbaw@AnWmlO4LBS;R3)SyxYhKw}NKFtx zTGl#>>m>((v$W+S`{FJ5@z{j(Ck8H(*Af!KVWh4AW4iSlB6{PPndk0X*z74u5fe72^o)#&RaZyNkaz1SB9C8B8Ne4J|Vo@0G*PV1huO9P$n;9Hk1@B^l~ zqU8W2Ryqr7Mr6n5{F+)h^Q9D{kdBJwD8pILIWs6AUeA1>kV;TSko@rHpK?j$<0TrU z$5q0j`>#@Y?6z%B40iXvAs0r0j{8c0zY6})l0QOWV zUm(LBMx<%~ZbFAnci4@QF5}KI`Yc!IFjT4vhDI8uvYpm_e}Jgd-39W_a_RenY? zO$p;u9s5f1Js72Q(nsp3x_-s_LG4DM&OlcTvisTtSy(05qp5A5t60Vycr^q95#lkH zOK}(n<$uIo&n4Us4g7`3=!v^F$nuvf879ai?bL03OqGt=8^O~eX2mx1L zRYqD2HdM@+Q(kQ$>215hBbT7%(QW;KZ%X(|Y{HUz->XT6Xvx(APRV!g^NdW+tc zgi?m)SW^U=IpGa_(*w`)X`Lo6<_*UA#S95>A{L#7a-ID$ytQ$28X{wEnA`7muNRn= zl3|;mt*T^h7hTw9()N>>*fj-JI>u^jE65}EuNlu?hnOhf`&IJ$zc1oYQ1lo%j;JxA z&kJ=K+0X3KDm$^F6N2|7;FtH#IO&mI#6F7ue-;K&RduB*>x22=x?YD0tL+;vg#!Vf zg?9T-yt4`|{^=HfZ45&5-aN8%zfLJLlMSqUMIV5A*%>inCMpEeeI&?o^;z8*3lLsy6=;u_~u1a3vc3_)fF7OX;#TZj)vMatHvv zv>!QBuc_1i2mwq4MjdtR|H2e1pwk0hn|;elIs+A>2S_@w3-8sDa5OG2A=9JF^$f#0 zRGHurnU-2sbZJEpvCqR9e$_V!y?;vSujjsVOQ)6ZrOatMGGl%pD$bPwfQPna`&1@P zv1HqOSeu`8ef}%$D#5P+uQ_@OYMx}YoV8|tBm`K*ihoiaazVr_>?*1?7F(kb|e7<<;E>S z=~W!XpOE^MR!gRWJIQ%XHADL~0yTvB157u$-9fN6>73j1=%LBHF|b{0#i<%Zkt_Ou z!2HM{#)@=i9W>C-*gga_^yGVqr3SF$ODBkqRraeJ+!wO{F= z*Z{}P;#|1Q8TS)_>WRc{g-mCw#qpt1l8&M&75M4`ExJhn) zse3kfr`pDDEg&KBiYjFBD61qfdF@*)ZGcOye_X*ftM>+xA;Sc1v_nAqdhWj5T289w z%qKOixtz@ys0F+ip9-wcFWCC~7@`Xm%|v)%x4^C6ag*@D?r2E%EkS{E3bW5|q#HFw zVsdP^ASybr=4;hP#JXG#cR9or!t`toXc$7_mfDfU^hi95(pEpNWI?)}_ki3GtDZ~z zWux3l;-@KI@{sNLI^VREdSJy;eT$Z2C;XY(D_Osq zS!#En{oqoe2j0RW_z|h)QJ_u|5{aSQ|DY+%IAd(__*|M2O|Izcv;ZCrXp^%D(LSd) zVbxvhV1b!s-pX|-{Wg8U?2-@lmpCO3Lz+K+*YwW!yPv8E&}tXTc2*+~T+aO?a5u9+ zwQ<80_X~BO40__eAa0KERW$eT#n|Ta+?Thi`QuS7wm#96ZlQkpp+jNrdadvlD}{Ov z6?@9$>p7eY)P+be)V&S&nj`k!;0l|^Aqg^+s3e(voDn}^fOQ4Z<2wslQed2X-*Hke zbWT$?C5)yHS8fN|-LfZ=(cb^s`38{(+=7K_WDe7cDhYD?A-)O)$3@q%Ch8iylQyV&Jo?NP*uSSgBe~0(W$?t=mi*ervhOQk#1x#jR z-{19M1chCUb#{(t?+%VD{BuNGXM-3S#uN*1&CteckdwUQ>MhiTp=YzS;R}zy{8fOK z@uUcbiyinAFx0AUeFL~7CtWPU`pDsb!o zL>vMJlCFs#;jhPv zD(FIk)~I0=?YuiYqrSl)a@1AULE)ZnAD_D6(mE$(+l9qVqcWWdL$=W{t3!j=pp!vC zWhFZeK;H~)yk$D8&q2m0%F-kE8?=3ehQcqLP3uf;aQq?~mTv5q(aW+!uL$#$Y z)a-}+0>BTUJk!`V9!S~yyXg*&nG7A>s7bgyDbf90-c>QTk>y2>mgJ}8#d+DgO?;#% zGoz+q(HufH{{OpaWco<3l^|y_LvgC0ng%PNQbJDnlNd-puTv7xdhyU9&}9vz+1`M_ zg?Lq(Q$1o(k*SJ2=@G?G=*@g+p9R-@&Fu%y)4>=m*=eYWfqsLcGtoZn6~H#ob#<*} z-vQ;=$-8RA8#p^!^-i(yhv@@mtKM15ftiIxDWZDF0A5@<+#UHuW{egKmabSfD$GOd7!1J+*+>vewnjC_e2t2um$^$>3L zIV%{WwC()6*>71L-ciK1Ni^azy(_AC66xH}7N?M2^ZoaEyfq5^&m)B32O-x`_e(O< zaOSOWU(3=FW}1yROMY7%e0R3}rl^OVv>-f!J^Ub<(xh8fifHA!cnRo}Uq0W;|E#sR zY7$Xq8`!GS>1;B}G8ZeFSex-iHsf0vB5j%aK~hFf<^s#K^>JWyJ2|XP&9GA@sE||7 z1{uKp8`y3wpX%+$4Dg?+a@qE`rYRPl$y0A|K1SUWsS3Aqtl2Lv%+dmAJ-XIBeKFN- zlL;u}(%s0%7n#Z30lBw8ptWOsQm-}(5F2U`ub~P$uQ&7&O1H!s^iN|in@wY0fY%SW zE5>o9^kG>S=Y0Kq8s49UyklC`d7w?dbFciGvKjeK6G{ZP)*3sO@g#J=U&0%M)~;V! z9RR~L7akr}4;k+4{TD?%gs4`%ur^i}|LsoyVcPgeryNc9WV>?@EAh3`6;VH&_A4*& z>Jd?MMX{b-9B3W0(9eRD50}Y}L%mpyiu{*Mme~yE7dV1e! z20Fty3MEw~hM!7rw$Ynpu&BW;H=0!Lqq#}5!ESaoCCWb3x*O*ea%za4TG8pvbA5jX zxv;_d3eQJQefjUGlxdvt5kSxMZ#sKu?$UVthO-Z%2AnBO$x2M)#*f09pAITr(OVkB zxgGPjN^c@EK3Em%0GMLA>qpBdS-a)mSKi{xEjYg(*`=jR)A@Ndma%oq z)folMVc{~Wc@GdBFMkbAicr1K{!d6*_=B-Y{Ny^uM^O5dmO+^XX=~nP^ltq|z9EvO zE8V7icpPd9aDl|K_xsG0->gE)$KCUbJ-j*l!;7oCrKTaBP~ zo$1wjz3V9lVT45_@A)dCptG;nIff$B9Odv5&}fjFVj6e1-%~`OS-z;ww7Fiqh!$Bk z=aw1_HXQIlfk&Kq#8tWk^M!D}6oQ@;h+x16eviC=N|qL|;EtPpQ%Le|vJ3Uqr;(MO zNAGZh=u&uJizX;`qCT~^H;f2X>J1W67)HO?_vV+|1&zQ6srAw=kAC~tE=K@n*_mj? zSq22lOIw*W7&?r=q-Dq6%o!L^DGmP-shrHFvv|Jx)8DVEkWFs1 zzsaC~kp*8SDh2%Lm?Q5Xd(w}H#ME(-GR{pW%lb53^fI!pPRFGthjT@Giq3nmH4ZVU zw%snoEQ+JDsNLM*)6SCv2MqzUKnB$3Q*5c#aIW(aTdPe=8-tuU< zU6t${%l#MWN~bOwLUGeN(}9gxpnDI$o3plQu@0*oY^4m_9h}}of*JvS$^_qP=ZGgv z3r;V)tzQ|#UW>r%=O?ZvX@u|R&6H5(d|*Qm(MOFpQNiC zEezkAtqdt96}Oh2`Q`@a>00isLBgKG+eV0t$$?mw%I_)F1hG$-tUz)*(`XBLC-CYv zj-IWup|WcG5GFzZZfnjc@}r(R^7@{qS!c8h)H*Up&6mw)$|-`fW2r<7HwzAjLxKlB z2BN1>u5}We6}Sxu8q@Zl_#{c0qc{-`seeZ9ZQa(K>v%YDxKWFkEVmgUX7dxO;@o7E zK3C~Sv_uX1qY1NDxzOWnx-6Re7}WN0eMai|)e|8SZNdmWfbXNYw%5_Bd}O0EzAq&3 z8a?$ibz_|LcRKli*u`*VdUGsvE-SID9O{A@qk}Z+$%phi>cuX0R2Om=5?N2X5`+FA zf_z*g5}Ahd0eu6o5OmlS!sD2ih~k;<*tL&Uw!{u&>&OTgn@|vI=sUOGiH}IfkyeVU z0T)}}14(Yfp_EKLHZ6YehPb0;(9afxDO0P)0s( zc!T8`5hxOidoGc?Cu2mRsOH>*vLq)sm(&V^Xrj(y$Mx-*n|SGazF zeAnDpLccx)<79CvPa%2wSaPR`mbF??Sn(-Fn^j`5UghDHq&Sl{e`xdt>-U@Q&2{!L zjW*mRI8H9?IPI>!1-6-uS%!UFl^bz-7cNtbDyI)8HDq~8@>;m*hedHNq*fph2}!A(Y5kZKUq1(Sd;6n}I2tJj+?>wNY*huvs& zk}e5<49gWpRg`}P@`*sP70`?11#=EqAW5)?^zd*Ibn$}I%A6YajPr)RNFwHiN9(D% zZ~_iW)i{``2D889`jjzhaHa(aF(a3dmsGdvQFzAMp5*(}J692z96se+<=!h?W*dB* zCL)V=SYdwYYi>VsP!UK9LJ0L%-MA=v$;&Y#NWt=4h&c>ogWAKo<<7S~(Zf(=BhAjz zBO}uhib2GWbgpa{wgQac?-WqoA^JCiW=U*Oz5$g{WWW(lAeWLomtL1T7R#w552nN| zwN~x62$YCLI>3Vow347)gS2Y1(rBd8U8~wfa`TWb{?=r+9aY zD<;)Oz>Ge4$Ape?Tc|D><8q~@oW>=FlLVWSqFhD9LjFK5GNOiuAJp-;%xR%Wb1HPD z#aKP!XUH~!3MIcSJIxlNyY@A~jl}zz);ZD8NxHGV&DAI$??*PeJ@5`0z9fYG*>4}( zA7e1==R>407X0h!U<3_-RaBp9)~3%)h|P##G(vHGrcp^vb35*tFhT)m(QQM3=+BvM}9)3vpgkY0nvzJkA{1N@cb z=(9_8R32ujmg?Gd;?*xtAV62;0W1o>A>m&8)2eRgk>W`jW2 zC_`%WCdCl-s>WL`wkN`lB_`gPdoYiboQUYw^#aMF93zhA-0iAC4Hgs=k;50ZbI1s0 z_j6>j3HgxltO@SbQC7ihfOB)v%u6%y!MF%;_bNzejSIzBAzxi( zIwWbOEtY82<591J92tB5zg!kjp^Tl&Y&ak=#X=Wije%NM4CrpB>kizPggvKo2o&=_ z?z6E?G^c?H7QsZmNrpnsK3KwkY(SX`B(R{$rQ^Hzr)8l`Tfy|%w7U~sXZH=y1~HIl z2MY{$RldGEl$aZ^<$16&LG!DucCzR+>K194qy$f+87!7GwoB7djI7%xR|8At8ku#X zjU^mJL6yRu3us)A>TSk}hHA3`9ijm(SFIC9-@_H29bEcgfCXs+{_c;cF?_6F6^BbO zloJhKQI1lXhGVUarvrp#KNE6CbTjbY&F6Pd+lruZg|}=lL(W=Xt7|%`o z_c;d=!hjl*2&#`r8@=am1!d|df(z`Fr!2DC{?y7X-8)~#hytU*9H5#-M5%ZlsSVQ& zH^J9whxftj-tUrCMrAOVV`g4HRY!U&9yFY~8pT|i_uktv zI-M0AjpxOaL=F`$akNX%MVM3|!s>9jNQa`=bmPhtA{Gb*)%_Aj_>rN(o`&D`2ReIx z#e0?D2sE_p2C`A}dpmhEJFCCt5U1Hi<*$Doj|pXop+%&9$DU|F{^)t4$P07@FrbGRCt%X=Ss=HF3z}__v z!OSpO2Uz6YRFN-7=1w#6xYN=z|h^HEjF7zPpIA}-|3M!o64m* zkWnus&>$uCt5&H@C%yrxlEht6X2>(|8I5d;xl&k~dB6`3;RJ9J`1yugxzjRLNL|?* z&_!82VJFF;tI4|%J_wGM`z^B9)l9gFqFVbZT9E3SkYzZ_Z(~rp@(lUeaFve?^<0R zjzIzdPHl&Rjesz#{(?7npVmKoN*MDA(yoRozZFZ(1!H5(m9v}y?C-iK9a$Ar(O*v+ z5wgLP4Ng!X%R6Q%Q~Q8jxKVsgNcHT032~U8Y|NJZJUs577emT& z%9g>gNH$snUs5AQ@6U*2F6(QMA3h4Lnp1!%&1i#zz4!3}FV_%VwO7m4MHp?m``OFn zp;&^hH&1954bfqp4snzs#C~A9;MIk58t=F~kDJ;0Iy}ILP+?DLn|Nc#gN8Js-wof} z8tktSh0%N^3JM`LRro8s8X|gKYjG80;1P<8{`@@w-gYu%Y%$g(cPfVK)S$`QO`zgL za^%FW_VqMy2nq#lS)my#;HVzPq_Eg6o0Q;Cs`&CeIb2EodI;Psn`dZ+Q4iC02!j*< zOPgsZh{a2yJBD<|_cDWF_xQZDgNAXBTTRK~G&7q)eG;2N8{3Y~McDb$8-5bZvlG8~ zXx?@gTx07)CWj{JZQC2;TV+3^=v8ZVAz3EX`f~XbLMgBj0~qcom|H|-amNRGl2jk1 zVj1=_6Iy^~+o&mazHnq6qp%oZ`@88>IE+xtfE>S+D=6)d% zUX$=w#!l^EGE5I2wVB%iZjdaQ8m4Y=6(9933A{w}vgff5llPN__5IZabtbJ&UGdBc z>ODVLzRSqrH6eh9?DhKe9KH=vc=5Egk|G($F;C{L8_AYRSCc)rRvT_e@OfVN@9`P!bew8-WtUnz2 ziH?Wi_xz^#7qDKsdMW|AUtB=BOjlpk%)TKH{F^;<`F-=vQlW_iov0?ZTg>$qbO4N^ zlZID~+YJ!|AL7OURZ4STban(YJcvqFb!b`hRSsT+T4LhLUV<}a2gB&bYOi&nmj084 zJtlCq_M!R)g+s}lC(!|eYq61kF4WP9jVtMAiqM!t^!QFA*Q?yLg)KHz-UamopUCAG z&piB5;ILfIhbr{rr5cqO1=w!&tyC;!v;~JS(m9;Tz+=o*yhLs^Q>;uIz=IzRP8kZq z4Eb>28JM%kK(hd3pH#n)LvNLvtRwm}#6|oRf7tX<->p zsN^-f;MpAql!SI`s9*9rcPi3IFX1b3;*bJY!7BB;*zs)>kqM5ZFfQ)I2cr_x9MPu3 zrWl2&DDFD4aBjNtJAo=ZGhB(;Y6pg)()U;$m?9DkR5P+eXuOj?nplZNw_XjOs<|JX z-rXh2+rNK}#|K6yn>Q6?m*trI=P(n?W`aUVHwsqp*-fi(2zFU?m7#o4LcG+7E)w1d zujS2|qP@{QfoQ1)38sF@7S*)s{b`&y$CM>WY5hJE-VPC@J6z;W#lIA@AGQNu8mtwrj3zn$ChBNM#pQmuGG4kT!rE)WBwE~3Ls~SCx2IAbJh`DB9I;C(KL6AFZw`y7#m*@F3};Lqw0jp`?*Z<_G<)jcYsJT% zEZZqY;=qe&(EH6aosxOp8R$@u5i ztNa~XGFoH=<)CySd)!Nq)m^OD;{yCu*{IX&NGP+jb5h_;VfsZ-LWJiBB?&L}i|hir`pn-uiYhCeA7 zZ$+YqKX?3pC|kcB>Ur3I<5R*HFhdD~orr(sMQd!jGoo%Ur%+jLn^h*K$6hP)R29Dy zUh3SHj|#-zEP-dsO8Nj#9P{~_tXz;6@gFQd6$#Ux+eS81r|{zz9QHZ0NZ#t}3gxoV-Y3yy z-Zs73gxCnCh}g2nsk*Q<)_eZ&5vlxZ6w*&1WomR`Ufe1#XevbRKD0;1cK&4&G2jSS z9;8n)&d_0p!b!zK09hrvfRd#$?Rq7^?uG?m)%P4Gom=YWKwmvo{MjcqNW!=NWgmOt zcYKo#L}gx-m!K`+_Xff_+vyqKO?APTmr?EJ_Lrut@cr%eIMXmhU=CN)nKu&ipw}oh z08)A8hEY$r?^A(=nBcV0dAM#WKn-~?DOd@Q*d%`52KD#~BzWNT%0T`(4F#7Z2vElP za8IEj7S}&v0`^$+O9ix-`*{ca6^c+URhWlkG|(~(1NoF#(g*hr4OD~zJ+6ywcxJW) z{d5Q2Q6YGp7@2*R3b zx&l*KZ|z~IW$=GU?trq!;6R5{sz=brXAF-_&b9a{b$uML8JLc(hShOVdW?#xHAZx7~usM0ih!pxC@U?cCJz_8SB|7|d3qj%C1#VX*^RU=FN&k$4XkWwst5o-FL96I?>g z>xwXCF5v5|SaK&)>(jFasL>y8LVNcEjy-^*jqf82 zKFn|re?+TT)?Aa2N@QyPb5#lEQw0}OofK$fv_NW zkJ*;&-JH>*^^Ky4cU1B&j{M3-Ay|jKbCERLoj^~!qhN1)jHm;Ya=Au&vX+>}qDn_c?7 zbrQ+E0Q3&}H;=R(d-uYU&P!**7IUkRA6jW#2(kEr+}mPsw(L2p(W9IFgVH!;5*>u% z`1x{f)YC$VZ$^LMs~&JLsql9iI>&^=CpPDy_GfvC`cSPqfNFPua{?+{(_E&tmiiA^_8~4&W^w4U_J+Pq z<*nPS`RH<4!Jzxbgy=WC_a~iBQt6a^b3`Q56EK-(Py~3AoZ_)i+d^wCQ_@IR^=Q4P z89ULUX?tCN+2ihNxj20g=h zK9$m0J|X!;cTUtKg-jx;sq{Bb`g+~Hj_GXltBrsY+lMJ_hU-c42rdhvrE$$z!Q=6& zPr*%$XZloQY9}_aLW7JJT_e;gZ;VVP+wX)Kk&J6k-~`ko@*$}FxCxNb2fouxYMcB6MwQra^X*>`c$XV0Ndx-;kq?vdLND^%HABlX{kFly7UjjA z{&I9KKg}Cyc0x$bxNvuY5DYD#bJnzcL@l9=Ly;GFwS4!x-4Gl~dw+qfq9BfO`zVBW z`=x>XE3q4h7r%SeZSPFI9JY~6Ya20*odAL z6!HPoY2|MAn z0*uQwdB>CLYiF%dBA3OMj_&I``#-Gw+!u|o_sk&Tq9dU#_cOJp!i1vNO08wg<-iYK zt{)tVlrHCwK836`E|12W+$fC0#nHprO6fDQT9Augn?Ez50f@yQMiRQ{o2u6umW;@_Va&I56x6llIe)*CN!17&(yNebJM0w&#d}|g zJ_CwZAa3xH^gC&07=&kq;8?1Oa_16qY)suhq@26>#a#v#Jnb9)M4yCy4A>j8%6p}rcqmjQZM_g5EC zI`%K^gxa7oHncZm`aW9Y&!=_SE~p@-U>RvssTV7N)DR&{ zCb%oq=~y@#S-Qm5Jqoo%PM!Mmcn?W-EYs(IVpRNAHtv<>n!${{Zyk(t`;YwsjPMM` zzGwRjl<@oN4XeL<`)IXDruv8b=`*R(bmgBV%r10^LKG%WpPqi2IdhfrnIj0=?8N7}Vq*%_#h0LW^b zUF&IGKYZD}`%LKZBMl~hATzAJdF3@fa~4mnr-T_CQ;3XkGWWQ?fM;p*Lp9fUBI`6{ z_U!lsYL=vWy9;zr9FkXIJ1ehelqfASqb)U}KphF^6vlM#H=|Lr|AA&cIuRO0gkVC@ zzRXjL-tpw}@OIRa_^lrI*>zd?shfdw6+cG7+fusl?tQ2t$zbtzpA7!G~Vq&wtYUd`?t7T8CPmM5?7Yzy=sCoX-)TumBQ zBT=ldT+Us?{F_-c30(l+;Yco-FG_H6v*)Hg5$_e%-HqmhWp&0B{;DoyHqny{IqeVz z)6q?NR6mo2))%q73mSd$Da+MSau3J;wj^?;8_rrr3UDG)m;zX+6{^m*O)rt8> z#nidL6C72Hzlop|8f)ddN5!8{C<+nRRjrz z+`=%d1Bvyz&|NSWIV=a=Uwu@$!F>&$Hn zvOb;~J$#Zf`Urr*!lTwTmjp%{O1RQ8-5q7OO`}A9XXmIL5WMXiGk+~{9c!AUWkJb> zCwM{z#wtVHh@3`_>Mi*glIY0P!n1Hz)0>zXOtwI;fJlKz7T!ZPd)pPD#zE>3B-VfA z(@RjgGC$Rn*KXYQlqBZDJ>6phE^0c^7(DRGdlKmQDEpd2&EpWvcUo&zt*Nh1XN4?y zI>X>P*_(WNpI7S_-7udE)@p*%2(62_+?F`juT9l7I*ue%olG$VIXePi0pS-#)BmsX z^<9h9Y*4f7-X`-UQVs}76dl`ksaS3^(WC+5Zhs<7FYz6pWDUd&X2Me|qCszJTeW@6 zRAm?R`%jzn4qC@RP|y(ocZtJC1pRARDzay-;w?ge(!=b`fh@F>&8#d{d<*+~YW?#4 zFKE1TD=aFD!HW0A`-_D%o5jpH1ZXMdkfjjZv&>esq&B{pr;FoOD?x7Y@*Q!=mE|Gb z={$2}tB}g=7O!+OjVpGZQ+k(jm<1o^+A>lNTN^)rQoqDh|_&1Cxg%Keig-k2;m4WcG#4~rd&DM zqP-~E-8x&fY)S&_WoR3ydh@lja2_qBv0KNPiZk0!F*FcT! z_|krRY?u#oDBSxg+u>{`5@VVaf%?rs)KTPB{$)Gc2R=_D?GEG;%KtITj}1L#$#rxTT`yNsA!o7 zO~3QuAvn?&@NF5;*`3bJ#_n4_-*3-uqY7$prh$W{O#05A%%#_HA3h`ttqMegvl(Ii zXk>R9n|w&YrU5=Tf%l{vI+Z!rh5Q8Kq?2H+p!)R?#8V|-^B4hlQ zZond&HX+Qj^0!yD-&oR*yjK&2fo6a%cei7u&_rd=*`D1SO04jx5Pey;|B#HMKTE1s z`K>p=iOT4&k3V!GMMvZ^vR_B$qn{yVm9tL>=y=O7vUo)q;2_0(oF2~nT;P1nBaK8c z+mn<_XbZsJb=}2gkPPTVrU@L$+#di%g52GUW+`<%)Y|_LZ1yBBdIY;+ZYy`W=SK{J zIhZ%Fefj651{Kou=3xU*i{W==xHP&noG}<7tLFqzCFU}1Xc3*`Y2{Rf<8v{}0ha)CL$(zDvzq_28Ey0S^TQ{t!o-VLDV9P1Fn?V#Ca;dGz7DC3 zU1I@<>m__D>;TgRi;SO7o!hj}<^re6zEWF^96J>=#%<9l{s} zHp^wwzW$7KeGoFiO4p_hpcZa9tFip>tbvw|iX+3h;9$dGDj_2S$EfrB?@1yJ5p4ib zq6eOSdPqoZ{vDW#84)a8N%&Ah6GZjSR#YsmfAW}ajooQKlq=6X;j~xWwpQPecCw6; zpqUc%(9XEcKO{e!*#SNo@WV2z!|t^w0Ee>(e~YpiexZ4^xEg7-!7OMqY_@tvNXTM8 zEbf}5VN46T$^gA<6eH|RnBL*hXs!qT@^4#i=bKYNa^#HlOTa@|=9a2CZH$?f)>Z)g z4Tn~{QxfOydco*So#5HO=kz4=!27c?I_hlUIE^{=Vy)%#JM0~KOpa$f+8Pk*^XH;A ztW5S_DDdQrpJk1tlLJ01@>X$S|;_##HS@V+?HAuO=OYx^Rbj z61a;D-we5^2`S66qFE@~;H#P}a!L5G;OOD88@kbR`gKp zaZt$YzF%bDbP^t@-kr?B=YjRwUTXvOkQV9=0x;%^1k9SB z90(RipoFcV8+a4tyRza3;?9TKgIksTD3Bu^!ZpR_o;1vu>$LcT+u>FT>6G-j4OxHA zpIoL@WbYfkh==z{V2~}fww$5R%0*!%eh=d{d9Q*{_SBrsgxIi|XbF%A%b+D{b%H6( zbYwntVkx)f??a46i1Ciz1mtN>s-xGGU})zy zlDiE<=-$Qh!+pz!a!qK7zjZkv;%1KqZb|EtGEMQ)qj@1=y-N}AnAwMI0H#LMK23)B zG5f~1%$nstbQC4osHhqSO%KKmqFfTBc&w~D4=rtcY<CQxAaY$mpYRDu&-el7juUD9G8;ztu9W6uQW{P3zEZ?xEU@dk!@z3B%HRw zH6@QHL!5^Mxa>0BIbUEVTJw0t4F2A19pspG*i~TF_9>3)EpB!g5AiHcbXC<;p?Yxf z%IWmr5B7IjRw*5q5lg_wE%Yff83h=PzTn}^(t}eCbbhdVSwbG<2Y7{fPV#VooA|H< zwDLu|pRnVx&@J+XSvUL!5W**a+cMi5N?^rIb2D=4QW?wKA8H9qh3b)k)h_(7HS{*{&p!W7JLVnaG{qzNBvyv;QiYx!%Tz@ zAIM{nf5Cfk?yb5-(yt-CK0fSDY*q`t`IT~bMa@m91tRg*3*?GCd@ zYeAtF#wTJx5boKP4PIUAw%NMA>G}_3yKz0ud)$mEHOQ}jzgGeAOxz+Ra__iOT|4@S z3Q70KUiP3~BXHM7p~Iuz5BSrRyoVu|L|6Z6M!!WF=;M;5IWl0y+07)q@isZ-5q3yR*NHBf25 zh<=*Lu9V`%vK^wcM;F9ZAWDaFfeC{uQ@O4Rdnb~3lNYNjz}74yAX}?b(!yNkstQ() zNAm*H1fk&{lUhRS<`Fm7`0Cu6S1%f5>LeF@95Gl>rMq6{mD>Ne`+(o>eJ>(`!g&wh z$GYJR)O5GtE~kLtnZwoFgoDfK7U}$m_X+mWrpj@m^QvPL`Xp}i9GLjpDnGS_&0QLW zBye~tuoF7e4(b`bIxi@QgE4Ktl4G*o7Ko&ft#P@9Zp11y?_?OI(XYmsC zml__COV%G^Y+9nw$mgx2Wk zs`)ym3Tr;0b;(j}^G{|!Qq^y~Skq->Lr{{vIM2mOu(Px=UNy4nYHbtmaaMK(2k6R2 zpP^Q?uf2M`n)rojh>0vfj=qD8w)GO6{GAa}y>Ip&t|~PX-`||kOA493YQdOLAn6_% zX_rN2;yiM-2LgTFs;M#&sJ!0)oqmGPSjW!7RzW5%!$wdp-@i6;!q2yo`K%laa>@cI zM~Oqtp8d_p0f!B30Sk_w5%4j1;y6>MJ- zd#m#u*4E8?@4aDMZcOAL>eL)UYMDKaCDlu^G~1l9L`I0ZHb`(3OnN22q--}IeZTbd zo&t#JxF3BT^LwQjM;G#jEuB(lm{pPZNi@_ScuI0rB&V%GhdY96#?Pq3V5-ACVbUs{lXXYmB|t=w*Hx#PKIw~d(&?cE`)OXOa&SX$Z$(kZ%` zueh8N1{@S;FC{X#XcZiW(Yxh~2<~UWP>a2I<@6BQx+KOM#G6_*gGsFbSjB2&snq8b zCiN&wI{Nd7D$Y4{x@C@p1CR;eJ3rdntR!+x8ZC;w&^I|xz@)B3h$ z{Ba!zZOsU?9l`BQ;jvO?H+!*wjrd63^MLo|5qpsDG!X8Wwzb|%?=-ukRdfx?04e@d zP;N&SIX=!Pq1wG8^ny7>p&bK=YgAS6CdPBWcaQ}f;`jB(|D5pW!su6uZUP5EoRS0i z8Z-!MCLj9_PE+7rGK7YMNlmzBxo6?~4Qadg+loPNVVR&AsX`u_)@QlGg!?;@p`oDG z3V3fsw)?2#PT!ga%>Tk|RjM8c%(opdMC%BZPfqATd&A`!O%>O_9v5A*P9^YJhWOtJ z)rU`>d<}OY#IoJdtFm4m{7=k*>>O@n7xGQOKH~M;o=9MyV*B^L7O z4dZxgC#pA*6Zs+92N{`Y7InpK^y)tJHwqE#>edz3wZA*|B*tRKFM|$Z(3_gsCe|yM zNz*B6*@s=%Rc10!xcya&u8g3%E2)<5_#RZjpeyDBlBMNi3<{XGdx zgzJmv_y%udBFgZsN2x#DkMLDw+#(W-2vsNnDP~Oa*Y-f906IGm+gq~UxLFOQegG_TXVSe<6nhe+}Qt-1P9>(Rjk7Cc8E zsm;dlOgZ{HD*cv;u`sB4^tPkvSd4!f&Ymv9pd6?6v4*2A&*I$E4SfLnrg z=(BW5i_s4O<;~m=DNVmkX6Gx1#As5@cGmbF{m*MU9>5hBq4orUCl8W5j*i-syr>IB zpe~fXRW?UysBX2uQqUDbSo~Auhsno0cT9QT>qdxh;rIxf$j)eAcO{S=Vw^2NYM+3q z$%cQ!VQ(AX0*TJEWtuK4{exmuDStD^T1Y;PpiTpwFAa6keS!w+?6)2>w|fYp{3@`~ zu1uOTa#-4#gEOcB!l$Xp@Q@;EuI7v5+FNjQ zz6>Wla+>Mt!IKeIeQE<)vY?&bU6!P|F}O+yy+T?1ddVN|C_>&Cy`t(e;P7r?_|#yuIVOJCR?ILD=v|7xSN;zWmQw>sHMAAF4>{f` z91BD-seSdnFRu;Xj}^pJ7=oX&WS=y;Ru^lXThc6F4k=jO-RBn#%LS6!xMS0J71v5w zvxy7Ct^I1Oy?aw|slGA3s|>}VLaJc?XDm31%lSBnqvA(;{7_!HdE0!WHnV_Ue@@rM zGP|(=g^J@}BEgKZ_zYv{8TtJn^f75~N1Ed{C7F&UBU!$>s8nCxt?y42vHt+O8s=?~ zJ4pE6slSzY&)^pmM$bv9yxNYFtfe+pjRZc8zmsvxj!5&cC@qSh30}tcKn4H(GRAoq zH!z2a(P2-OQUYsUrAvn`&RY5R2Oh2j{Y{?+6pf59cv6ibh3i1|bGX_SU6JMcp;&-d zWjjcd0yESf-W{U|HWM-o5`7q%i4dy-4)FHw{0qd{3k^~z)9h>C4|hmFr`U78qXlA! zB%&9LT}*CNdn27f)3Ye}y`2C!K)kQapHS>5&3vHeJG`G)OhlcDJJ@C^zE}_3%#6qnqh47SdTUJijG^^Lj-e-uSjhXyH1VAMlF zeon-bQxde8;(1JWDr>POf{NDfsKlSoC^C80;CyhC-WhLrc_RI3ny!l=iwJn9ezD^k zx21_}^n#<75JmNz45kbcg)LOf3)^eIQejIZayOQ@rH}$sQdUMm>PT3~B;naD^lL0);dA=9~-zlN* z;E6Cn|D+i)F)T8`BG}yY0>e%E9g{-$Jtwi|QsY7^?mOL6{D0Cx1sRfFAqg`M5a~F1 zzmt3xdh69RPJE3$RYfwc5dfoN!=~6Lg>m(<{y0d}x~etF`UU8ag;pH+8$zvLJ-F?0P5EA_`roqg z7RA`|v#Kof6dRgraocfJEpHj9xH+9^bA6P=7aiQ6n+Kd$SvO zrLBcWu=&n-8p^qF>Ma9RIF*Tj@ASy4g zLZk_hJI0`?@!tMznKQtAlCv^*;&iIH-P0JSUzG|8dY@+Igw(xUskgR*w#-#XV#Dpn)JB55zPw-c-`ZaC7^g_U2$a zA0VeTpCL<)urA7Et%`|l2VSq4=MF=s@eDX=^b^x=RWNAH|Wt3;gu9=|nmcsJW7Yw*W*Y?PZpj%IGtswEe%aueY&UFet zv8}leFt)pST|8Tu$+beyaG9kZ?EK~SqVwMhE2KnQG>ci2x>p|<}k?vZ8vRpJDE27g-?X<_4Tu0u1;qNkc2OUgBN^NZ_ z7-3-&o`?ZFd75xH`c|rrxaJeSb_Xu->k#FTw+ahn8 z@EB3r=G&uoUsJmgSW6T%fyz_fO01A8R~L2}4b4WBnerRhbF2{9{^O0^(@~U0M?M0# zrCz)hn9~wAgV${<144If8+w#Ki)TX<8vSWOjH|$Y_zpg=813^8%pMj!76shs4p8I` zdGG$2DR^-$nTWm2r?Qj(kwDwRR|DQkjdAB62z+34_#?!;GashWs$!Em8_xb<@#wQ^ z&F7mCVX*a6|Bpg9w?QTcS3JlkbC1GHGdK6gKg*He=K&@xy)Fnvhf*o)Q{ByACoISc zvlB#NXx)XN$vBwG- zT^Y6aODZxZ!uPGej7I0{ytz3oRR%(}I*>^J*pAo9nOa7YB$Ah5KKc_4VfT^exv%R4 zYdkm|!2|-3AXFq`$;H;`&gd4k=iJ$HKW@Z1G_(Xs?@Z|wjQODxUKt*LxM z-))4Ye~o*KvPUr8*X6Z=0cnC}Qi^?-Fq2eq@A?^yH_}SABUACHkHW-d7FPv2>`z>R z7X=#)_XQo)b1aKvWPA_?tItnQrn42UIAX(GNPPi~6-w{-og52}j^f!DL%+aB6} zuOED_ubLuWZ17I_gHj-prvM!+48L8+! zv0M+0pkB5l4Shc`Ak|^>H(lrDf5?U^;R~fZ&Sz8F)4;O!P{EFRdN% zSuo|YGF?vcI)_)r8t-`m%1TEx_Sryn1!6M-ks+JLC;PQ?<iUPK2)7JtFoEnc3f8TWFo>mF2#zQft(7;%2PL(l(V#ZY#=0R){nSa`$b#eTOT{ql35c zYUEK`A#iuevOQPIjsR!}huYbJya?BRcf(;(GugA)C5E+WZAEd`PPuac$mSH3fG-@} zMN<+{He{Ssj3Yb@F6>r=z_P*#a<!IdzQ>;Zy5 zxpvW_;Na=wBPKUH5$^|oTfT;P!@|qmcNwB9poPCO$g6!I{BCUJ&ZzaB-xZnY6^YYw z7l1St6~{7TU`3_MnrF0Ky2t0u=ECHlQ&Z(q0Kbp8{vt9-1NeHyjZ&U!1{lE8VxKuUq3m-V9(dEg$ALxOA3wkFHmNCdi zb9C3i2VSx~;SVcXpYb8=jZRu#?lHXfCF=)j%Er|*AB>kkAHE)5rH80TN+}Tu)y4~X zd5$|Xsj#Z$WXKJj&Lk|rdIiN5LGz?N#W?biGxwqPIOw&vLnE$s%}v!S->oJfuJ#w9 z$MKrESw$3%tuR)sse`Lv346y0x?u#+J7_G-B0RJO9DiI_e~K&sGSig?K}~+`%&n5* z0Vy+{F3`b~(p}3I>7{T`6k||<*_41u7*tsF8+NcKpIfSPV-$0gE-}wL|Ii65B}i?k8L{AHO#SErqTl!Z+%PwuL8(&)>LPN(Qvp z9LH4**#_V{+||^@;DDCh-9`l?%nUx>-v{c)Nlq_$eY}qnkeXr3!ar(LEKku2xSPQn z^jQ2l=87xi2w^v~^I{?dy}9=bq)nP$ED1TRSPPsPvrEGc^zW4sk~x$c;Yy;KC1lc- zuA1X2$a%?N%x)(ncSy8+#H}n`wFF(zWV~TksEdv$ZZ#XAGjBV9^;UyEb718~%Ul@q zc(@7Cu&Nh?+r%wnuWZJjptn>oJY>A{u%u_=y1u5xzR;Hv{43G{E)X)%5if&B1vvqB zXu{%T8ODv>7;MI;5_atB`#6{Y6Oa*DB2P76M75ug4F9*D!H7 zeo~it+9M%|FDo5EEkPr=#i0cDT{xVUX~Ea?Zp0BYHDvxwgx@D~dfnC)5}jpjL4k(a z2l_4h;Ci4MhUd@;K2@Pe8$mNVsb>k~wqUr<5N9bmRzB`t+#|_QjTFYX2J?Qi+j!EF%FI%w?gFr1OV%U6)!fSxmgvO#|~ww2Eteku?3r9s9{pDNvaFhplFd4mhAVBtqE(d38)pNGMhSihoEu3M0=$M$vY@~os)e1Fd;@$w z#GB%s^8nGt+tIe4w$ZNkA3#NBIp>AI1pQ`dn)kIJn@OD7VYay3F@>SO1Mkmj^i@=U zw~02a8Z%isHgU&>9Re@tG)t8ntpYpmbSJ?kHhfgUg+$YBP)<&=+i;%#W!Y! zz>IESS9G^BKAL_%ze}*^b#MAf%jo6D=1xae{M^ojsR}O<6mNQ zWLZv6ExKr))sv>a5R#AjO@Pi{S934alc58f!RV!%%LLaBuweVhK7l7r9X=O46iJ*) zoLHP`PI~yTR-;3Ml6RzW@)Zg!Akv0!7x5-in|+x#%^nUMSQHoV!2wYQhI)ohK{l8g zM#yCHGEC|fjz0hn5MP+t>hi0R;xQX!M{7*FJY6JcDSuzy4o2Ma zq-ps5sUIX~EAF$qaGxvYJ8^;m0}M*fMS|dXSGFFaED5S0NIlmiYCXI61X}E^7e|Ad zA-O?3R*GX73vD_sfDi(^W(q}Xu+^9_57O1ZFpyVJGv_bKsVO@44EvAdZ8tbsrT1D_ zpiLK(e6Ng!)=-;RnELo-C+fR*75I}Mz(a#~aWfpOQ+Il~ouy#4!jn|AadYn@vOAjE zoUEe5aR{3Md)UT91^KMG#h;Ln*Py=kLO85J=>VAiv=`~0II{d-lF<+@gA`NM!QQazM3`KziFo{^Sjqr4&4ivgd~1G{Nlq$lh7FlJ zzJB+zl8&`K0p3B(R8R>fxw%XtC{)hN+3dWJ>x7iZc4JZ{?|K z(`{OHV}el5-zbG+Yfw3R#U^BsjL7?dCrY5t4x@@{;IvVgS4(z3hQ^pvDtsA4k(sr( zGt=I^Ya#EVExfrIz8duvMDS=F&sDLJIG;|zrja<040te=?9Mi#Up$h7gHV_H-HH$` zL5+&$M{};HGCOWn>^f8~`dhMX+0?D@MYre~l7#XV1=o3;5!H8Nlq;FLP|oyc#4jO5 zN1rbNJ}qKaRr#*@au!_sUbk0#lEx8qQ#p9;ms6Foz_qe&FkUo$<~NaW4q-KANDi0_ z5WTTFEXA0mO269u&sWTY^vkf1<|tymxZu~c+(a4y-puTQZ_kCvAf=JrwI>ZQIqX3Z z_ywO?@?@aBC@3I1eHCZ$8ZW*F>vPi9qQf z`qIehDL$l*1}fRPztw$0IHuH6!ODE$lU-Lo*`bJAKh42$b$ zslE!Q=B!z)zS&OU6a=EhrmJUxoNYQRCO2Zy1TKDTU9*}4SGyBa@YmTdBkXF>kb+ep z$o4#LUA;sM_-Zp&Bv3+U&J^VnztOCOIc=ZtnWyo|L-B6(=(%ly(a^je;)h`R5oi;b zr3kue#yN_4l$Z<82o_(hYXPM8Ke!rL^jmh0MI+6yj~>Y|v#j$wIRHeac*2AgZkYBW zg5!yu3wW3x)u5L!4>QOG?V@kYrCjkwZ?PKsKRv%r+Iv)30P&Ll>`Px}(}Ddxkujsuhl+Y?s!t0Ae!&28<~{{V zD!7wA^a$r)QC|Vvg}DtFnVVr3?0Rb^6lg=e6M1r*!_4*$^}Uxauq1h)NKb8GoTKD< zbR&v*1*wR8v#Q+r!|$9_8gqFBRu5)g+*|)gnS|_{&a%B%5`z0@7Q$!%-;CC(ZCe^P z7c-d5IGlT}(=lwg^Y}{sfdv(~X_fdq)ziu)zMUO$_iNYh-lvIu(U0ja=Bv>JK!*&5 zMB;4;V1F2%%HPY)#S5-ypc9(+a&PLMO14O#(;S{%ZFDO@-c!3`O;LIDB-#>Dp7E@e zO?GQn_@WeDy_%j0GkcnF0pY`G+qUUmkJ2ZRw$nr`VWUMvV&Pkt!s>@-I z;;u#M35*ZWD>lEdQ^LF;GW^3}BTXOSK$9yTo)=XQ0$!EbhaTIW>hCz79zA;5MT<4Us0 zugR!nalf%wwZ_tlG=xGPhDH_zE1AUnEBW52H8b%fbjW%Y2w#x4G}0tjR#pQWEx>CU z0-sS+&(OOxhz#V3Mz5M_E2F)q{LWNAV1;AvV)8_2Mg3D~yYsi877{Fg5_+VG0K=@R&lmhv${6Z$vy>N)$kH* z*&c`RH21KR8uS@tMx%L>Io+Gu6AI>m^G>;4Lpn_CX2HnaeCibe6wT$u%+xVq!wD@m z)<}{Kkg#0?7{S=d69eql6e_!HO1bQ^Br6s8%nV?>(jABZOD)=RSuk>q++vUB-ym)Z z@)*EfM{kB@^_kH^Tr?QB^&C_YxYjfK!XwKa)J@FpMw7uh8Z6IGMGVB z17p>2cg|2S{usFdL879reJo3cGY(^b!wIc}_zY{go>SSb+AX#+{eK^Alm|Q-rORd{ zQj+baE}e8qr3sXGtj#6^7y27K+0_^hQnh69PJQ$-tyLoceO0uGE3e$H3f!0z^i}B&oxg3C+2{GxNjP;8@ zr2u5*!NwkFaiMYt6;8P8H~9mK#*bCMMpfMz<28F*^=mKmv^jP)@tc&(T?{*$6Q`|l zWP414#$OE!p}`edxg}1%^guSLU2&e|sg&|DDZCV2k;^Ypa&J8TjICM1y(JpOW2-<; zyhD0h;Wb=Zz0v6I0N(>Z!AY%?#_4;}=YR=Sk(4K=Zjq6_J!`!iOUl^eUbM}w;~CBL={0E8e=@5n z1~GKdQO^$UwrYhE@Nio!6Wj{j{dE!i5nFDir)E<|`@2Qm1_E>%nGz`t0sOA7a7^D) z*cAd4Iik|0oHF5`&3=fJC=Tj^NN2r38mHZQ0SyjxpN1Im|GR{gh17hO{Twdf_pa~H z+p8QXt1tT(;N@o+@gL56E9D zX2)|!VzJB*KIwF974feX{fi#ik7uvUXzqMNoI%Qbm%Wgc;JreDknYO>OyszctP^U) zyYHNwhbpaF*NoZ>vbr^|P?d4P4J;h*r!!vSp7hjCPEdPw%Vs}am_pcS|0|8U0%|UC zx(qdv1;^V}0YQcE2$L}&b^z6ZYvlJV5f#& z1j`TXPy+A3=jZ)P095yG6?ZTH4*(3I8IiZ(SDtfXVLq&tZtjGoe>t85y_AysAUwen z-qU!4N!_<^cT=}8RWr>WK=wL5RWK6hfBW^hsY6ylUd=#?e?LN#8Pf)vHbY4K3y;1^ zjc{hF&<)P741Y{o;$N;0~ zHMwE?l;d{cmRHwam{<&Hx1ei)pbyi~{5Y!Z!~R2-_w9$%>rk_9tP8PcqyKmC*$MWk zAqLSE6+TFLF+89Y8x~Mn+f$_U?t8)AWIFG}li9~GsV_1Kmr)W*Tr=3xNJlYxPg@ZN zVUAnpwu3DwpnIipIxrgW$`P;D-ckhn+6}o*8Pkj=pu_P+IhXc>ah~z2QZ2G?^dt|c zQ8>+<6c{rD=4?>@ox2InP1g;&>NNqA1)Z=ibtbDpbjqv@EI!>YSDfiNkp4m$YnC^6 zM4skA-+sbwYX|2gHsv1)+ZnJ@FG;#i-Nw~yYR6m^uiP96b5kLd#RWlC&aeV7hb?NT zri)ZyNIOKEHkVSE!+qpg4OGe*PWpkAMzE3>yL|KoxHbNxZR0d@xn39|IpW4TXyS4j zB4HApiV4dLBw*P_1TYkOd|bq#ng4DxJBt2P>$j!U7*gDa zrEjkpHwz1dh}8-UxYMb~h{$B-OgW*{L9dqJG(i`gzG5p;P~b;FrO{45++*&<(4~x{ zSpT3*908$gPSzt2>-jBv?7o&27uqNkVaGSWsr`v@qPwlLm7X1~G+^%On1RN+#UR=0 zDdZg~3!h&AlOwX*;cGne!1D%^z`W*9Wm(upvH(Y?O3WVMwM6P?z3Yqw5A4l8S9uXK z%uleGlS`0bZfS}Hf&6W54FvkcH@A6xVdtXaX3!>(^-$s^PT4(|Ack69My^15Gq+<~ z?{4QBNsTXtOR)14O+ZIk=`Y`&h~zAo>Ec@vGHDHD6U>KZy%I@;m7p0Cgy^`jYbt6% z+gr1hglMgvNJy`=b6~^}ki1FbXw88$nkUac!I4O4OQMJKOUa*wFV0$GngjSg@h238 zKd6yskv4J_Jbe;1=!M(`RJ#DtWYbLNDJ+nZ( zP*VKCIKNDRiT1}>KbkYSWSH(CW~BkA0%cm+MjU>`REI;K<%gC!q?duwBt6`OZd%N% z&xN`weN`G8q~%+rQ8sJr>01>s7VrDGlT>M?}WBCt-{7x=5L4+W^JJ1icZ%<7f$fz5x;~&Q2EnTw?CqGf}^`S`1dI=kZ0L zyboe)EZVyYC!dnSha+_8iIvR{qu@xF1aJ2+fK7*-dXQAQdt52>iJ8;wETxq6IjdQ< zF#dg`DTjK$$f~!T8){xnPcuK2mQoC2Rr;;$r{%cw- zOF4K&USsjiFhqHwmdCMOT#eE(VpXho6a-$IBcWlKiU5k_yot0s0g?O+%8n+hbH4RQy9R z3^HZGB&*@=4;GXvelNuMBuh=sKV6t_@pc*yGRZAExJa%c2ZgTb6}^odPQidFEaFow zr_!GsQhg_FB9=!Tho{+JmAh4c&b@0?<#IKK`1RHD8Za{)lHVPLo8 z_yp@syY#?RkF_1?@eLK_W}?;b4ZZO2y2A<>?Ro08EOdl`tv3MZJLj;XFDt~ZpX%h< z6wdr0Dceva>?M%3-6Av}ZO32r#cCFUMIDlf?Q4a-Qiz&0^PA{|_K5};qeyT#5mn?Zi|)bOG0p++212y;Wf%x20iSv-YcGohw;>uZ48XvDfRZn ztue!UHIYz!*?&kjwuVr8X|?{lK#&z+?0D$T_p}3sA|3Zh{hgPj3$D}rMA#3M^5)4Z z(9T%4@NuT1{A0q*n*!RwUZpdU!QizOK>zV#c3xCb@X9z+66iE=a}2h)5U7mBeZCoj zmjYF=@A?IS$QjxE#)yYpeeJWZ^Umx=89aU@FOpCvO*kr|NNpb>Do_1y@u64^uAUC{ zsOPvt7(7sEmR0dsE7`WRh+#e1dh4?fdzo2iRJ-IaBsI}=M}A8`!;zX|;%*17lU=T{ zs@w9Xgt$xz`jQ^omE^tg0bzG;H_M3Nti}Wd5UU?tT<35!vWPgzvi1!srIhVzNkWFA z0)$7nCSHHqr63M{2cHXyWN`tv4pw5~9FthP7F< z6oyax%Rm&4rH(^pM~P{l!irCmUQlh2NhS40nHkYmQMgdAM%O%hAp5p4RS>#H@|%=; zBHJbZR9%r395?zqmzg{3Y%A3TX8oj{0n6$?+L_VA~Z`~mK`WYV2h0LABvFd{C-~UKsrQC{Bnc-;-yV8{@igc;a0z6 zclM@@y``k9v9)s*_vD}-^-{OeWZog%&~6H{V&3nz()>`OqjN!ag03NqH)%rrj6qf1 zRl#7)TNjZ6c@z_!U#i0c$c_wf1ffN}d@=hzE+m8+^Eog{b1*5;{UbfRUKNxo(Qm1X zlbYA%#GR4g(RL1#nNG!xzVrKog2~2T68Us?W4E`j97~Jm@k*4IC3Ii)X8~=&an}nu zdn?BhlR9d);Ph(=|MP;s0+bL7@{#~WK)Sy}<&BwExW3%1XaX-mBJMo>ejZfffToU5 zcV^s*AcJ9@sCmqVrH>Ge8j^e%?cleLF=9lGwE~?&)^iQ$A3UlSyrzx(oRWpb$Syd6_U4@S>t`6zy5aF>%9rtR3D_bR#d-veD-u8x@LBeZ~(Q$8%gJ!m(`6> zv&1fT4khU}ds|P-H+XMqc441%qkkz#)1VeKCKSeOk-o*c&H6L^&aSaXJ(k=!EpOCj z+`5HXzMT0}NDYBt7<3+L%oIy;5v*as_#V%ac=FCaQBHU2eOGB_5wOO&YuEkmc6z zv?d;JEFgl57R`wETtwg|cmFXoeJ*rz%)1Qbg;63EmSq~IFUCV^{vvY0SHmmLXnnWsPlWIn<3GU&cmOO$q4?{Eex6`KEm60THZ&Es8RFz+(FbVNV8L z%|I+w7u6i^>qf+Zh|iK@S7fQ4XMJ+VQ>k=HyO8q>k8I}P9S2kJ?I=erWp1|o0rTg*XBcAB5cHhizm z)Y{Gj%c|~2b>~lmT@~?OWVUXC1c12T)!}h@LvK1Yb&+mcp5ov@j-f8rA1;OGN%Xky z6UvXDPY41C%y*iXhEk(-ov16V(&&lZvu_x#jaLY^#E#iHt^7vWEf8qt(9`iHYlqru zQ@D=!ZvGXPk*|?1+3A$pLGGKJ*Pxd0z?6~gIao~`kehx8^Iss*6Z|GF#uIs13Ub)`bmyhww?6a3<+Ui8*XUQ$2DafZGL_`9zPhs7R$9vmmF{WW{ zz1Oy$N0t27GEwqBvrsdJuGT=SO@&Hcr*{Cc)KrpEC4*wgXC&e&wbTy&NkejlE%TtC zhCyE)I1G@k`0EMx0~Oy$Nke`)qZSyQ3!bc=#qo&avpmn`$mWbV zUdRg!RtVu!RS;zc{)iopl4(L6F#!w$7l`CS%AR%J3&^WIoH#h7ud#c(Psj0tG;W`A ziiI%0kGVvUXGj0_*PYBy-N9(5rx2};jM*T*;07E z-)7$NBVKY8Yco@Izlp0T?Wqc zC|g*2+xam`$%-&4G+8NQbrcRmpE+$_#@lD6mRqR})x{B_EIjB+6TNlUd3&ty-kDZ2IClLV(ZBT%FDWot!)SK%gRsJ}R3 zw2yNJcDu>H0>A7@=0>~1fAYEmZpa`J8r2J9wt>Jac{Wtuq}YLJw;F$M!?w&Sp4Hp7gB>^)30YRl$#?&6kPX$uiH zdQu6#;P4CA!ud%YRLJK3x79@gc0YXd+$!RPgN2zp`Y$WEHO9j32KJm#d@ZqFsv>5i z${LXHikzg)Hn_Xm6oH#Nk!~gM$z{jArc|0Kyu139$M2*fd`pRZY&ePEc!-43;F7rL zW&4Ej^`fLU5+Mi!LPfrxwW8AAiO66&P_tmT};FRM_e3YE-1g#FX#K+?+Jt@-m>kWCkZW;3Qc)&&qG%1P=1UFN~y#hS;#s zTmuz4XB?ipsV8WD%$AcFq4Of zrE+R#dI8GU(`W_5M880qJC%5Z4_OVO@s}cMXHVmngcM9f$iy{3TTirvG;wiuEI^K; zr!f`f+*>b#3{{Jna_b3BwcUQZU#L61YRd8S(@;bhL(jnqV=NbrPc-Dbt_0xNBu&&{ zg$6GIp+*cN;GzOZ%v~g^Z#w#blCV893%fCYbe9J;Q~9ai#oiDi_=z;zf7!Y- zO=)vFs1V?QF=h$gmKYZq-FzKAWn+g{+g_R-{vBuJ>1$=sZ`mwp&@|N!rn-=(@wG~O zM3Nu}(fXRq4uyxva*0Ni{m8&H@rCR=lQRfR%4zOX8^yw2-Pcydp5r?;pd2Yne-BdG zmuH<->$5XB%;Rq58JABpYaT+2rs-Y@&@*sc7%{b(SD)Q=IRlp+A74(+aLN9U2pV4g9OaVg9ZH;-d+lPxJMYy|@wmxDI@`2;EyqZz>?eQU{qNrh|O}apIxEoogKMNl^KNwNFmIQ#KQlEK|?9$-7&xVCgPtlYzN9tEzKUS-sVV;%+U}irwd6 zy*5f+QG3M67-h4!-ofsl@=!ytZlODJ>@Q=lgeT1!5MzK{6tTe8UEWd#s=;$^=sWXM zn{{2;TyAu#5fgrDu3L$~sEecjFJS_DCM1)F zQUWTTG%LY}dF@Ap>7?cT${+J_>t|N@@hIqtix?GTb=$I=HOf+P-6Va2z?HeATp%JJ;B3+!$4~{xw z9R^+xNM(}n+XkI*sQ&|a_*bveLsq1K?=)Tp|F8dfalmWlR7ftrc972OfF}QQ>G0S# zIxw2G2)=j!kct%8)V9pAnF~tAtB8HqsW(zGzm44`G~pSqV@Ugn96P50_{X{|P)GjU zY)Q4OBZ_5LiZHf>jGcWp0G69%X}(U!OzH;Q4!Jo^?Ib9%Ac8Uxvkd`O; zyeUx#^RsXmj1r|u%8j0vSzz;cakv)dDo~huez;hF1$Cg&VKHcuba=Ix-+wST`f0b* z1)vofC3V9c0|X6*$DDHnwB6?!BA}dOdRd>|$B278W5+1R!G4E3``So|14FX&*I6!M z|Al__@2QhD=vOD1xwYsqB0JORmJ@?_`Oo7brFhOwjc$h}qjcYao!4=dau`q_h8*JT z#b20eVdgd?^O|*6jvG8sqoSfz(r3LT0K7=|@&YsHQ5C(V*x5fosc4UyGkP6;f+Am) zhCjjjG$okCu*4}bg9e?>g!Kp0U4R1!X)JVb z!l3Q-0x)yo%*={#2O8tPkm4&fIxaH0v9F!uKh8WWM%KSl0c(|6bx%i=Lj%+pi!Y52 zWDd^%xc(1Sp&=e<3Fc$q)D>k18(DXI0>6Dq;n%0Uo$?#s;Tq&p#m2p}Om)4vc(N<; zoVGZRbgZEz*?k9TxEOn344q4AP67j9;!5Kzw#h4|*d0AM9OoJ}Nz);+-TzW11hIs7 zbR*7NZ+43sOeeBfpj9jfwg)FtW)6r2r~u{hOI?Q9**F}p>yLRv?n~~mDk5L&Uy89* zYPCTLVVFN}31Pqc3WrHXpy8xu6kKD7*VGLwvScLKRc*DuH)ePg%4ZusSu0SbhH3=suPYI%0MyU!yEuG;zHNmafi_?S(Gt77_b^7VOuRt< zjy|qXL)lLSiGSpamOE0$Lakdd6M=H^X)^uXPsM9fQmv zN(kjpEO*qg$xB#HMg)RlRO=BBXU^R0BHB+%Td{8R@xap@TGraRf`pQrYo{Lf16|i9 zsR)-hqMX|5_Zg=0V9nyArS}XU1!XvLrL3TUnh7Ge91Bn>rgeEn?#}}qfMeLZwpd?+ z&fdygvbC@jG~Xx(-goSdRFAm;)s=d(vD9=;WN{e1vnKD2t(pDDEOTwAC*9OiJ}Mo* zTx)pQUEthg;B&xhR0shd13*QzrE(`Q?OVkL0P+G$)$0Jmyeg2;NjhR=6=0m$a#`Ts z_nMoVUVd0AG29V}O9B>-R|k9_6P3KTyaF>mx9l>t@?2bJtm{+lsjws#LdwC2 zJ-vGe8mEL{eqqu?U;me6Jq`%aF{WbPZKt2{@O!@8&--_*K)T^Jkt`mU^ky;*J= z7srk|_eyA>d!PqA2){ZYYH`br^zi#KE7O+Aq%BO323~Fs_|qRSM}ZVttiCXqPHnoG zTWCM5QPL4?=av8AAC+6sqaD~6swH9R535R-L+9j8&&NihiBX~zY zh4r#SV?Xc^Uo-`)8AlLidWOh=XbSO=%Goa`ZZL9}K;9ppe~Q&*CAq0(3E#{6qZdDUCG===3UM*BOg8{u_yGMpvyhWd}k9Z-?r-?w|u%*_Ga_cPw4^I`#E+s z#l+^AbtK8IT*3b>R2t_mmi{c_pygCA^)HkthVd**_!bsMnW2GqBjUVzyV)wT>(xE= z>2?)1#P9XEv`k;X0P#QSK?708B9_DwCz)GyAl5bhIA7B(+(Qm6ahpQWi2m2DLMo6x zZNfgBe@+^>bJGPdVJ48}g44HSrsGCy3HtsgQ}JmISQEk|e1LbZ6d{SxMgXglqm8PN z%SJCfioh1dNcPUWH$xw}CYMR3cPsk!G(s5SpXmdv(&O6SUhm(7t&@~n1QI5F*b4UFs^k z3sR9zw7Y-i#3GVX#G~C1s7p%KQ{N-D5duyVt_xaq0q=`x9=PcOkH<+z!B=1BTMc*W z9+mg!yyNZUWznfyn$CRq89_%>U1+UeEN0-HVRe0terLgurKUHC@7boT)c%BC{#NFc=j_(mX>L7Rg+-PGre;nJp{8Nn5TgRYs!>mG+cj>ubzdPhYP+R`(Drj>qP;ZlM zFFmHToUa^_qCNi8odc{15w7Uk94L3*=B(O;UHcubvgnx+)WHYQiJK>RA8le6dr}ky zO}$f7-zun{bQk4Fa(MfCVSzBmo|uk1SVW#S4P6%@?p3c5xFzgVHuyu^FAc*`=@J^H z*AM}PFU|?cXjPHyx8A&FD5-tt9Ph**k+p-$@W+{_Jpo(k(NlVN^alWfqCd|uSSVaj zGsoTLo~@jl`j&%Rue@i)5$yg^q#Fb=nYQ1W36@rY?<*Mgw{tY}`Th>Y$&Gld;0Tn6PX-mgh{DWpk1J|7g~&5}N4wxt zIeaQNdbUC*w2HUKM5nZk#pGIc#wQ0$gLF($*0|g2x^_$5Fv-KEEYH8tzf=-`HMDMY ztq~j$w>;0r;+rL@f4;UXk>pe`N)m1Z2J-iNX)KHa(?nU+3q_C`47R`^V%MEz+N0;_ z60$(QczfXNb4zkpda@T!L#ZMvTB2`5e;EJPpf1)+QZj4h!QkyfM>WL670U{@>Qsd) z$3C^&LH#VGY1t|h&Dpk6T06T4cVM)(wq%7b?2H#COu)x687{Rc(~a;uR!Yv|!@tjamBLn%g^Hqhu@l4zU0N%`hNQ zWV@uZhYo?EyXzmNkzGM3uwNLcRSd01iqb5-*}?z2?|Gn^=}_%VG_n zqjQ)Q z)sx1x=e(HBE?PCoNO#?`c{$o2EQniuh5QtLcw4}5=vHs*c`Fg${iy_-%&kYt!kM5? z`>C)9OV{#uCvLYmS!}aM|04I8!fv8k`EQ0FOCB8SXMvX&4*NIovtHKhH}1W#8r@70_UKcgQ;hcD z*i|U*WiP4MR?N7?Bg=#D-kG$QGO3o{Ht7*oMN=GbksD{UU3kJME03CdyUU4e$2~hH zBpAUxxYSdHX?p{VBU%kl`}C&oVe>bbeeDEj70c4^)pd2{9P1Dc2%|k?yd6<0N!W|x z19&)r>}2Dx@kc0Rhcbv#z+v_;f_SIY);juI&&J)p>Z?rA0r(i18p|%DbQPQMKjz}u z1jWQem`lyRx$17(KFcPJtPoDJW`x@o)zqZj3Q5torugixGl~XoA_{?#c5tTGQaKwn z73Sm%DnGIwrOz6M7~lF84k+Z;a3wFpMEEY9P!mvebpR6h&Zwmq>_st zHWF~sS7?$?w-jV|a86HFu>ebW`NxDqjVd4CQcHiirjGK04*TwIY%JIQiM+hlTNLGC zrfa`*yWT-cv8wiOA_s2ekW%O18E({hmZsgJ1tSJzyC@k>inekAMRgn=r55ewwnGzo zC9?|xEbudn`l{w!25{B>ePiBdSjMr9mY4|yFnwNG4xoYyt+MqrqjlRSJP+*CxFeM1 zHy|qg4?!>;*?JhhrY}4)?b$A#fxJbsRZ7wovQ2u5Z*@E$t3c7Xu*@Z^kpP|CnlLXq zB}UOdEB&N-05Q49RV)KE&05=m-@Pv1cRTOtxla*u`Ohbo0B!>MPE-{5PID`xkEv(8^oc2fj7{*s|H15z zsws~P1Ki31{YQC>a}N%f2VHl-J!1t1bP%6i=}~p=#l$dghg{u4K1s(yH}`!GHBXMO zD7S516if1!51)@NqtD##*pgchvtdr^c_0f|Ni3oMZi_NCTDBAT2{hKrHV0bhncP3? zO5#hP^zS28Af@ES0-fN{p%zC-41ri~U;OzIpqv}9dE&Nc)GE%IjvodcU}tsLA6pfC z2jws1%gs=q<)FAxAj+Wv6LDd+#6jl8M!NAqcF&LMlEa#3J%1_F)wrGBf^i^C7!7`W zJwy+i7}Q6Z4d083vb7&ZsjER>Yn(X}t+YOw??8kn>QcfN()7(6rRmuo5fk{!HQPG3 zV3YSDye|4aiZ|U>OwxSXzeIQuivSh8w$%(vwUy(DlcT_kp2S|7FhHj+X0HN$+COu& z5W|VCb?p9J>H306Km!ey^y`tQCnV}+z?|!AMgHvU3-vl=;c?i}6oL)h%S1U(H}x*; zmxgiy%0=3Tsd_DJw_NzD%Q7IkuVD(pVb^Yy)G5%`9$d{}8I*`7$R z8*U4A9o}RJ6{2ksX5pxrI|K2(xg{kBr9Vjba;|qJFN3*3KKmVb-;s8nxH{nmfs=u> zWre*MET<{*T)&&BOfFvoEW~3Rd1+^pe<2zQ>x+9P4O+?2ElIfuM0lPofSJ_@>olF? z9?WvVMCW2G-q}8b=Zg9^^y}nhrbpD9=DA+Eso>0 z|62lCJ8t+7%dvabenG-Ielqe{cwIP0U0Sm2Gm6l}^XY%$%!PcPf?S*_B9lRZKE@nKzY8_Y?KHM>Zr z2KN5gRAA`4t5apy$?&5tuer}0u>f2=|F3ZS!MrZVad{2Ap!NDE+I1fn2~puzM^`cB znQTdP__`IzpW-C$09v&qyFfifF+Pp3SB;*(;KXazQR1M(#k1&qhj&@XhFYedz@lrH z0-tg67P-FsV+C}nrLab}#h)@~V#`A}0ZWu7{QR>5km4u~rYCd~`HGV2pT&&TKSxeO zDO8D4fCSISyepy8iz8aC~=phkvWom42|7@@we79 z_X;bK;7)axQ@7DfFA9`vse>jkD>}+t-~6(mI2!4`)8Qv0Y!jtQlTq1iuVbYSKkc9V zW?kJ#9!+BwVq%{VMrs7v;mlxcoB*a@WCg^yn zfj6L?sdb?U`~5cRVo}_T}S|8i&xX zjEJ$SQWtTP5RoNNc6vp6_v?P>zy2%@9i|FwSQ28f3q(Cjmv~aI_}yO@L<$16zk~s@ z*-Gs6@slNJ=tihnHN6auTA#~!h3D{;?~x=cua*@Np?x{vhFRZ62^pa*rTWzf}<4(WDPZC3>SX29zixQaGR>OTj9E~R`y_&6wQ~XrgKD)D6h8E z7!y#hebMWjc)>R~qhTJgiV?#C}mOOq>1g!dq z*?G~m<;!&ORmC{9io?HP)$IM>wOg%1ZB7kQNx5m{1Pm9~^Vv51vvdPmC;11! z!6D#fD_u;uA&2CQ;{ge+2N+TF3-(q9VOqp;j8A`_p7gLL6}XmbeJ+u7V4eb^z08wE zrs&f_4{G5s$0aYqfO7O8>tRwGML{t@Yzuiy<~q$O9V5$Bd9&CWB#)}4JcO)U{t{5` zyWRyytbb|rcX{;JS>stm*}VgUb&;|Q4Pbb;KtTs5w)tNKjiZPmrV8R3YLgd4L9^u9 zjDR>i{t{)skm%<#LP~an0Z9>zuzN&Nk$uz%$?hea1Bp!(riXja z>T;Bv*p{GZM0(E{zlwXWsV)&UKYbX}#jaLHyv?|T3YTXcgIPAV=MphaZW#(>bsdv}X!w6aC zxqixX_>P?%ys26d*y~4mQi8(SESf-{g0(5&N2-PGLrf*_v^Vtt{eo8Sd0u)e z(n|zou~-8)@uEVOmHC-*cbc^Q#53U~?_<$)_Re&(vZPN;F_}6cl~r5*;%Ujaheb++ z3s?DApDtXm22Gq^&REd@I}(M8w29H?W+JpZjj|-r0{->u9#GY$!q=D|&ih zlKSXy+ctcIIS^`kud~BfIK;(>(vGIB3R53%Bp%z(!SScn8=N*tQaJsP^;^^p4BjW! z)b!OSZ3V=sqa<2bX+oZk(D0zw@TQ0FIoLzxRatN+*|wgvB|!qurt=UUHgwoC75oLW zYLx`EH?2>d0kY|_6Hny3@-0x*o_acG-GKQ99!ao#`p8aDQV7TGYK()fA$hC#eFZqU1s(wS!^u}xblfif-%!o0iQT_Lf6Fn<0r@;RkZJ1_Y`|r=SM>dpPJbqP?uQjMl6?dk;;IlG% z=~+n7E@Iy{a$3d=d?>tu+FBN5MIg=Fl*n2qmcNQ@mwQ#f@FK8dQ*0>6F{=Y@)z_U^ zoKV17@%ZiHrd8qlFA$L!wMsE1<`ssgqDihHk+hR&5U|R|5|VlPsoHEn44)b#%msWk z?Jao^oMbRKL}g@j9{_2Z5>oqd&bjWqf&P@Gdm0C|v0}EpRN0YV@(yej3$kljiZXxI zscEndz0pvg0Ji#P$A;|UL~-6qc^A_1!PV zsx5``Eszp*yrn9P!b3t7s#(lXY0yD&l1u4M9=c9p>UFTFe2|gZe2sYr`dUypgGh_q zs+O+Q+$lWG?6mt=Zon{Ambd{(2ZEtc9uO?oL(n#fSwL3=7K~HSw!TGI6lPg%5;M&Xk{&|foqumXsjl3rJf{%}Iq@9`^?g06Ael-V4N2Chx+ysLlp zg(JL@D`>9GQ~&h`#0~(e-^gt+i>{~BEmK%TG$}E{N;A(ypUIW7dzm<|5tdhP`dZGE zhsMvqZ0CX#o`r{>4qU-cm6ACH%((^N=nn7+c zRPd~s{c860u}tqYLDf;RU3hZEKQn8{K=oYo1xy+g_2ne z0v&**t1X%E&il%1;Z1_TW z3<*dW{5#uJ0!a)$k=}F+ZmxX|Bz~ys3vvd4Np=d}o%Tp6(s?^2e&vh^KUJ7uIr(;B-K@lC^O;b)y<(>}i!i}qgBnRa`mNQO-&po_jz|VoN zUFdeVfuuY+f<-nY5W7)k9gksh?6lMoV@?-@P0r4C#zl6!0>N#-=EumU$l(+J%$_lr zv(qLhg!kngew+efNNWq4yf#S3?ELsRSF&`WaJBPHunyZ-0$hXQx*PrO(x*LXpaI7=?uIEZo}vS2LTX5`X7?5Sx-f=(PglxvDU06YiauZUWCNX+VT>Dc^5^G2ooU~CwB@k`-U@HVaeH2 z3N+o3Bvay>Vk&i}?Y5#^EF{#jH=i?1V)1g@;R3b`g**TxY%Z?}5RWt>3hIHYflT3q zEe|*S;9|>8kV-kb*$GIvuLpbpAeSs$IS>r=iR+hz9CXk>Tg7CU1}upnSBt+lM>2#M z?vC{d{J^*zX+Jqa>^#O48lC=FMKD}|r5eG}OujD02#s|LQVTJ-h@b#4gERUD#BEl$ zRMW^xk5gyH$g*HWIfSFR4wd~k)>TntavXM_mC!`xYm$n9GQQ17;s0vi0dQ0BJcs6Y zVaD}4z;wcE)c)%*!WrZ|@Rzt<9nYyYAOjJ`a?UsN3i@ z0UUsHO`sDAcT(kHw@WVP`I+>;%=5zQ(&NEQ%ePqSe~$n21EdVt9Jf zl~-q!ytw~hU9p)|AANE!3C-gD#Q@Rlr}nSEFE7XK)SX4zGx$Jvt?00Mu?y(pJGYqEiviA+@|sdMt5i#Hgb=UqDykF$rBxK`rJ{c@46UErU@ut0GL!2>dyA7s(U@)2bQm}&WSmJV1_E$5tMf8E zroPF6Q01$(nec+~?6so}p~A=# zgFqZ5u*jgSMRf+3#dPLvHC)dyYxd+2i%!pcFK17;V*D&{kDqdfO(*5T-z_M14urA%&ern{j+_ga`@Up zCh2tj>YYtN(>=+83d_WN(UTK-ITCjfNoIVX<%bh?^Z zrm`)B6bVCa#XhVZG5-Q&0r6;6Z7<@nKP(}omomWuQ0QHYvaKzH2|RV^TRp{LgIBo2 zfm`S-KKAH_Grg-aw#4wlTt8IfgG@dk73I{g^Vq7>_tlW$kU;6U#QV+@qs+QmB%k(d z2Bfrkp^Daq!c!|%DlPMm2zJz-mm+PX7yfjvhGtBZ$l8Kz+mTcF3I`S2)K7VrM19+2 zSaN51Psh02|E$va_}zxqG~M-k=~=ZqgW7E1lCYB{>5le!hZ3<7)mkV4j?stVG2n%Y>2B!Wnh8<#os-W&mtZDMUyC@x0AjeTS z_{x~3wO?93^=_}22uiRA*uz|ou(0p|@Rie9F_dofYOnqGHK9zOZ&T-lK7cj>o(jlG zNLZ-@-QX44!E<)qk_ZEtDm~q@6Bdr`4x9a4VBlkqx-jCa5m8!X&V1pb>JE2S9{1(z zdMMhV?Ynt1NaES+Ld zFgO_6Npr%X^_KyhZl^VMe>}Laf&##wm;1Nm4dVdg&9F;+EA5wUqCI7tHXf@Fva%}0 z?%3v2lpmRmB5oVLZ;jhZhyu4lGV#`nu`CK{{z>8=;@1Ea{wPtzdAzE!9uuhngkKwC zPcpIuZ?W0cjm}l69lhW{Ss*MK>4eN+squHTqL*JjjsL!@b}TN$NM6Hg9w%HDnsk}2 zQFP{20I*q*Ge&AKjZA0mb@&m-q$4Aj71F=Qe{;EG8(O!t)!khFr*=Jig4mOC;s%!Y zPNRc5+zEXhOo97~_vzdRrh5Th(ERZkv11z~tY5mrBd-GZDwrNg1fW*%)W(;4G0Yabe)Wtx>HbLY2(i0!g$r{)qE9=kiUIRD!T@U`&^GHIk*r-@sE!}5E6=i(Xv%z#PBtN{bO6*jKn4ksm7tG`0gel*$wfLi=QgXIT+K2G zH7hdsqvbCTrDWLB(!bOpvyk2sYm|ln(C>ns{hX)DX0!w95c)<_S{xLxSfcbj!pzE}7i^*g;}T~;%pv4k0jE*VG1?`FHZILu6;Wu z2~EuEtl{skxG(HT;3Hit({X1F63%bZTyyr|N9e%kgs49ZIe>r8hGhCn)($GV|}nZATM?%D#=RqhQxMgSZ}*L5P`=dX>p4is0nMs*QQuXDemEx6M82 zM%~e^nepT|MQj+ie*k}C9GikH-z(2OH2ef&U7>{tdzmH`SFhP~14LB5r6+l}s_P?A z7{qXx4ENAi)ao7V1@p~mbVkg3ayJ*&U4a7FZ7Dk;jss;=kvJ{?+bdAib(8R4{RSA-q0cLl0AEs(rNa90VKD^ZPm z-LB`&%k6izQ?QiQGPP@y;>nb&8nfBrYj!3tL=sd0X%ko=FI(M68(;eZ1Pra?8Tan z$FH?itX3fLGuf=JL5U=kBR$z}SS+1k@ww>dztObPf8wwt zd~-9T0huXTKDyU}#yX|y_R4p?xTJbzl?*mj-_ltL&%wjP3DEMq{(W<{`xN*XFxZc6 zN3Y_;-|;lLVpb<|)?D@V7#}MFifDRz?(y1jz1!_otU6pwwK=%ReOV%F9aeMbF^4FH*kpemv?Xc z(Yj-%mpQ=?QDR^B2Z(62!HwxH1&nzV;4}ed*{v|K{QC63#K%Q~#yC$iCQ@d>0G7d8 z+P6uPfCQe45MMMXu95F3p_YS^X6dffuc+wSe?@Pk*6`@jwwJGvPaZYHKYa9l`FY6q z*p~nbR0G1eH%WjYMzZn*5(2~Oq2`JOZ?*M1PWk_R*}g4hJ6zCs-L%hH)6fCk+3NP< z*;BJRqhE~Ks8?yhq;croUcAwCL2#++*FaISeUdI=AQQg`cj;HFt zHhEM5L^n*=W62*WIgmBeV&%h5P`$8XUl)T9{JV`wRp!bUO-Cc0Tr_&wq7SkkL!~pa zT?_ngq}W;61^G}Q!nhV%d1BfjO*rDjGvDm6^aXD0E8(Qmv8FwM`_qr=M-3~y3>I)3_~3Iy zWs1hYUd!c4LYkgx}Mrb>&p!^>IhF+u* zU?92XRO7e44b!x$F|3*rqXr#k085cFKQ@Iz{1f@uGdUPid%JMogA-HD?cUk9&XqRe zv#R?;evcfeYY{fG1B^3URFo|JJGS3cpjE)3?>AP~m0C-VjEl=hJ!Ep4t)s%V0Jy%f?ab*-gg z+l!Y-+T-?Zwx;5`4n^h+)BqCD*3HJvq4RK=OL7?5gr_?+f>DV`BYS1|9U}3fE`YSB zT^TtVcOqS*g=su^OWSi?hp{LpWqM_4e|z_5IH=dEQOmh_>6+3j++wAQel4UKD1Qt^ zy;2~)i^kip%pp%wb|x|F>3~L4!RR*mL8N;e&uOTjhF&Pfdfmh3v_E!W%PlhMTXJQ@ z(_}Q2P0FFlALKwF`#bo73dFY7mU`8#y#ju}MUx~1GZ@$o0X@!=Ptlsv zqjvPxdaxLzrNjlDH=NpSDQ&1EOX622orSHM)TaEhjm0<_z-)*o;YZU+8phNmGB51C1OI}t(>%je%9bX*;CEjvR^=FJ5K|C;| zr)lk`K&gZUxz{{h5aF2|F9A3`{?MOX6o^@{HLURO((a4@V53BhL{Fxy1o?L=QnS5IOcc^G2A z^aq~ zXi;9|{mUeh@u$-d80`2TonkBvz%>5s)VHv+2X5ty_B$ERkwhyQ7+P8gJ07ZR)mXaXqH+IJ#b!WX1I71% z+pWnUj3}|Y_XM-BQG(s!kCkOJllK0u>8#f=I6Vw(A7B~xot08p?>qD z7TNEuD{j>yXl3cqfX{G%3DZRpeXoJ&SfXD`O_9P zFQmj0N6EGXJ!G=y$Pn~JJk69H9zwRJtNA=H;Yge|4@#gMd^;rw-NsP~8%W zhI!md*kv6W6Vrl-PNn?&L-7mc99kcdB~7@@yTrevH~VT+vS{$Fu*fXV1M))JbNBo$ z3q00i2@9JftsvqpYog3j>hiM!(tw6qsRv=kuM(x1eE~` z;1coJzL?s~8bxr}%GMyTkhVqTI`xs@zR>dNSqr_V-J6O6?*Qfgo0V-4pDUm|(`2cA z#eKlZaud#of~(RktMZz@Oky9y0m`sfVL`jbfey*2+*7JDFlsF(Z-TEV z*q>#hbwQzWm&oC95h!cYH;4;aYFueK&r0S8a4%qqeZfHn&eA&dNJC7V>R!7oJ(Z?y zwEWTr?I7X^ZJKgftj+q5mcAKm)fd`z)lJksAY5gi3*|3)wb9X6;v=y_Bhzkx0Y}L zcgd^h8_B}n+-aW*h*fV5mNdM4LqYYO@v<5o0q_S49jOT{wik|BxktDOrgvugAs)9k2A{MR)`Ynj#9U~dkW zY(nwH`1^#M2waHUzORv^d~3noMu|~I3bw%=4_WG0kiFR>kmUbdPjji0*W(a3lg1*! zc`i+_Z~~O1}Ko{_SCkM@C;K{dN=Kuo+L3q!&xTI|F@3T2*$yQOAwQDOB5IcOdK^r+vJ z>Y#hWXl5NFUoc^;L|M3xK|w@at9x%u#QsUhXs%xj7+4g1LD@T?{8C`yOLb_=)EO4` zX}9>yw5S~mqf?3Wp{tqk3V|zgr5`|a84Elt<9>zW1b4?M8rR4cR9;<`N#&%lcT-B3 zEyKqfV3=?W8Z5t8u(Chx_2?Q(!dJ6pdT>lPYk5hb0!8L39GgJjpi0zw@FnLA_PFU) z1c3w8C|W(u;Yw_3mQzjoB$tNdU|Xcc|0L>l!S5cs#hc;jL>3E0$wh zVSI3SFaC9SY}7jR-y^hk-9xB&vJC(y0_F=ncl(yt-V$E2>xq1Bghwnwl`TzHBXXYR z?Gf(G@#|JI31v*W>(oiOTO*wDaZm{hD1qMOCz1!s>6mNFif>C{0z!iSQdJ0Q9P^}m znI@ng2YaEzR?ArdgpjCg;)^!o0;&8~kM9EbcYn${lYeh6b5}YWTpX*V8@j-&h zsMiB2a}K2i6Nf-bOQ5?y$*}<@pRPuYH9hV$TJ)gjznrcgtE2a;Eq(^bD4i}89nX){ zNdyUX*a>I+Y14y;JZPYw+*`^Wfa0K2%6I)kz4VNbqY*AIF>7(w;89GgG!KSM?}8F; z+qm%)9$&a#&oOxEWlRNLR5j}V-9INTzN9GyuemFlpc4}=#!r)t*%4@2g3Pt6g5_G` zE(Y$~m8lT}=RUZOehMbG-P}8XRVLaIX9Wt7D$_Q&syUDlvI=TFS;e2hfJ@o)TA=2M z?tq~?YW(&}>&S4dA3oUXfbEcrL8`{}YP=`!8gVq~Qo#t%E?W?4V}?A};{X@Rf8>c_ z!aZFc(ib7qnC7qcWvFTW_tvp$jDO)*eJnp zRJkVPL76ib&GY~+3?EIq1m0@8BQU)L$a12SSpklRD`Mp*p%jg=W{ zeFf*c%Iv+1txvXopMOwPDP1vr)WZKyOsE839%f7SosqSo;I33r7Bb4ne z^)v5SgfQl6GU+1yjfJseR$XTI#o=RB#%F$u(gb?vn!a5o#rM4wa%g zsN>ii&UruC&|1yvt%e>7G6dxek)ZQW_!sgXLTzIK9VOfcr?MmZ*}Ac61-z){id0!` z1X2829y38-(HMr^Oq&I2yWdu^#Ka(qK%tz{an+Rt&Q9jKa7K7Mm)v5P*w~A0hJp=L z)}`Hu^eLJiQ3eP}A6050GY#;KNRqW??-~+`@u;n3UmkRYTD@%`eteCvJ_E~H3d7D# za|7Oa*asFIpRj295+M$}Cd#v%xR$ zJWMZ#}^TkDLO&^^JsR9bTmd@=ZH~v4k6w%pF0%i!Q{eKiNVm_ z_YGedeXzbn?*P{D$6txy$*oNKSj^0Y#q5h(nz^!s;v-BEOX7VgMek(~ZDMBIl1vn; z$y=jkoafO$_pujQn*kz0EKbQ+sN=p$mTDlNYI_0#R|DhmJ=_W-^)+vcQ#2P3R1IGr zsbszbJRl4p<@7bOSHYTuEX4XHT8V`He+}&UqNXt!Kl1|)dvjffZR&7MLDneFb@viF z{`F^u)hRNPq3=SR^EBhM)}2XBWr2wFGK*DIW0S$6cjaf$u@f-TGOAW|?AWJEa%DM) zzP7H|9g@+nte?#p%B^ouFM=L z$2s(6c5n?kJ!G+mOf4=y%I({7J9!5YrM>1gV?l^T_85SX9DeqD8ey+g@mFVv0J22- zJr{(ofVt_#KuLQPkePC=|MN?9dpS*{ty<}$-JCOUX+n?Eu$Sx3yo@^lZ*|I>nQ^yJ zqsZbjolPOLo4uL-Y2Rg(4*ho*tXCHpC!+D(N?$&PDMtlgiPCjw03<1fIR$1<=At>I zDpe0Fu1(TwN@ly+Y!-jLY{``#voFrb?FM9e?!4XBK$sQ3V*jWbHDoEs9XDIN0^ zD@L-{9kCz$1bFUX1)9+uBjs3Kns>KM`gUWOZh z1)UX6Z5yKG=w)=3C`g6nG6$iYZxKn&j1Qd6W}a>HtfHBx`W#Z{;*NLr=bF{8{7-*U z4~2w9nIF=%CvzD+LWvtEH1kIj?&4&I!2QNEh*}7a=UBc0G)B%>&oVgK?+r9SAuK7G zA3iSJm0T=?tJow-YJ|&Dgz0_397?XSe?-hJlM5_{+6oGpg)t`I0H(%>!CNBEouj*UgBRqAAc^DpgZ^|pwjP*Bxr zz7|7~_6C@>&G|PCn~y?{iUYjxsRB+ayXxP4dsuUaZG>aBed>nFJ$E;J6B!{H!7}yO7xzmXLti}Eg6!bDG+B3yVG2k)>s(N&n zd1lT09(ytBcsWn~QwfpNGW@51?7sR4DYw7tB9GXTXDj5+)y9DFpz8g#nS!rl3|?BaL`Ab6@tXg6K4ECrf#`vgt0d80=~GEsM_>PWkh|OCSsHa@H&cHU<-O zK|!NmmV~|8@)FXeStKG{0BJQ;n4m4joX&Ug>-)*Eve8}60yk+7Gt@(X{xT)Ye=|ir z%vX5|QaqqEGp*?P)dx4*P9Z{Z$b<`;Htjx*UKK=nEBSo2;E31336np^;*APn)H73niUU$p9s6!FwtAU6(G551DpV{eC>8y?AwoxI&7CA?h#u$n)qM{Ld4ek;t)7-js}A* zvW#J#8*C_)MPF)-^&IQg(iJVksM>tZ1jAwwk5_NOtW-Z?M!LXTwVQj`zp%H#0Ps7A zctjhR)+`=X7f(mw{G}uK)m3vv-#4ol7L%dK%@0O~WwDfbh|aIPvr5gRxMh2U&__JD zM1fcgL>?slnbl0nDqEW&dIO}pgAw?8ng?oW9ejg+5Nhqmshj&HiB9OKu+2zwVXAGy zfh#)o4dor)Uw)(A&fZ+=B)nVGw|0SjwaZmsh$cM-W(I3DATn^+-cz_)(#Xu-7~27k zVg6e}gq8`2=Z%D+P3~}5VkQk&__B_Qfrm?&^{_jWvyB|2##TKr(7)hze~U$%;leq^ z&VL}P_;q;P(uW5DI4vRZTA8=aJ$?E<4c#^3x4!~rwvdRk_baVuGDy3}dJr_19Y0)R zy1aFHDP9jcurgf5)ma{m%FF1!fvaSMz&!aCq>xGo$YxOI&u`%B0um7TE%m27@xl;+ zs5Cj@A}FZo3jD5^$T>(c_rV6W26SEEN|1QHbTTD{!inBPhT2?Nyg?>O~n?YdJg zz%6lk=&`z3!J*%5mfcV~p|vi%*}TY13T1r>4h3{-O7`WSZRICLQ{GF#Ffb+-J^su} z+4CuUYbrzujzg*SBNUGuhd;Jhx&Ww5T#LtXc7oYlGNx)3l&FfMHp8cXmf9a_P`Nk- z??8}s*1+Hg{b3Pgwg2%106HFK`VZ$|SAi$wB&dM@!xoI`mURG_f1UF?v4p5T#$Jms zHx~yPHvZ!^6&)8CG{fOopK*5%zC+Njwud6Bo%!#o8^hLZn1lwd2hhh$ZX`+bR$YFk z-uyBicm7hl-Yr$B3N_X>#WHb!(RiU4b^#=uii>?|jskeh7O?uT05aysd>LGPOPg6s z|NRWqsrpWWhC}dC$E_YT_PbQlfnc0+x*)EAvTJ%2j@)7Y`Kx9UQ}P6b{;L6(s@$W3 z=19ZMDU}w(n+IrkOSwUVN9WSbu9P}2eHVd18!M3kWa;1(*5LX-{wo=@Ttuz987F~1 zbi7U6(deG&VIb-myZtrsT)vj z^UZA(Nj({%GR~1+A9$z<DUe2yBLJ!I-xx$S;7N&o~2Cv>3KSpq&q5ra!MSwUU<%IKK4+vq!c zy$Y>w5pbkf1P?z#k6cOZtABCjq^41)QpH`)* zwk2aTlq2ZpWq_&P6#{Fuim9q9rj9l(Ul=hD6$}2mdI`dEr3F5UI@j^ z4_j>kh!&@AkI(#}9|%ocvd`aKqoyK$L=R*tGQ5kImUn@wf#nMm@#JCE-~ z?n@kRL>xj!Adxn~y86mnejQ__Oh@20xN^7?mMD~=IYTs?@7dS-sn03#-$6#zce*_C& zdtSaU`G;D5y4JQ7T^k_%a(1rCHtctkSQW0E-cR9x;khdGN(i^}#2|-(_2GR=rrJkz zo1GO~>6{o)wF)O+U<}lft6yc_$yOXZLUag@%^vrt0u7IN4^hu%E!a(MZjGogBCi`UnpaZho9<0J*}IA1b8^ZwxLKltUv8fow}pOfXb(d4 z&R7#W6bn;j4uJtC%$9@q57ib5`_DvAbu z!RzLG-dzbV1Nm>>oesA;Xw2meEP-j;n6A=7td3kjI13D|_c`qtEyrym~)uhlB$_eeITi-0bOdt^Owz%B5+!Bkdpj3K6ruV1+$}_!8#p-+@p8f5@V^rLZO_-I9bcX zw^pD`%G%=F;vIW$Ya9JGI_z9sIqYzByLOz^GW_# zPLVqvgQ*TL2`cLFo{uSQDM&iaG*@tg=uc`Iv{=RGMEtlH#Yz$9I2kT1<@5+pc#O|5-D~NAV*Og@QWAeuJT=|TdfJv4XsVoi* z*aCWO;tcx^m+)wa5%(suo>$b;MHtU1N%|`VGZ%2iILW;6OapHTF~-IzAlrt@G81+# zb!-CuT=`;9hen=s)%914pheXqA z(%KXf+J|qIVkN6jm%=&1VQcaBBFMH$uyIp{Q*10jeUsWMRvy)lrPZVUb3#BjETFa$ z!#iOQkmS2*+W18l2~918Qnj-(?T>fR6YBYErhUR}+E{C#UdAEb=53u~GLcKa+mHo& z`o+p!r|9IXKL>~s|LoP>>u9FK0D~x8spVkJfkRJqXkOB^yFf_8+4J{QEr*MXe4pL> z;|Qpq6swyD9E)=v!~GIdK_3fhlRo>|>S`Y-U+hH7+s&~ThF9Ft!+_Ng151QbuIP-r zfeAAiuIKy39Xq}IhKs2emDw5Jxi4Xxi7Y#CO^b=<>(ypnC)IoJvkjU0 zR+}28B@D_ZmTG*P=Nv`HDC%Lp8gUe!qemM2kf-e|Es*7|={_-D8+x&c{WB#5M6)Tf z99pxU9bsS#G%W6~;eMygM1kneo*g{igAo0q`NkLF$KVe(WjvF*7-Ww)!$~H$=3Dh2 zkWdOZIoZ3pIiWuBubURmJM$fqgeu;FTA!?LR~cE)bOczHv{SChR!`7J3lDPFNCv(g zb@P;PQtx{4!B`)J{aA8Jd@DHinGN?URQ5|2tKtPcM?FcFqu;T8MX>(Ntzm!%#0?(-g!ae${U( zppBbtD;zdGCpLag^zeISKC@zqh1hw=2yv|dQdN&=9qAd4h?X;oi}9zv$ggot952P| z*@>W@B>)^z;Ah;0@R5`p$EQb?a1KBD)QN3+DSj!<^#SEoPpG}uHAPeRJp1z5T?lbN z=4>d}dF%VBKT|ADR!CtMcU8*)NRLHC+4%Dci^LXDPRj&7U+64Rw=Z)DqR@RItK3-M ztzn6_c_$gr5^{rO<>LGJULO#2Pf%BrY)-f}6eD4uD4&a4DF6VM>hMU;3xw1F0h8Du a?e&lW0000wr2L2!7dtQm000001X)@WY`H+ooF000E$*0e?f03iV!0000G&sfah=9540T>vr~NeROI5q(hJ3QtGS z!4;|pXZW)T&B<2$p4v}$ABZH|&xav|Y6Rt|rVtPOe81ojSK0dW;a;9AcfX(O4@F>U zE34y(6G|(t+Mj&eOaW8G{%FaWxPf9)(|z&al6u(cNk&Y@CA9BcBnIN}CAo*t(hE3T^aCJF=?c0MoOrhZfCF28BXu-8&=x%@FXRRh}Kh+51l*)L36hz_;8CTq12 zAj>A>^4BGNLki7#qoF)uj?X6bJ5Da;%0d3J!Q(g_Kk#D z6t`#OTdc|l@v!+3dV@o9AjQd-h{|dG6nw+@aK;G?QsxJ$rf@RuWpC@4ITHu#GAB)+ ze=!xyAiELkXB83L%Ugsh5H}Z`%4-pbxkkZLso(P6%|~hmVoD~+)45w=dI$tDtDUX> zohxfzo z7vcmu+A#bV4_-2|CM@;UCAB9qBm6~R9N2Zx3D{Pa$nsTyzQg&;8A?BS-%JMIeYaF! zp>-}RIy?prMG@vk62cdapexu4Hv&*5`R%M4l0sxG1TWp~nYc31729P-psIwFh}|}d z*5*z&Mxq>+Q-&o=%}G%MxNI?UiG|Sr)w-i>y1e9i4^^h!A=R~H*Ibr8Ww7U_kMG66 zTUTUV8{E4(s)476k1Y^h#l2@V|2MeTu@2HXBRvj(LL>|hK#!t1imz`97(%&t|Ksn> zWO|LAa+uxBgrJFtq;LhE(&9Y{B6Jb;9DN5@gabf=X)I&RKxpt5{aX?oPRq=v`Ny*& z7}{tYhIa508@AAc!_cY47D5IEM+ajF+)dGC0$L4g-;#N-X{X=_Oav}S=^u6p^aoTG zDOBJfnHQ<3X%fsyX(SykW20U_EJZY2W4{Mj!dB2*jd$CB2h5v5G5sX zvl|qoL|oMP2|_~qBp!{{o(wC^2W%<$imrlmiNy#=fUkdIzR_Gu`~QZ%^D|h&JO6-} za~FgVrZDtabmCK%YhuEhi1eh8VGmg7h}TUyZKhd(y?}fl6Kl$JvdAMFWjOWw*jb`c zdr;bm92q!!@P4P`Ac$ISC=_YpFrP;VJUuYfu3{n1YF5hl?)TS-W*W$rOO5=B``ve( zS-v&Gzq?zE#?G{aB#opR8f*t)K(@1>Rm=c8vO|?j4T$umL5XYQg%R_V9eUMR%LbId zpjOn&s`Vf*#g(W3AXR|Glk|63ZLs;Kam%G1B(G+b@EZZ{# z4v0AwjNDx8wKlZFyeY61I)5QEA)cUhU<82+7;(nzlAuyFwL!tFXhr*YVEW&a$WC(& zeN)Ed*{zz7^4KVHV78fNX0UB}YGl*>78OkzcL~rxcmY8m+#+#!_@fH($Y2{4C)rwB zvcntgDNAZSiM(~Cqa9?Xa0_em{1W_w-3N8`Ni{nJar0H=zXrO*6y`1R46= zCpoXP0>Uup_iO~a`DZmpGreucrhTdiW7+d3X>*wFY0&fbHQEO2vMoBGikG8ZjlzQe z0g40udL?`|(|l$`V&`|zprHECOA>iUBYdn)5&_k*rh8_RaAMQYx=ruqL;kF)J^}<% z1N_8aCoCcY6{}hjt)+=ei3wuiT zxdF;Xg(^Ogzls%sWqso>t1d`4lsaj}wb|hL7kJ_3w^#}6W}rsVAy0y{O+iq0?kZGF zSG?-;Xo2;R-C96t(%eYDF4h_`0%OSy3uTA9O^x?3I}_tpIbffekuPtb;khChN@=bt zJQgt-9H7#nNTZ8oQfYIF74iQvO>e8;o}z-{Zv*;IOXa*oGv2qL(SY8Qa)OkjIdfpA z0!~{6%;4N%NlSDTA5a$jkuMl~j2KsJ<}u3bJ^(B5;!52hnL6umE#=+sbf_R}a3yU8 zv9c4Go$3_0OA#5~VD$O%=bHLj8xFDfIf5PUM*dxSXpE1wTr>#~pqtAFfGmmH?EG4g z&a3BuLo-hMT9D#)Z0P~yb1cTc5lggM6<45ny{CJxUELp@CGs;Z6YS zBlN+!WctDL(C)>7S`7c}QgX12L~>Y3#_x>sO6 zf%#sGJ?P{;*MZ7|mNxEBfi|bL81tvv>rOT@B`4=hE)_GEo4nJvS4Gw0!`NJjz}eC! zYTX=6CRN^FEwf`N)W7-uxTAS3A4;G&(V!dGKzk{)E=%X=7v~SDTc6kQ9D>P7G7!nh zt4f-^RO)JnX?4H`~<5Uv^Us+-hbqQAgZ0pY9O>|h1ZNJPEh+YXG+VZM~DuVuM1qwF8ERslKz zkQ#Q0!eg1fTM&>sjr%c0T`%Ht5m+athW!?!ARaYSTR@ z>3Io_-T9aF`SRMYH#>E0R0w;D%=yZIQ@p~p&mI(@)_@!9B$jmosyIK{-B@EZIv&x@ zMI4PPYb1_4qCn9OLX%P1n?IMt68I*1P=9%@slLmJozZtwvLaw_~VMrl(Ww(vGpW*fYDyKJo(4G4+1qVQ3cmFH()WE=zstjY7iS zC)9ziJiAs!Xp|m&+Vz>c0yl)@f(kDOVU_f>{u{HQ5OJbX=8q&~Nla%Ee?KPJ_xE}K zCs9d-0tL?GMsOt+uv`QScq5DB*=4rMII8%4E)%5}&Dpw-jK2~rh~GhE$NIMbK*cC5 zpaeGMpI4Z=c;(_AI9TGza@|v`)=)9l>QNr0)P}R7D+5g?rY*txw@9|zmyvhNshy4a z+>PYuGFk9j&d}hrZ{-zH8~7a%@xg?xT$f&Z&MS66hSR=AGuQz%bCZZTDV1hPu=^_XxTz_1{_ec{K;0J1_`-jobP1tMLXZBEeW(j?RirPlM)MWW`jGwi z;l0_uLw|%QoCL1%ctI(LixJpmkdSy^D3(6}A1v}l^rGN_rktjTs(Z%Q++cB=BGnng z8F-RyUmxwaoM`k-ibmg@bDJ~8OBJsr`^A;;&mDDfQvcp=afPhSqWxF(pmVh@@V=*k zP2*>#j(ke$i~X+O3-J9zDL-miahOs@>2<;t;ykl*4-|I6;1ZN-5$&jPp#Blc6_IJe z1m1Rtb$L&>>`~)VLb2RpnnFR@H(JFnJET~>@)5m=!70cxE~v0y$Cj`G+9gj7!d5ij z%%G}y_M+(d#CkvT=;`b%2MQtgN-on)7%GU~AnUZ+5Xp@J*gO7jTY6rhwEzrr>M7Lv zgzHZwFc8_ELY)j|`sEr|9N33P`lmF@%=hkk4dR6%b~w~Ab>MpSqog|`>i-l|D3Rd zQzP~r>|?%5n`{1b_Db}rgMa9obuD#@(k+TA+a!}oE2UCUr)qPyIS(a@+!!;aAbVNS z=D_s)2|RUuWpL|F@gemZIiIe%hw~Bt9D(sSRjlh+^DspL{22ZdI26fLSuw48CTYII zUa=l0=bam=nge&QB+~c<57YfMrtl$YFTSu*UlG0iCspph@Gd1e1q=a#2*hKl0z0R~ z#~TmLNhy__li7x(D>*$v0fT z=y=c=5jg>{Jx?oy25q4+r}Jzo33J#AUW$p&85nxnpAv_QMh-wW2!#essw@;(CI~$^U_nL~y419JUvIv3O3sx zn`f;jlYM9`^FI)zHMjo@za5W~E*hwpo`v(rDCkptZr=CU)h5V|j;7?vCN^Xz{X21e zH_97cm!Z~$MKmUrM(KcuB6SNn6NfAH%&+mEB%t}5!qDt8H5X^p^c7fB}uq2okz_=Jr< znE{T_J6ychVS0^Ess>hH>mI}T)hD`vnvt8NWN05C*pXu;4=P$ETpFQz>5u{XXc!;0 zLxe5(IY@qwNnn9(!)ww)e$~5}I=c3zLP8*~;$?sCxltX6SBy)HNW%v0kr6&Zw5l2a zX&m?UG*6DcIo0K_P32Ed&Euux8dfy-ToY2WWvCR6>o7qN`j-t+Spp%jM64J@Zs`b^ zP-2f#LJDxkYmT8%~=M5%)5jsd^) z)Yu>G74JUJAE4}$1Rdz}NxXe$m*$I$$`A=@+`7QZPZ-+^_P;dxWDTfPSHeqIyGMqF zEq<(@zolhLT4W5AfDC%aR_>fRm6SdLJ8Jn&3LIhBwio!kBR zt4ZR*&X+E`t!tr>4B4kgaInSgMj!0fEX88D7(`vT?|}!IeI|#Sg40&{t0GP6vaY&t zzy!}8R8E`sTtEznhd@Z<&3K9mYmg) zexchN6>T5wP*=iGErB_5*S5-1;vT}7YYQD$2m*e?mc16#WbYT+Y-eD8^Dw-%jn6R@EYJNl`iMIo!W{^9C7-3r z(=e=aHE)WM5iN@}KyjQ*FJX4p^Wn{!>=$OqTd{^R&feq!I$~osb1T`9_5|2RBKKOS zb6@VqESXtxs(xnv8f;88IcFaj(J-NIiKkQ91dOQRMV^?|XQ!lf_pj9rpi{K3eIq`Q zca)I4OOaz(5fEfVii(UO_7;d73$#JwQ%ni1`QhwH{W|^CcQ-fTFK<%QB&}YKp=b?g zN4papDgo;xn3IX?;S{9Dt|hmoP5@nnc&iMB`~V)Z49%(A%glG;KSx%Rls381i?}Xj zn&aMCT5?wAQJ}Hd3FE+vsQn7OeN<~W>0>$$Q+2mP#_ueja0iDRL!P@jAd2D^znvD0 zeS@4AGud}sALg`dp`@(!MRZPkL>z|bd}1{G?V1PMEf5It6e^M67?JR4L(>v1lpij* zj$)dW53eYDv`?AT)G-VIS7dk?rTn>;WfAvxsWf*{7C34#NTvggo9 z5!3scq8iG9u`7&{cs}Sg|Br|yJfg6-;-S@bZpy@*(CmfW%9G>_MQqZFp z0zQCm^q%C@oA&Jb&WFeMlcReK%?gJvy1AQ4SUfE*3v`Aj{l{Dp3kybUJ+Gk|0X|$} z^$qN?`$BfWxa|Ch*o?b8U1Mc=nTAv5sCnsj?5}FhUOAveh(-ViSfyI zyMZ>O#BS$bX0|jLw|<67ro@=PvXOvPr!$>D8y3}^yJJ-c?R-r|bUblTJnTSZuN|?O zz1tQgi1PRgyfvx8(%~XC@EKVza<7se+;YmQeV0X!)LNifoMAl|f5n+$rntNIeW?vy zyF35`^BNkoq5>F3$Jf~vnSu;<5Xw~{wEEvG-I=h={vbZ@Q`$bcj9lTawB4X=SV4Hw z8{VB++=GCX0Z1uPe``IL${zqv3h9xN?bfuEZB`!@xND+U-0W3i;3d)YxDKOQB3q)U zT(fIst+)9^bk7($;JWX|x54o0f4eSVB7C*wysvpYw{{!Sc5^P@r{|@+a0TbB=9Op zTD9k(4eQ3H?e%P=yyl#rUdp3AT|HNVuP}?sRM(B2v;9$>ZQbM%8Nw4m#rz$DE_6@& zA)WkV@KMAyi{$|-2SgY{gMG_sf^r zPE|1M_wo5-tFt<4_v3Em8k|d7K+tDM`0Y~5hwTjPi%+|?VqkW2j!{uI8vQf025m3f z;J+ZSw^ZAR<>$Sfr;|)4jk%rCa+c&u*2gu4p|ezquzl?T&i6&?o-5gHUxlUz5O{W{ zmY{p%Ph=H@X_lH2KKvHy(OM33`E5n)MdcEUrL7PVq(xQIn~#=^MmKYie^_|E z1^s!Qk)coIRCwgjL@54Yhw z`PTy#u>M8N{U*R^Ys6LZm|O8fam2L?>S#UGNJM0?G$K~+=4#vo4qKuo;4*S@T@i^T zKD5#;Iq_iN+j_SI$+)wVX!atM`$Y}2P;X{fEt%gZ+C*nvGm)~{A+c~;{$Lf z`EHG~?a8vTd-h^@pl(DFbw_1lisj2L0nFiHhM@llpM&d!wS-7oq)=px2_!>5$jMioy`{yZJ3m zxHx6?R#1b+B(9&M8J;c@#=^?Y7YfLrGB{xI%9mql;h-@W<8XlO>Z)x-i@PP0wkn3^ z^n_8liw%M80E)cr_n=A18E$L{;!+T8Gc@TyMpYwJKg0VFwJoUP%jV>di16Mp~5+3apjqO(zE_aW0Oa@Le7b?l4wQy+>jwYe5uP$n^Cw&X0*!GjL zGQWZcu6FecRYL&HzJoVI`}Zjl4lZDn>$g(a7BiVh3@f^hRJ+P(N_D5>2puRvdZbDy zFdv3{*M<&Z59}?~=zF%a{t~Cm5*!wWe~;&=(nfO4fXz3>+gxWbliPx@6>~zhL09o= zX?(|q`z>pu_?5nE!SOhA6;r!3a!UvT%KZ1?G=o%6Aps06J=E^?PQV2lE1_XG zxFGJ?Ri2mq)wc#K??#}0fHBLay%R~@?x7ShsdkaSBx|3jzn0(H4-&ITuO-<}5J8Ed zlsZt4b`dK;K7by}C_>u_qW|qq2TU3hR?WDNI8=S1oCvUXDz`w~zCTN4=9{n;Y0>;#|?`WLqcZiI{th(6iB z>rqTrdt#gqe~K!~?6%?zqFoW0FCk#=FscEa#l3eu1n#*?0Hrd&Ev6UpUJKp5DVxCw zA{fBa?v_T>3icrH;faR=KKgHb_yUXs1Oe;GR4}qwd~346swn_P^zvz2Pr%b5c&23A zxO+jS`V|n>D`932FGfvP)idLI6GXBTT*2I&@XI(<-ejG>h%9#0g^On9|CUktuBQ@A zm&-*00mvFaQE-|gs1tX+iFTM>eYpnZUnUMJ=G;1WeV1!8^a+||1G zk*9MPRy661XO2sImrJ+G$bV^m@tHHRYjAYjs_VQlk{D=xi zd~`-S3p5Afgk?TjNOplM=hIrtVQE325IJ7eBq?Wa2wykxUk{z=#bpi{_bY5n>s5H^ zn|iMTs~Ij@FP{)SQ>4)ukP%YEaPmfu}V zsB(B#f2DB={RLm06P-k0@wt$zU-KY{Ww8xL<|PzaXrjtSe%l|P(B=-PH*xF+LthIH zDBs9!l%pOD>@Akjix}Fo@2_2qJHUPnOWb86@P14Kb5?&NGi~=(M!tr9d4lo??&nSt zr{qct=(|AbSI5YV*~?05P=O;eS5#-^ujM9VCuWGvYcKznWLj&nog698`H_KBQKG`C z<0yq1v|@%ZPU%id$UWX%YFb~8JA^Gw#-Ty<6XocM&R{2d>EMcgk>sxKO+K|I^QQ4| zggrRZ+n6x>j;d1YLLaM!;qm&=>qs@dHh4DazDeJhtlXJ*3^8ty_RE2o^1 z_YcOmB~ETtJi~RV#f{QfTS#&Bp{2R+?&0W8E0bihWPIwUDar(Z7ujwH0$0GGEsiQ?NGwCK34j7}<1g_pJS+s$xpjK2i)P<`==Io;MDfda=sRg^}K zaL)8#jz3loIYWgj`PSX^#r~aIxYaacyj)Xs%_o z1AaTUZthBSHZSlWNrJ_x%0tAzBw(qApx3OUGV>1m-L{x=s8`UIOC@PhE^j<7a}Q+YOeS!sKCkVXr2 zIP7tDZp9Qi(g+`(qbeQ2Z)?pk;*FV(~~6nsMJlghnI?qmb~@M@O$1E)8;v(0Bd z5Zz;A;S$rBGgIm<4u-0?K^VX(){#QIlj78c&8nxI3b~vt0}U?2 zl;r=Iu2H{b665yM?(TLQo}Co;w>8^+V^XtC(_-5mo1i-+@3}hK0rx5cac)>9*(o~| zhSzY*1OU;DY}_~6r(p9Jar}@6VIgJ{7JjuW7mlEzTmoktFGg6k`EeW+mI&bc{@t5dNFoM+CSEh=CV2R5x3QAse1l~Qq`%W4@H5RD`n0aY^F z7@}cb;68aN+_!E zrd@K7msGs~NWCIPRNhacPEH${rf?Rn-mvpuD0dQ}`~Yt)w_aN@Qbyy*Atnkx!56(c zUv-9u04C~N5h__at-|o<`Zk;z`Sa+3mf1D?g?MwKm?qgST?1CTDX+&o_;NG{w0Jj^ z0d44f$yC*1cX=UBwV+r8IgU1lSzW7={5vYKsx!!b9g}lnrt#W18_$&kCamtb5WmO` z%~76ZDyI4^f$KtbKFY2f#fGWetL<5hAv2z-5l|2l>u@R{uOd80YPD+>9^`JMoG5Wu z7s%KICvyuxbR>((QDQoz=2buVVJr7YRuUsE9@m*!7(0GCSk_UJWf+q&MyQ!ap?pw> zC|KoUkWreRV+w0rCF3skzyg|cYK$|S45V%%QTO&${+mFm)g}q>S*kprm9)ereJEs@ zd7X#b1LhyTxTu0Jw*#$6qOIlg$DWnlhLP=hc5{>fk+(7Q^SW><0r2 zPfVMyE9!l_g^`FLIMAdn*a?K}u6N;31>+X$Wp1V0Dn?Upt)174mafPSGC>fk!WVL7 zn8P^dTIKdA1vEVob+bYkef1H*unWB;J zyzvw$?|SQxH#3P^FD{lmXC6m$BKg?x=&{6cwHh=_u<56^~hb z?{D0207z)7%b=BkWOJk4U6L26N5#Df?Zwm3b?~fxCRwMIZ?Kw-u8t!E+k)iUJNKwI z&!+B^aD?*$8~W*RUxhR3g#;pSn#S-d8xJo;jqnWx0lVCLa1=|9@flmvxIij$NMLB85uTKGeh`pv3v@H+g1s(Y2kE)3Yts@*1Xf ztlQ|0m6>#Ap$i|Qjg_wlIT-<1)CIC-mZiOr#dlkT`xWC~rA9HvL>n}s6Z2ij!bG&F zda$U}=(oEx&N1m^afyTL^}tw%{F7GW3vLuUWu+`gRvrXIv}hi2PSuGc$Dvy{=>-sRsz250xr9W~27dy#;mpz~I@{B#S2O>l zwbTI=4;{f~Z;#ekJ{S+Gp6}11mIf1`nCzoQPl(zxayY@?fy`z-=0B< z*r$lQPCD$Ki$Xb7tmm3Wu?D79If{7Uv*=1*8pu&`+fC?`vfc+J%}q_MbN|EfK)X8f zSUlFZt1-lqO&MpRCSyZFrhmPJA0m9FnlHVTJ9no(c&0w@oi-sBwK=S6ax3wO`emVb zv?CCNynvP01NvRzC~{Wnn0-681V*xd!&u8}%s`Tencp(Y?C`(1MNf-viYa6_kv1_=PcVIgvuDNiJ-I|QZCme^y2agB zM>A`5HT@p(-KlQkgivRg*9dL=FpK#@HkiAvGq5(tY@|sF|E2{ka#sf9sx5$O5U2eN z^X2R;yhBMhu(Zs}?AuMFw8J%L%V3dp6zsY5Ge+eMUNZ+Wg3h6965dG>*>6ua^om4b z|7;-p>}-c9C4h7v(CtIvSOlk&`kKt7hCdhfpY1}*BUgv`UV!?~Gt6;NFvb(v8A5ze z5?(s zK|_p6ZR#X@Te2(4CJCUM%`e<$?vWCdvx|ZFH*qVHUtfURALNIA`Y305(|Qd-$`iI% zi&+4UmKIcuitB+bb4rJFV~w00*TTqZ_92_23{b!O@ybOfx{b*h120vzF?q?o9?9Jm zd-CgrgV&yW-|eHEE=znhFGt)?w<7AD&EO-PA=ziQb zLlL(U?rp3!k`y<}(J83uuKdDTusXdH31#^k0a75( zM1y)usz`T?Df@6rldGwny6Fm(NR()z36QhIQjMvjL;dfS(1>AZ7)`~8tp7y%R{Cy} zDOgT&nb~n`!HbjQW(@Wk6w5ttKV=fxB3(N6KAN=QI$JDhP>H9MsoRxJ7ltMJiW&dG z<@gSp+y%Nl1DO&80u*`zUo3ZI<(4n<>vxiZvUTs87LSy~aG^^ZYl%JMjg>Y#_D+%m zSrch-1xtD*Ke$3*5z$#Eo6A%SP1AMC5I)p`yL3E&)3VsCx$b7wS9mZ;mvgGi`oyGxwO^S zZXg=>{^qZ0Lvn|3l-6S>>{_TQXbq{D%h{G^l`#;+tb6dEbbpJ6sU$QgM_FcmgfBlV~FArsYn%BgwsopjA`i4|c=EUyABY%QH;|zdCmgsL>$Bv6D*4 zXm*edbZ{40w|&(UH*B|HkoK#(s?mh8hFE))d%Ty62E?l5ewP32B|V+)j5~uA&K-dq zfU-ht-b7P!XUH^x6)tiAkv9F=kv#wtsg`(@6b={8G;pR~8a>hsO$9b>|D&ezHKaRs zqyChL?7d+dL_VGC^!jAS)UeMLukN5iC>7hz{LaizP7>BS`cZ|3h$vtA!QQzpd%y*? zlshVK6<`NcdvVfdk)v4jH$+e|OM~?ekPM1bnbf7JP%Jrw+Jt%}4c*lf?B!ycGvWaoRy>r118+t`e)HPdNUt8H4R)Uqw!s3jLL~iwUKRnp0~zPt^x8W?Brc&CJU=G&_uv?WRCJGDdWho@rv#0 zbd#zSy`pf_kD~r@D zM4a(V{RaOjrfZLdD{zp8q(s!NJzRSmdVq0=a|ckta{YDFpSo4N{LMm(rAEqUJTZ0O zcY?rpx;?-9fR`i=ak{)Y9^#C;;~YMsq$Y$xSTl{0>Y!K(CzY*r!=VuSw-3L`{Hfd} zd)@nEQ4!l{9Tinex!gt@3O3W|;G_F16ih8HsV9`zlo{}<4_+(jJd(FL?s{kxJE;C1 zoXicKMhr??hankc!*$^TuZ}CU>Y%fq2vO+k6?ub7NB3$2wkB+zq+2R`ed(R$WKYw! z^iUO&b;-|l$_t%pTzP^?Ng`DElx#?eo_2MgIE2|Px*QIl@uH!_nSGuZ9DBqH2SHi% zOMu@tk_=i?*myjUC&3er-U_`2*X+4^bc?K>~fqOVr)Dw z_yk2H+Vi`vn+htX!l4stCT}EJdRjeP!*Ca$L+L2Eva;xL;Y3?vIYoph#P*?653ypq zMbYwf!>ZuP>d6mOP;{z_IR`SzNf4RFwv%&c!`ZS?QyFpW>yP=Ao94`l8;wf+RUT_y zkSZL#2E@;J-3zq@n446ThZy<6^z-4VcWj+eEm5FoJ!R{aydO@B5+ay%h`o^-8}k-hP}f%!8NdmL}mVEQ3&`qH?)S6 zMo)>%vE3ing%hj&4&5PN;kq?7{=C~e(O+|4ozv-jJ`=MJc|+d6K|!Mn8{jnpP!hBb zyuUSlsq++YI2szj-a{~mpk^m2^%ZGX{QoVpnGgz% zecyIKm#s~{HS3LcUJgP$K6WHGi}ZDc3}rzek}l)WZPV?t)8JT`ftl7!1L z13S{){n2If&;B9G{out+u!4He5o@Lhfz?T=n2rA_HvqGM6DJML*!uUiL@lv1eVn6b zm97zRv%2IRY%tuc%^U~p4A^fSu(8!TSZu?tc3OFY=j|a!FXsQ>ED7$|yOz@}+6{n%P~!$7xlL@h)NBM+P21HoU1@G&Bc}VeuSE9uQWNiEg1nXhF<&*3J5G|_`O6@R>w<; zGMZxQraF7ICzXXkqg!}LKwGh~vN64Ycn4iJ)MEjRw8bc76rYj+955?-1k{^|=M0W* zI8eCj?8DOR8d|s-PxC_MaHIZAi5Z)!K3zzb=-Wi`fq~lNUs$0r@qT-zb|Z8b3(g%r zapERwZ)F7-Ic~di{eM2);N*3={1}!1>y90eA(}7NyZi-jTH=1pb3!67_yBeRS4v|R zbAbaP@z~+v05CHg5xQy?u*9cr5AVV~cD+mKaXV+Op(dD}B&46ySnj7^1m5*=V)#Vs zb-7*sdyi&qE6wJh0-Yd(0dG@KUG&Vs?0sE`QDrZPSze#poTnc&+qt27Mi(e^f>dPD zQ*aTEFR!PHS%{vRvqxn$_|{oni>3aA;gVZjq90;e0-{}qe~RS2ByFeh#_#TdHn`a- zf+Ky@FBYjjDdwk1UA=L72yTDn>A8r=V_ zd^tPU!e_dKA5W9Pmnh-_$a`caaIs?o_8U!}5bwh+uS6cDJJzkPJ4qe0io;uu(0>5L zB7eU_49(CKncTx#wMp9}AwF|2Ck{5qM-ExAe?VFD_&siK`fC)lbdRsh^qp3RYuy$H zNcjvo0+$>E19G>uHdVNTyw1cu68D81o`PAy1Lv1z2bwPB0Xch|PsZT}ODIDH|;;c*Bb=N7qJPSYat7ovlwXY(C# zS&H<2cDLp+^lXLQ)G$Xn(_-N+t)En>NQt5sZ#JXEk6h)P#mo9bqu^>ImzR|=&ijJ4 zaeWU+s*xKPu6Na@bp&Npa3fWbf2^&b!F9|LZ@~j;%5iWij+Mt)(KhVA%d2D0)#qbKd>iDcS}>$0Eo^1)>|k9Byh^JeCjrAgx&P;I85`+y5u!n_5B zLGpBkn`JDdPdR(IJ-IkF4Y!RDR+V4kh_DZ5rJN}cuyXfcu>N(B3oiU>tlM|HROo8V zqFtMeKFBJ)z0kzI1jK?NVSd!oie#Jlkr{-&)v91~>e#$O43%wPyP$FWad~}I=56e9 z%FkhrPKoyOPB*L?UM+ww?_Hv2`f2zvhsck}A*nGqs$K7LIQpAGoZ&V=8>OfJ%H;E= ziEx|MZ``$cU)nRXK4v!vS*p^b7udC*?I!Imr&q)HV^_+$44QiWnV{B{=fVqZU2y zG{t%7_5RM~VIY3qGfXK_sX1A(e0U%y|7=#kek34K=W?L;ZKysXC0dugRWc9AQfgsS z%VMa>qd`{qyNiW41VQ|iLdY55WwTL<=mPmCMxOPg((8ZRI`eT#Pz z;D($6+0JH)5v;#}R`&0SURr8)z~_j$`%Rzwf#6k5U%IW)&x@Qm;+6=Qxtb_rLzSnl z8u!&J7EY1zPYayAI(v;l!~jyY+exR!A>-++o_xTv0~GC_kbZH&L;Wt!r!&>YWBkg^ zX&o+rG3P2d)gQzcVHJ-21Om?N7YiO3R6r}ORM#ccEjtCD&RXchBLO_b#MmzK36%MV zUIqLbK&l!|Rcg%CoCkfrNe1)IJXH$GZquMjV00eT^d@$dq_x=cKQFv)sgC2#s{RgP zC({<|h73oZLh6#2L(CO+;&hdi)T_SH0gjSsDMWpPpro#_%Mg&*LKwlvBKry9XLo1x z#`?w@eBJyY!w|?8+&R=7lG=pfPeqP1rED{!RW)o|L4Epk_5G>wY1*!CyoXCMsP#Np z_To$u!!>qB^RY&9HzP~GKCndX1y+w(f}U=imo)@dZ6`Rngl-B&2t~^Y_j+dkszDFG zi!FLz?Lt#i10AVpa4}ufl(zcZe4fSJdgj5>k$22N?&v2>4Ptw`2mE&v2*g6*(U=d) zy88%gFICK2cHiJOs7)emH=|5Kmg@+x3>;io7Pwhoc!FeBhs)ZG6b&|(9NC(?ldGBf zBw_DldNcupySA=XMstFcUKPwnML_lOfM`*`Izo4%Hz5nt%tWOAGzGx-t$KU+v^jBmk=P%;ohYNDrz*iSF0Q zt5}KE=cH%{Q;a!l#?Hf|JqltFu6lgdfFR?JD}LI%JG}e;YQrAY+ncO_3=y^uDNtg& zeuJ&!6IpB@E`sFW8yyt~L5F_ienG$WZJ0qo;dYYN7Yh5N2;8+B9CX?s`x_jr_6~q_ zt&#USArhKf1B^Rt6SroPEg2Lcfet!`{uut6pkBBnN!Zs&M7NkUJzB^w_K-d-)VJ}r zo8$f`(HOHQIA6A77ZE~RQ%iwXx{xh1bpzmQ2K{wIyH=(t*? zwh(UfSv-a$|FC>iAL&Pm{Dc0zZWUo48C6O;^l{i_BC_1U&OLwLn_AON!`;RHt0Na3 zJj^8uc4=Jp?S5eYYvxskS;>MuM+U!iOe|@&3(Mf6I`oW);{B8)ePnM$hHnS=XC|#F z`9mv(vhg98%Hi}YC1&2SM>|S#k@TKjeE-6&g86m=R1^*fp~;kD;Ku+5x`!Z+Iv`_VKC`MT(Mgj{j1ABL3do9>#Gy+?x%ctJ#epT(BXS0L%d(TD_-I*kFr zOPP?}zwP_cqK37%{WvS59$FKvdV}>=fwfW3f^m}g^f+|hQ-ub|6bZN?<5^{)R?1r% zaoXgd;ajp`tH0eLg?;bMn;Owz;5D?KQ>Sm>{jBG}T$ z61F<7qI+HC&4u;_^nP6Rj*>o9FMu}X3$scgK(P)f?hlRe4V}mhulyY?Gx)F|Q(r2% z>0=<{bjNv00E4E0hG-H96vg~ PvBYQl0ssI200dcD);I*6 diff --git a/kernel/kernel/files/patches/linux/patch-5.10.5.xz b/kernel/kernel/files/patches/linux/patch-5.10.5.xz deleted file mode 100644 index 2c6d95f6ec639b88f8b6bf4c604b0264a3eaa19c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 223376 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�^{l}VIJS3Fd&`%H$`4RyQaHbRSyiAd|MON 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

  • @eDl(Y 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

    %F8#%05$4MKU7xOfR;oFW?N?}&Fo_EASZ#{b! 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 diff --git a/kernel/kernel/files/patches/mageia/aufs5.patch b/kernel/kernel/files/patches/mageia/aufs5.patch deleted file mode 100644 index 9f4dcd01..00000000 --- a/kernel/kernel/files/patches/mageia/aufs5.patch +++ /dev/null @@ -1,38152 +0,0 @@ -diff --git a/Documentation/ABI/testing/debugfs-aufs b/Documentation/ABI/testing/debugfs-aufs -new file mode 100644 -index 000000000000..4a6694194ba6 ---- /dev/null -+++ b/Documentation/ABI/testing/debugfs-aufs -@@ -0,0 +1,55 @@ -+What: /debug/aufs/si_/ -+Date: March 2009 -+Contact: J. R. Okajima -+Description: -+ Under /debug/aufs, a directory named si_ is created -+ per aufs mount, where is a unique id generated -+ internally. -+ -+What: /debug/aufs/si_/plink -+Date: Apr 2013 -+Contact: J. R. Okajima -+Description: -+ It has three lines and shows the information about the -+ pseudo-link. The first line is a single number -+ representing a number of buckets. The second line is a -+ number of pseudo-links per buckets (separated by a -+ blank). The last line is a single number representing a -+ total number of psedo-links. -+ When the aufs mount option 'noplink' is specified, it -+ will show "1\n0\n0\n". -+ -+What: /debug/aufs/si_/xib -+Date: March 2009 -+Contact: J. R. Okajima -+Description: -+ It shows the consumed blocks by xib (External Inode Number -+ Bitmap), its block size and file size. -+ When the aufs mount option 'noxino' is specified, it -+ will be empty. About XINO files, see the aufs manual. -+ -+What: /debug/aufs/si_/xi0, xi1 ... xiN and xiN-N -+Date: March 2009 -+Contact: J. R. Okajima -+Description: -+ It shows the consumed blocks by xino (External Inode Number -+ Translation Table), its link count, block size and file -+ size. -+ Due to the file size limit, there may exist multiple -+ xino files per branch. In this case, "-N" is added to -+ the filename and it corresponds to the index of the -+ internal xino array. "-0" is omitted. -+ When the aufs mount option 'noxino' is specified, Those -+ entries won't exist. About XINO files, see the aufs -+ manual. -+ -+What: /debug/aufs/si_/xigen -+Date: March 2009 -+Contact: J. R. Okajima -+Description: -+ It shows the consumed blocks by xigen (External Inode -+ Generation Table), its block size and file size. -+ If CONFIG_AUFS_EXPORT is disabled, this entry will not -+ be created. -+ When the aufs mount option 'noxino' is specified, it -+ will be empty. About XINO files, see the aufs manual. -diff --git a/Documentation/ABI/testing/sysfs-aufs b/Documentation/ABI/testing/sysfs-aufs -new file mode 100644 -index 000000000000..82f9518495ea ---- /dev/null -+++ b/Documentation/ABI/testing/sysfs-aufs -@@ -0,0 +1,31 @@ -+What: /sys/fs/aufs/si_/ -+Date: March 2009 -+Contact: J. R. Okajima -+Description: -+ Under /sys/fs/aufs, a directory named si_ is created -+ per aufs mount, where is a unique id generated -+ internally. -+ -+What: /sys/fs/aufs/si_/br0, br1 ... brN -+Date: March 2009 -+Contact: J. R. Okajima -+Description: -+ It shows the abolute path of a member directory (which -+ is called branch) in aufs, and its permission. -+ -+What: /sys/fs/aufs/si_/brid0, brid1 ... bridN -+Date: July 2013 -+Contact: J. R. Okajima -+Description: -+ It shows the id of a member directory (which is called -+ branch) in aufs. -+ -+What: /sys/fs/aufs/si_/xi_path -+Date: March 2009 -+Contact: J. R. Okajima -+Description: -+ It shows the abolute path of XINO (External Inode Number -+ Bitmap, Translation Table and Generation Table) file -+ even if it is the default path. -+ When the aufs mount option 'noxino' is specified, it -+ will be empty. About XINO files, see the aufs manual. -diff --git a/Documentation/filesystems/aufs/README b/Documentation/filesystems/aufs/README -new file mode 100644 -index 000000000000..3e655d357134 ---- /dev/null -+++ b/Documentation/filesystems/aufs/README -@@ -0,0 +1,401 @@ -+ -+Aufs5 -- advanced multi layered unification filesystem version 5.x -+http://aufs.sf.net -+Junjiro R. Okajima -+ -+ -+0. Introduction -+---------------------------------------- -+In the early days, aufs was entirely re-designed and re-implemented -+Unionfs Version 1.x series. Adding many original ideas, approaches, -+improvements and implementations, it became totally different from -+Unionfs while keeping the basic features. -+Later, Unionfs Version 2.x series began taking some of the same -+approaches to aufs1's. -+Unionfs was being developed by Professor Erez Zadok at Stony Brook -+University and his team. -+ -+Aufs5 supports linux-v5.0 and later, If you want older kernel version -+support, -+- for linux-v4.x series, try aufs4-linux.git or aufs4-standalone.git -+- for linux-v3.x series, try aufs3-linux.git or aufs3-standalone.git -+- for linux-v2.6.16 and later, try aufs2-2.6.git, aufs2-standalone.git -+ or aufs1 from CVS on SourceForge. -+ -+Note: it becomes clear that "Aufs was rejected. Let's give it up." -+ According to Christoph Hellwig, linux rejects all union-type -+ filesystems but UnionMount. -+ -+ -+PS. Al Viro seems have a plan to merge aufs as well as overlayfs and -+ UnionMount, and he pointed out an issue around a directory mutex -+ lock and aufs addressed it. But it is still unsure whether aufs will -+ be merged (or any other union solution). -+ -+ -+ -+1. Features -+---------------------------------------- -+- unite several directories into a single virtual filesystem. The member -+ directory is called as a branch. -+- you can specify the permission flags to the branch, which are 'readonly', -+ 'readwrite' and 'whiteout-able.' -+- by upper writable branch, internal copyup and whiteout, files/dirs on -+ readonly branch are modifiable logically. -+- dynamic branch manipulation, add, del. -+- etc... -+ -+Also there are many enhancements in aufs, such as: -+- test only the highest one for the directory permission (dirperm1) -+- copyup on open (coo=) -+- 'move' policy for copy-up between two writable branches, after -+ checking free space. -+- xattr, acl -+- readdir(3) in userspace. -+- keep inode number by external inode number table -+- keep the timestamps of file/dir in internal copyup operation -+- seekable directory, supporting NFS readdir. -+- whiteout is hardlinked in order to reduce the consumption of inodes -+ on branch -+- do not copyup, nor create a whiteout when it is unnecessary -+- revert a single systemcall when an error occurs in aufs -+- remount interface instead of ioctl -+- maintain /etc/mtab by an external command, /sbin/mount.aufs. -+- loopback mounted filesystem as a branch -+- kernel thread for removing the dir who has a plenty of whiteouts -+- support copyup sparse file (a file which has a 'hole' in it) -+- default permission flags for branches -+- selectable permission flags for ro branch, whether whiteout can -+ exist or not -+- export via NFS. -+- support /fs/aufs and /aufs. -+- support multiple writable branches, some policies to select one -+ among multiple writable branches. -+- a new semantics for link(2) and rename(2) to support multiple -+ writable branches. -+- no glibc changes are required. -+- pseudo hardlink (hardlink over branches) -+- allow a direct access manually to a file on branch, e.g. bypassing aufs. -+ including NFS or remote filesystem branch. -+- userspace wrapper for pathconf(3)/fpathconf(3) with _PC_LINK_MAX. -+- and more... -+ -+Currently these features are dropped temporary from aufs5. -+See design/08plan.txt in detail. -+- nested mount, i.e. aufs as readonly no-whiteout branch of another aufs -+ (robr) -+- statistics of aufs thread (/sys/fs/aufs/stat) -+ -+Features or just an idea in the future (see also design/*.txt), -+- reorder the branch index without del/re-add. -+- permanent xino files for NFSD -+- an option for refreshing the opened files after add/del branches -+- light version, without branch manipulation. (unnecessary?) -+- copyup in userspace -+- inotify in userspace -+- readv/writev -+ -+ -+2. Download -+---------------------------------------- -+There are three GIT trees for aufs5, aufs5-linux.git, -+aufs5-standalone.git, and aufs-util.git. Note that there is no "5" in -+"aufs-util.git." -+While the aufs-util is always necessary, you need either of aufs5-linux -+or aufs5-standalone. -+ -+The aufs5-linux tree includes the whole linux mainline GIT tree, -+git://git.kernel.org/.../torvalds/linux.git. -+And you cannot select CONFIG_AUFS_FS=m for this version, eg. you cannot -+build aufs5 as an external kernel module. -+Several extra patches are not included in this tree. Only -+aufs5-standalone tree contains them. They are described in the later -+section "Configuration and Compilation." -+ -+On the other hand, the aufs5-standalone tree has only aufs source files -+and necessary patches, and you can select CONFIG_AUFS_FS=m. -+But you need to apply all aufs patches manually. -+ -+You will find GIT branches whose name is in form of "aufs5.x" where "x" -+represents the linux kernel version, "linux-5.x". For instance, -+"aufs5.0" is for linux-5.0. For latest "linux-5.x-rcN", use -+"aufs5.x-rcN" branch. -+ -+o aufs5-linux tree -+$ git clone --reference /your/linux/git/tree \ -+ git://github.com/sfjro/aufs5-linux.git aufs5-linux.git -+- if you don't have linux GIT tree, then remove "--reference ..." -+$ cd aufs5-linux.git -+$ git checkout origin/aufs5.0 -+ -+Or You may want to directly git-pull aufs into your linux GIT tree, and -+leave the patch-work to GIT. -+$ cd /your/linux/git/tree -+$ git remote add aufs5 git://github.com/sfjro/aufs5-linux.git -+$ git fetch aufs5 -+$ git checkout -b my5.0 v5.0 -+$ (add your local change...) -+$ git pull aufs5 aufs5.0 -+- now you have v5.0 + your_changes + aufs5.0 in you my5.0 branch. -+- you may need to solve some conflicts between your_changes and -+ aufs5.0. in this case, git-rerere is recommended so that you can -+ solve the similar conflicts automatically when you upgrade to 5.1 or -+ later in the future. -+ -+o aufs5-standalone tree -+$ git clone git://github.com/sfjro/aufs5-standalone.git aufs5-standalone.git -+$ cd aufs5-standalone.git -+$ git checkout origin/aufs5.0 -+ -+o aufs-util tree -+$ git clone git://git.code.sf.net/p/aufs/aufs-util aufs-util.git -+- note that the public aufs-util.git is on SourceForge instead of -+ GitHUB. -+$ cd aufs-util.git -+$ git checkout origin/aufs5.0 -+ -+Note: The 5.x-rcN branch is to be used with `rc' kernel versions ONLY. -+The minor version number, 'x' in '5.x', of aufs may not always -+follow the minor version number of the kernel. -+Because changes in the kernel that cause the use of a new -+minor version number do not always require changes to aufs-util. -+ -+Since aufs-util has its own minor version number, you may not be -+able to find a GIT branch in aufs-util for your kernel's -+exact minor version number. -+In this case, you should git-checkout the branch for the -+nearest lower number. -+ -+For (an unreleased) example: -+If you are using "linux-5.10" and the "aufs5.10" branch -+does not exist in aufs-util repository, then "aufs5.9", "aufs5.8" -+or something numerically smaller is the branch for your kernel. -+ -+Also you can view all branches by -+ $ git branch -a -+ -+ -+3. Configuration and Compilation -+---------------------------------------- -+Make sure you have git-checkout'ed the correct branch. -+ -+For aufs5-linux tree, -+- enable CONFIG_AUFS_FS. -+- set other aufs configurations if necessary. -+ -+For aufs5-standalone tree, -+There are several ways to build. -+ -+1. -+- apply ./aufs5-kbuild.patch to your kernel source files. -+- apply ./aufs5-base.patch too. -+- apply ./aufs5-mmap.patch too. -+- apply ./aufs5-standalone.patch too, if you have a plan to set -+ CONFIG_AUFS_FS=m. otherwise you don't need ./aufs5-standalone.patch. -+- copy ./{Documentation,fs,include/uapi/linux/aufs_type.h} files to your -+ kernel source tree. Never copy $PWD/include/uapi/linux/Kbuild. -+- enable CONFIG_AUFS_FS, you can select either -+ =m or =y. -+- and build your kernel as usual. -+- install the built kernel. -+- install the header files too by "make headers_install" to the -+ directory where you specify. By default, it is $PWD/usr. -+ "make help" shows a brief note for headers_install. -+- and reboot your system. -+ -+2. -+- module only (CONFIG_AUFS_FS=m). -+- apply ./aufs5-base.patch to your kernel source files. -+- apply ./aufs5-mmap.patch too. -+- apply ./aufs5-standalone.patch too. -+- build your kernel, don't forget "make headers_install", and reboot. -+- edit ./config.mk and set other aufs configurations if necessary. -+ Note: You should read $PWD/fs/aufs/Kconfig carefully which describes -+ every aufs configurations. -+- build the module by simple "make". -+- you can specify ${KDIR} make variable which points to your kernel -+ source tree. -+- install the files -+ + run "make install" to install the aufs module, or copy the built -+ $PWD/aufs.ko to /lib/modules/... and run depmod -a (or reboot simply). -+ + run "make install_headers" (instead of headers_install) to install -+ the modified aufs header file (you can specify DESTDIR which is -+ available in aufs standalone version's Makefile only), or copy -+ $PWD/usr/include/linux/aufs_type.h to /usr/include/linux or wherever -+ you like manually. By default, the target directory is $PWD/usr. -+- no need to apply aufs5-kbuild.patch, nor copying source files to your -+ kernel source tree. -+ -+Note: The header file aufs_type.h is necessary to build aufs-util -+ as well as "make headers_install" in the kernel source tree. -+ headers_install is subject to be forgotten, but it is essentially -+ necessary, not only for building aufs-util. -+ You may not meet problems without headers_install in some older -+ version though. -+ -+And then, -+- read README in aufs-util, build and install it -+- note that your distribution may contain an obsoleted version of -+ aufs_type.h in /usr/include/linux or something. When you build aufs -+ utilities, make sure that your compiler refers the correct aufs header -+ file which is built by "make headers_install." -+- if you want to use readdir(3) in userspace or pathconf(3) wrapper, -+ then run "make install_ulib" too. And refer to the aufs manual in -+ detail. -+ -+There several other patches in aufs5-standalone.git. They are all -+optional. When you meet some problems, they will help you. -+- aufs5-loopback.patch -+ Supports a nested loopback mount in a branch-fs. This patch is -+ unnecessary until aufs produces a message like "you may want to try -+ another patch for loopback file". -+- proc_mounts.patch -+ When there are many mountpoints and many mount(2)/umount(2) are -+ running, then /proc/mounts may not show the all mountpoints. This -+ patch makes /proc/mounts always show the full mountpoints list. -+ If you don't want to apply this patch and meet such problem, then you -+ need to increase the value of 'ProcMounts_Times' make-variable in -+ aufs-util.git as a second best solution. -+- vfs-ino.patch -+ Modifies a system global kernel internal function get_next_ino() in -+ order to stop assigning 0 for an inode-number. Not directly related to -+ aufs, but recommended generally. -+- tmpfs-idr.patch -+ Keeps the tmpfs inode number as the lowest value. Effective to reduce -+ the size of aufs XINO files for tmpfs branch. Also it prevents the -+ duplication of inode number, which is important for backup tools and -+ other utilities. When you find aufs XINO files for tmpfs branch -+ growing too much, try this patch. -+- lockdep-debug.patch -+ Because aufs is not only an ordinary filesystem (callee of VFS), but -+ also a caller of VFS functions for branch filesystems, subclassing of -+ the internal locks for LOCKDEP is necessary. LOCKDEP is a debugging -+ feature of linux kernel. If you enable CONFIG_LOCKDEP, then you will -+ need to apply this debug patch to expand several constant values. -+ If you don't know what LOCKDEP is, then you don't have apply this -+ patch. -+ -+ -+4. Usage -+---------------------------------------- -+At first, make sure aufs-util are installed, and please read the aufs -+manual, aufs.5 in aufs-util.git tree. -+$ man -l aufs.5 -+ -+And then, -+$ mkdir /tmp/rw /tmp/aufs -+# mount -t aufs -o br=/tmp/rw:${HOME} none /tmp/aufs -+ -+Here is another example. The result is equivalent. -+# mount -t aufs -o br=/tmp/rw=rw:${HOME}=ro none /tmp/aufs -+ Or -+# mount -t aufs -o br:/tmp/rw none /tmp/aufs -+# mount -o remount,append:${HOME} /tmp/aufs -+ -+Then, you can see whole tree of your home dir through /tmp/aufs. If -+you modify a file under /tmp/aufs, the one on your home directory is -+not affected, instead the same named file will be newly created under -+/tmp/rw. And all of your modification to a file will be applied to -+the one under /tmp/rw. This is called the file based Copy on Write -+(COW) method. -+Aufs mount options are described in aufs.5. -+If you run chroot or something and make your aufs as a root directory, -+then you need to customize the shutdown script. See the aufs manual in -+detail. -+ -+Additionally, there are some sample usages of aufs which are a -+diskless system with network booting, and LiveCD over NFS. -+See sample dir in CVS tree on SourceForge. -+ -+ -+5. Contact -+---------------------------------------- -+When you have any problems or strange behaviour in aufs, please let me -+know with: -+- /proc/mounts (instead of the output of mount(8)) -+- /sys/module/aufs/* -+- /sys/fs/aufs/* (if you have them) -+- /debug/aufs/* (if you have them) -+- linux kernel version -+ if your kernel is not plain, for example modified by distributor, -+ the url where i can download its source is necessary too. -+- aufs version which was printed at loading the module or booting the -+ system, instead of the date you downloaded. -+- configuration (define/undefine CONFIG_AUFS_xxx) -+- kernel configuration or /proc/config.gz (if you have it) -+- LSM (linux security module, if you are using) -+- behaviour which you think to be incorrect -+- actual operation, reproducible one is better -+- mailto: aufs-users at lists.sourceforge.net -+ -+Usually, I don't watch the Public Areas(Bugs, Support Requests, Patches, -+and Feature Requests) on SourceForge. Please join and write to -+aufs-users ML. -+ -+ -+6. Acknowledgements -+---------------------------------------- -+Thanks to everyone who have tried and are using aufs, whoever -+have reported a bug or any feedback. -+ -+Especially donators: -+Tomas Matejicek(slax.org) made a donation (much more than once). -+ Since Apr 2010, Tomas M (the author of Slax and Linux Live -+ scripts) is making "doubling" donations. -+ Unfortunately I cannot list all of the donators, but I really -+ appreciate. -+ It ends Aug 2010, but the ordinary donation URL is still available. -+ -+Dai Itasaka made a donation (2007/8). -+Chuck Smith made a donation (2008/4, 10 and 12). -+Henk Schoneveld made a donation (2008/9). -+Chih-Wei Huang, ASUS, CTC donated Eee PC 4G (2008/10). -+Francois Dupoux made a donation (2008/11). -+Bruno Cesar Ribas and Luis Carlos Erpen de Bona, C3SL serves public -+ aufs2 GIT tree (2009/2). -+William Grant made a donation (2009/3). -+Patrick Lane made a donation (2009/4). -+The Mail Archive (mail-archive.com) made donations (2009/5). -+Nippy Networks (Ed Wildgoose) made a donation (2009/7). -+New Dream Network, LLC (www.dreamhost.com) made a donation (2009/11). -+Pavel Pronskiy made a donation (2011/2). -+Iridium and Inmarsat satellite phone retailer (www.mailasail.com), Nippy -+ Networks (Ed Wildgoose) made a donation for hardware (2011/3). -+Max Lekomcev (DOM-TV project) made a donation (2011/7, 12, 2012/3, 6 and -+11). -+Sam Liddicott made a donation (2011/9). -+Era Scarecrow made a donation (2013/4). -+Bor Ratajc made a donation (2013/4). -+Alessandro Gorreta made a donation (2013/4). -+POIRETTE Marc made a donation (2013/4). -+Alessandro Gorreta made a donation (2013/4). -+lauri kasvandik made a donation (2013/5). -+"pemasu from Finland" made a donation (2013/7). -+The Parted Magic Project made a donation (2013/9 and 11). -+Pavel Barta made a donation (2013/10). -+Nikolay Pertsev made a donation (2014/5). -+James B made a donation (2014/7 and 2015/7). -+Stefano Di Biase made a donation (2014/8). -+Daniel Epellei made a donation (2015/1). -+OmegaPhil made a donation (2016/1, 2018/4). -+Tomasz Szewczyk made a donation (2016/4). -+James Burry made a donation (2016/12). -+Carsten Rose made a donation (2018/9). -+Porteus Kiosk made a donation (2018/10). -+ -+Thank you very much. -+Donations are always, including future donations, very important and -+helpful for me to keep on developing aufs. -+ -+ -+7. -+---------------------------------------- -+If you are an experienced user, no explanation is needed. Aufs is -+just a linux filesystem. -+ -+ -+Enjoy! -+ -+# Local variables: ; -+# mode: text; -+# End: ; -diff --git a/Documentation/filesystems/aufs/design/01intro.txt b/Documentation/filesystems/aufs/design/01intro.txt -new file mode 100644 -index 000000000000..7f75ee4a784c ---- /dev/null -+++ b/Documentation/filesystems/aufs/design/01intro.txt -@@ -0,0 +1,158 @@ -+ -+# Copyright (C) 2005-2020 Junjiro R. Okajima -+ -+Introduction -+---------------------------------------- -+ -+aufs [ei ju: ef es] | /ey-yoo-ef-es/ | [a u f s] -+1. abbrev. for "advanced multi-layered unification filesystem". -+2. abbrev. for "another unionfs". -+3. abbrev. for "auf das" in German which means "on the" in English. -+ Ex. "Butter aufs Brot"(G) means "butter onto bread"(E). -+ But "Filesystem aufs Filesystem" is hard to understand. -+4. abbrev. for "African Urban Fashion Show". -+ -+AUFS is a filesystem with features: -+- multi layered stackable unification filesystem, the member directory -+ is called as a branch. -+- branch permission and attribute, 'readonly', 'real-readonly', -+ 'readwrite', 'whiteout-able', 'link-able whiteout', etc. and their -+ combination. -+- internal "file copy-on-write". -+- logical deletion, whiteout. -+- dynamic branch manipulation, adding, deleting and changing permission. -+- allow bypassing aufs, user's direct branch access. -+- external inode number translation table and bitmap which maintains the -+ persistent aufs inode number. -+- seekable directory, including NFS readdir. -+- file mapping, mmap and sharing pages. -+- pseudo-link, hardlink over branches. -+- loopback mounted filesystem as a branch. -+- several policies to select one among multiple writable branches. -+- revert a single systemcall when an error occurs in aufs. -+- and more... -+ -+ -+Multi Layered Stackable Unification Filesystem -+---------------------------------------------------------------------- -+Most people already knows what it is. -+It is a filesystem which unifies several directories and provides a -+merged single directory. When users access a file, the access will be -+passed/re-directed/converted (sorry, I am not sure which English word is -+correct) to the real file on the member filesystem. The member -+filesystem is called 'lower filesystem' or 'branch' and has a mode -+'readonly' and 'readwrite.' And the deletion for a file on the lower -+readonly branch is handled by creating 'whiteout' on the upper writable -+branch. -+ -+On LKML, there have been discussions about UnionMount (Jan Blunck, -+Bharata B Rao and Valerie Aurora) and Unionfs (Erez Zadok). They took -+different approaches to implement the merged-view. -+The former tries putting it into VFS, and the latter implements as a -+separate filesystem. -+(If I misunderstand about these implementations, please let me know and -+I shall correct it. Because it is a long time ago when I read their -+source files last time). -+ -+UnionMount's approach will be able to small, but may be hard to share -+branches between several UnionMount since the whiteout in it is -+implemented in the inode on branch filesystem and always -+shared. According to Bharata's post, readdir does not seems to be -+finished yet. -+There are several missing features known in this implementations such as -+- for users, the inode number may change silently. eg. copy-up. -+- link(2) may break by copy-up. -+- read(2) may get an obsoleted filedata (fstat(2) too). -+- fcntl(F_SETLK) may be broken by copy-up. -+- unnecessary copy-up may happen, for example mmap(MAP_PRIVATE) after -+ open(O_RDWR). -+ -+In linux-3.18, "overlay" filesystem (formerly known as "overlayfs") was -+merged into mainline. This is another implementation of UnionMount as a -+separated filesystem. All the limitations and known problems which -+UnionMount are equally inherited to "overlay" filesystem. -+ -+Unionfs has a longer history. When I started implementing a stackable -+filesystem (Aug 2005), it already existed. It has virtual super_block, -+inode, dentry and file objects and they have an array pointing lower -+same kind objects. After contributing many patches for Unionfs, I -+re-started my project AUFS (Jun 2006). -+ -+In AUFS, the structure of filesystem resembles to Unionfs, but I -+implemented my own ideas, approaches and enhancements and it became -+totally different one. -+ -+Comparing DM snapshot and fs based implementation -+- the number of bytes to be copied between devices is much smaller. -+- the type of filesystem must be one and only. -+- the fs must be writable, no readonly fs, even for the lower original -+ device. so the compression fs will not be usable. but if we use -+ loopback mount, we may address this issue. -+ for instance, -+ mount /cdrom/squashfs.img /sq -+ losetup /sq/ext2.img -+ losetup /somewhere/cow -+ dmsetup "snapshot /dev/loop0 /dev/loop1 ..." -+- it will be difficult (or needs more operations) to extract the -+ difference between the original device and COW. -+- DM snapshot-merge may help a lot when users try merging. in the -+ fs-layer union, users will use rsync(1). -+ -+You may want to read my old paper "Filesystems in LiveCD" -+(http://aufs.sourceforge.net/aufs2/report/sq/sq.pdf). -+ -+ -+Several characters/aspects/persona of aufs -+---------------------------------------------------------------------- -+ -+Aufs has several characters, aspects or persona. -+1. a filesystem, callee of VFS helper -+2. sub-VFS, caller of VFS helper for branches -+3. a virtual filesystem which maintains persistent inode number -+4. reader/writer of files on branches such like an application -+ -+1. Callee of VFS Helper -+As an ordinary linux filesystem, aufs is a callee of VFS. For instance, -+unlink(2) from an application reaches sys_unlink() kernel function and -+then vfs_unlink() is called. vfs_unlink() is one of VFS helper and it -+calls filesystem specific unlink operation. Actually aufs implements the -+unlink operation but it behaves like a redirector. -+ -+2. Caller of VFS Helper for Branches -+aufs_unlink() passes the unlink request to the branch filesystem as if -+it were called from VFS. So the called unlink operation of the branch -+filesystem acts as usual. As a caller of VFS helper, aufs should handle -+every necessary pre/post operation for the branch filesystem. -+- acquire the lock for the parent dir on a branch -+- lookup in a branch -+- revalidate dentry on a branch -+- mnt_want_write() for a branch -+- vfs_unlink() for a branch -+- mnt_drop_write() for a branch -+- release the lock on a branch -+ -+3. Persistent Inode Number -+One of the most important issue for a filesystem is to maintain inode -+numbers. This is particularly important to support exporting a -+filesystem via NFS. Aufs is a virtual filesystem which doesn't have a -+backend block device for its own. But some storage is necessary to -+keep and maintain the inode numbers. It may be a large space and may not -+suit to keep in memory. Aufs rents some space from its first writable -+branch filesystem (by default) and creates file(s) on it. These files -+are created by aufs internally and removed soon (currently) keeping -+opened. -+Note: Because these files are removed, they are totally gone after -+ unmounting aufs. It means the inode numbers are not persistent -+ across unmount or reboot. I have a plan to make them really -+ persistent which will be important for aufs on NFS server. -+ -+4. Read/Write Files Internally (copy-on-write) -+Because a branch can be readonly, when you write a file on it, aufs will -+"copy-up" it to the upper writable branch internally. And then write the -+originally requested thing to the file. Generally kernel doesn't -+open/read/write file actively. In aufs, even a single write may cause a -+internal "file copy". This behaviour is very similar to cp(1) command. -+ -+Some people may think it is better to pass such work to user space -+helper, instead of doing in kernel space. Actually I am still thinking -+about it. But currently I have implemented it in kernel space. -diff --git a/Documentation/filesystems/aufs/design/02struct.txt b/Documentation/filesystems/aufs/design/02struct.txt -new file mode 100644 -index 000000000000..0a948e812796 ---- /dev/null -+++ b/Documentation/filesystems/aufs/design/02struct.txt -@@ -0,0 +1,245 @@ -+ -+# Copyright (C) 2005-2020 Junjiro R. Okajima -+ -+Basic Aufs Internal Structure -+ -+Superblock/Inode/Dentry/File Objects -+---------------------------------------------------------------------- -+As like an ordinary filesystem, aufs has its own -+superblock/inode/dentry/file objects. All these objects have a -+dynamically allocated array and store the same kind of pointers to the -+lower filesystem, branch. -+For example, when you build a union with one readwrite branch and one -+readonly, mounted /au, /rw and /ro respectively. -+- /au = /rw + /ro -+- /ro/fileA exists but /rw/fileA -+ -+Aufs lookup operation finds /ro/fileA and gets dentry for that. These -+pointers are stored in a aufs dentry. The array in aufs dentry will be, -+- [0] = NULL (because /rw/fileA doesn't exist) -+- [1] = /ro/fileA -+ -+This style of an array is essentially same to the aufs -+superblock/inode/dentry/file objects. -+ -+Because aufs supports manipulating branches, ie. add/delete/change -+branches dynamically, these objects has its own generation. When -+branches are changed, the generation in aufs superblock is -+incremented. And a generation in other object are compared when it is -+accessed. When a generation in other objects are obsoleted, aufs -+refreshes the internal array. -+ -+ -+Superblock -+---------------------------------------------------------------------- -+Additionally aufs superblock has some data for policies to select one -+among multiple writable branches, XIB files, pseudo-links and kobject. -+See below in detail. -+About the policies which supports copy-down a directory, see -+wbr_policy.txt too. -+ -+ -+Branch and XINO(External Inode Number Translation Table) -+---------------------------------------------------------------------- -+Every branch has its own xino (external inode number translation table) -+file. The xino file is created and unlinked by aufs internally. When two -+members of a union exist on the same filesystem, they share the single -+xino file. -+The struct of a xino file is simple, just a sequence of aufs inode -+numbers which is indexed by the lower inode number. -+In the above sample, assume the inode number of /ro/fileA is i111 and -+aufs assigns the inode number i999 for fileA. Then aufs writes 999 as -+4(8) bytes at 111 * 4(8) bytes offset in the xino file. -+ -+When the inode numbers are not contiguous, the xino file will be sparse -+which has a hole in it and doesn't consume as much disk space as it -+might appear. If your branch filesystem consumes disk space for such -+holes, then you should specify 'xino=' option at mounting aufs. -+ -+Aufs has a mount option to free the disk blocks for such holes in XINO -+files on tmpfs or ramdisk. But it is not so effective actually. If you -+meet a problem of disk shortage due to XINO files, then you should try -+"tmpfs-ino.patch" (and "vfs-ino.patch" too) in aufs4-standalone.git. -+The patch localizes the assignment inumbers per tmpfs-mount and avoid -+the holes in XINO files. -+ -+Also a writable branch has three kinds of "whiteout bases". All these -+are existed when the branch is joined to aufs, and their names are -+whiteout-ed doubly, so that users will never see their names in aufs -+hierarchy. -+1. a regular file which will be hardlinked to all whiteouts. -+2. a directory to store a pseudo-link. -+3. a directory to store an "orphan"-ed file temporary. -+ -+1. Whiteout Base -+ When you remove a file on a readonly branch, aufs handles it as a -+ logical deletion and creates a whiteout on the upper writable branch -+ as a hardlink of this file in order not to consume inode on the -+ writable branch. -+2. Pseudo-link Dir -+ See below, Pseudo-link. -+3. Step-Parent Dir -+ When "fileC" exists on the lower readonly branch only and it is -+ opened and removed with its parent dir, and then user writes -+ something into it, then aufs copies-up fileC to this -+ directory. Because there is no other dir to store fileC. After -+ creating a file under this dir, the file is unlinked. -+ -+Because aufs supports manipulating branches, ie. add/delete/change -+dynamically, a branch has its own id. When the branch order changes, -+aufs finds the new index by searching the branch id. -+ -+ -+Pseudo-link -+---------------------------------------------------------------------- -+Assume "fileA" exists on the lower readonly branch only and it is -+hardlinked to "fileB" on the branch. When you write something to fileA, -+aufs copies-up it to the upper writable branch. Additionally aufs -+creates a hardlink under the Pseudo-link Directory of the writable -+branch. The inode of a pseudo-link is kept in aufs super_block as a -+simple list. If fileB is read after unlinking fileA, aufs returns -+filedata from the pseudo-link instead of the lower readonly -+branch. Because the pseudo-link is based upon the inode, to keep the -+inode number by xino (see above) is essentially necessary. -+ -+All the hardlinks under the Pseudo-link Directory of the writable branch -+should be restored in a proper location later. Aufs provides a utility -+to do this. The userspace helpers executed at remounting and unmounting -+aufs by default. -+During this utility is running, it puts aufs into the pseudo-link -+maintenance mode. In this mode, only the process which began the -+maintenance mode (and its child processes) is allowed to operate in -+aufs. Some other processes which are not related to the pseudo-link will -+be allowed to run too, but the rest have to return an error or wait -+until the maintenance mode ends. If a process already acquires an inode -+mutex (in VFS), it has to return an error. -+ -+ -+XIB(external inode number bitmap) -+---------------------------------------------------------------------- -+Addition to the xino file per a branch, aufs has an external inode number -+bitmap in a superblock object. It is also an internal file such like a -+xino file. -+It is a simple bitmap to mark whether the aufs inode number is in-use or -+not. -+To reduce the file I/O, aufs prepares a single memory page to cache xib. -+ -+As well as XINO files, aufs has a feature to truncate/refresh XIB to -+reduce the number of consumed disk blocks for these files. -+ -+ -+Virtual or Vertical Dir, and Readdir in Userspace -+---------------------------------------------------------------------- -+In order to support multiple layers (branches), aufs readdir operation -+constructs a virtual dir block on memory. For readdir, aufs calls -+vfs_readdir() internally for each dir on branches, merges their entries -+with eliminating the whiteout-ed ones, and sets it to file (dir) -+object. So the file object has its entry list until it is closed. The -+entry list will be updated when the file position is zero and becomes -+obsoleted. This decision is made in aufs automatically. -+ -+The dynamically allocated memory block for the name of entries has a -+unit of 512 bytes (by default) and stores the names contiguously (no -+padding). Another block for each entry is handled by kmem_cache too. -+During building dir blocks, aufs creates hash list and judging whether -+the entry is whiteouted by its upper branch or already listed. -+The merged result is cached in the corresponding inode object and -+maintained by a customizable life-time option. -+ -+Some people may call it can be a security hole or invite DoS attack -+since the opened and once readdir-ed dir (file object) holds its entry -+list and becomes a pressure for system memory. But I'd say it is similar -+to files under /proc or /sys. The virtual files in them also holds a -+memory page (generally) while they are opened. When an idea to reduce -+memory for them is introduced, it will be applied to aufs too. -+For those who really hate this situation, I've developed readdir(3) -+library which operates this merging in userspace. You just need to set -+LD_PRELOAD environment variable, and aufs will not consume no memory in -+kernel space for readdir(3). -+ -+ -+Workqueue -+---------------------------------------------------------------------- -+Aufs sometimes requires privilege access to a branch. For instance, -+in copy-up/down operation. When a user process is going to make changes -+to a file which exists in the lower readonly branch only, and the mode -+of one of ancestor directories may not be writable by a user -+process. Here aufs copy-up the file with its ancestors and they may -+require privilege to set its owner/group/mode/etc. -+This is a typical case of a application character of aufs (see -+Introduction). -+ -+Aufs uses workqueue synchronously for this case. It creates its own -+workqueue. The workqueue is a kernel thread and has privilege. Aufs -+passes the request to call mkdir or write (for example), and wait for -+its completion. This approach solves a problem of a signal handler -+simply. -+If aufs didn't adopt the workqueue and changed the privilege of the -+process, then the process may receive the unexpected SIGXFSZ or other -+signals. -+ -+Also aufs uses the system global workqueue ("events" kernel thread) too -+for asynchronous tasks, such like handling inotify/fsnotify, re-creating a -+whiteout base and etc. This is unrelated to a privilege. -+Most of aufs operation tries acquiring a rw_semaphore for aufs -+superblock at the beginning, at the same time waits for the completion -+of all queued asynchronous tasks. -+ -+ -+Whiteout -+---------------------------------------------------------------------- -+The whiteout in aufs is very similar to Unionfs's. That is represented -+by its filename. UnionMount takes an approach of a file mode, but I am -+afraid several utilities (find(1) or something) will have to support it. -+ -+Basically the whiteout represents "logical deletion" which stops aufs to -+lookup further, but also it represents "dir is opaque" which also stop -+further lookup. -+ -+In aufs, rmdir(2) and rename(2) for dir uses whiteout alternatively. -+In order to make several functions in a single systemcall to be -+revertible, aufs adopts an approach to rename a directory to a temporary -+unique whiteouted name. -+For example, in rename(2) dir where the target dir already existed, aufs -+renames the target dir to a temporary unique whiteouted name before the -+actual rename on a branch, and then handles other actions (make it opaque, -+update the attributes, etc). If an error happens in these actions, aufs -+simply renames the whiteouted name back and returns an error. If all are -+succeeded, aufs registers a function to remove the whiteouted unique -+temporary name completely and asynchronously to the system global -+workqueue. -+ -+ -+Copy-up -+---------------------------------------------------------------------- -+It is a well-known feature or concept. -+When user modifies a file on a readonly branch, aufs operate "copy-up" -+internally and makes change to the new file on the upper writable branch. -+When the trigger systemcall does not update the timestamps of the parent -+dir, aufs reverts it after copy-up. -+ -+ -+Move-down (aufs3.9 and later) -+---------------------------------------------------------------------- -+"Copy-up" is one of the essential feature in aufs. It copies a file from -+the lower readonly branch to the upper writable branch when a user -+changes something about the file. -+"Move-down" is an opposite action of copy-up. Basically this action is -+ran manually instead of automatically and internally. -+For desgin and implementation, aufs has to consider these issues. -+- whiteout for the file may exist on the lower branch. -+- ancestor directories may not exist on the lower branch. -+- diropq for the ancestor directories may exist on the upper branch. -+- free space on the lower branch will reduce. -+- another access to the file may happen during moving-down, including -+ UDBA (see "Revalidate Dentry and UDBA"). -+- the file should not be hard-linked nor pseudo-linked. they should be -+ handled by auplink utility later. -+ -+Sometimes users want to move-down a file from the upper writable branch -+to the lower readonly or writable branch. For instance, -+- the free space of the upper writable branch is going to run out. -+- create a new intermediate branch between the upper and lower branch. -+- etc. -+ -+For this purpose, use "aumvdown" command in aufs-util.git. -diff --git a/Documentation/filesystems/aufs/design/03atomic_open.txt b/Documentation/filesystems/aufs/design/03atomic_open.txt -new file mode 100644 -index 000000000000..415205649c4c ---- /dev/null -+++ b/Documentation/filesystems/aufs/design/03atomic_open.txt -@@ -0,0 +1,72 @@ -+ -+# Copyright (C) 2015-2020 Junjiro R. Okajima -+ -+Support for a branch who has its ->atomic_open() -+---------------------------------------------------------------------- -+The filesystems who implement its ->atomic_open() are not majority. For -+example NFSv4 does, and aufs should call NFSv4 ->atomic_open, -+particularly for open(O_CREAT|O_EXCL, 0400) case. Other than -+->atomic_open(), NFSv4 returns an error for this open(2). While I am not -+sure whether all filesystems who have ->atomic_open() behave like this, -+but NFSv4 surely returns the error. -+ -+In order to support ->atomic_open() for aufs, there are a few -+approaches. -+ -+A. Introduce aufs_atomic_open() -+ - calls one of VFS:do_last(), lookup_open() or atomic_open() for -+ branch fs. -+B. Introduce aufs_atomic_open() calling create, open and chmod. this is -+ an aufs user Pip Cet's approach -+ - calls aufs_create(), VFS finish_open() and notify_change(). -+ - pass fake-mode to finish_open(), and then correct the mode by -+ notify_change(). -+C. Extend aufs_open() to call branch fs's ->atomic_open() -+ - no aufs_atomic_open(). -+ - aufs_lookup() registers the TID to an aufs internal object. -+ - aufs_create() does nothing when the matching TID is registered, but -+ registers the mode. -+ - aufs_open() calls branch fs's ->atomic_open() when the matching -+ TID is registered. -+D. Extend aufs_open() to re-try branch fs's ->open() with superuser's -+ credential -+ - no aufs_atomic_open(). -+ - aufs_create() registers the TID to an internal object. this info -+ represents "this process created this file just now." -+ - when aufs gets EACCES from branch fs's ->open(), then confirm the -+ registered TID and re-try open() with superuser's credential. -+ -+Pros and cons for each approach. -+ -+A. -+ - straightforward but highly depends upon VFS internal. -+ - the atomic behavaiour is kept. -+ - some of parameters such as nameidata are hard to reproduce for -+ branch fs. -+ - large overhead. -+B. -+ - easy to implement. -+ - the atomic behavaiour is lost. -+C. -+ - the atomic behavaiour is kept. -+ - dirty and tricky. -+ - VFS checks whether the file is created correctly after calling -+ ->create(), which means this approach doesn't work. -+D. -+ - easy to implement. -+ - the atomic behavaiour is lost. -+ - to open a file with superuser's credential and give it to a user -+ process is a bad idea, since the file object keeps the credential -+ in it. It may affect LSM or something. This approach doesn't work -+ either. -+ -+The approach A is ideal, but it hard to implement. So here is a -+variation of A, which is to be implemented. -+ -+A-1. Introduce aufs_atomic_open() -+ - calls branch fs ->atomic_open() if exists. otherwise calls -+ vfs_create() and finish_open(). -+ - the demerit is that the several checks after branch fs -+ ->atomic_open() are lost. in the ordinary case, the checks are -+ done by VFS:do_last(), lookup_open() and atomic_open(). some can -+ be implemented in aufs, but not all I am afraid. -diff --git a/Documentation/filesystems/aufs/design/03lookup.txt b/Documentation/filesystems/aufs/design/03lookup.txt -new file mode 100644 -index 000000000000..0b3b22bc999f ---- /dev/null -+++ b/Documentation/filesystems/aufs/design/03lookup.txt -@@ -0,0 +1,100 @@ -+ -+# Copyright (C) 2005-2020 Junjiro R. Okajima -+ -+Lookup in a Branch -+---------------------------------------------------------------------- -+Since aufs has a character of sub-VFS (see Introduction), it operates -+lookup for branches as VFS does. It may be a heavy work. But almost all -+lookup operation in aufs is the simplest case, ie. lookup only an entry -+directly connected to its parent. Digging down the directory hierarchy -+is unnecessary. VFS has a function lookup_one_len() for that use, and -+aufs calls it. -+ -+When a branch is a remote filesystem, aufs basically relies upon its -+->d_revalidate(), also aufs forces the hardest revalidate tests for -+them. -+For d_revalidate, aufs implements three levels of revalidate tests. See -+"Revalidate Dentry and UDBA" in detail. -+ -+ -+Test Only the Highest One for the Directory Permission (dirperm1 option) -+---------------------------------------------------------------------- -+Let's try case study. -+- aufs has two branches, upper readwrite and lower readonly. -+ /au = /rw + /ro -+- "dirA" exists under /ro, but /rw. and its mode is 0700. -+- user invoked "chmod a+rx /au/dirA" -+- the internal copy-up is activated and "/rw/dirA" is created and its -+ permission bits are set to world readable. -+- then "/au/dirA" becomes world readable? -+ -+In this case, /ro/dirA is still 0700 since it exists in readonly branch, -+or it may be a natively readonly filesystem. If aufs respects the lower -+branch, it should not respond readdir request from other users. But user -+allowed it by chmod. Should really aufs rejects showing the entries -+under /ro/dirA? -+ -+To be honest, I don't have a good solution for this case. So aufs -+implements 'dirperm1' and 'nodirperm1' mount options, and leave it to -+users. -+When dirperm1 is specified, aufs checks only the highest one for the -+directory permission, and shows the entries. Otherwise, as usual, checks -+every dir existing on all branches and rejects the request. -+ -+As a side effect, dirperm1 option improves the performance of aufs -+because the number of permission check is reduced when the number of -+branch is many. -+ -+ -+Revalidate Dentry and UDBA (User's Direct Branch Access) -+---------------------------------------------------------------------- -+Generally VFS helpers re-validate a dentry as a part of lookup. -+0. digging down the directory hierarchy. -+1. lock the parent dir by its i_mutex. -+2. lookup the final (child) entry. -+3. revalidate it. -+4. call the actual operation (create, unlink, etc.) -+5. unlock the parent dir -+ -+If the filesystem implements its ->d_revalidate() (step 3), then it is -+called. Actually aufs implements it and checks the dentry on a branch is -+still valid. -+But it is not enough. Because aufs has to release the lock for the -+parent dir on a branch at the end of ->lookup() (step 2) and -+->d_revalidate() (step 3) while the i_mutex of the aufs dir is still -+held by VFS. -+If the file on a branch is changed directly, eg. bypassing aufs, after -+aufs released the lock, then the subsequent operation may cause -+something unpleasant result. -+ -+This situation is a result of VFS architecture, ->lookup() and -+->d_revalidate() is separated. But I never say it is wrong. It is a good -+design from VFS's point of view. It is just not suitable for sub-VFS -+character in aufs. -+ -+Aufs supports such case by three level of revalidation which is -+selectable by user. -+1. Simple Revalidate -+ Addition to the native flow in VFS's, confirm the child-parent -+ relationship on the branch just after locking the parent dir on the -+ branch in the "actual operation" (step 4). When this validation -+ fails, aufs returns EBUSY. ->d_revalidate() (step 3) in aufs still -+ checks the validation of the dentry on branches. -+2. Monitor Changes Internally by Inotify/Fsnotify -+ Addition to above, in the "actual operation" (step 4) aufs re-lookup -+ the dentry on the branch, and returns EBUSY if it finds different -+ dentry. -+ Additionally, aufs sets the inotify/fsnotify watch for every dir on branches -+ during it is in cache. When the event is notified, aufs registers a -+ function to kernel 'events' thread by schedule_work(). And the -+ function sets some special status to the cached aufs dentry and inode -+ private data. If they are not cached, then aufs has nothing to -+ do. When the same file is accessed through aufs (step 0-3) later, -+ aufs will detect the status and refresh all necessary data. -+ In this mode, aufs has to ignore the event which is fired by aufs -+ itself. -+3. No Extra Validation -+ This is the simplest test and doesn't add any additional revalidation -+ test, and skip the revalidation in step 4. It is useful and improves -+ aufs performance when system surely hide the aufs branches from user, -+ by over-mounting something (or another method). -diff --git a/Documentation/filesystems/aufs/design/04branch.txt b/Documentation/filesystems/aufs/design/04branch.txt -new file mode 100644 -index 000000000000..0e7bc1075f37 ---- /dev/null -+++ b/Documentation/filesystems/aufs/design/04branch.txt -@@ -0,0 +1,61 @@ -+ -+# Copyright (C) 2005-2020 Junjiro R. Okajima -+ -+Branch Manipulation -+ -+Since aufs supports dynamic branch manipulation, ie. add/remove a branch -+and changing its permission/attribute, there are a lot of works to do. -+ -+ -+Add a Branch -+---------------------------------------------------------------------- -+o Confirm the adding dir exists outside of aufs, including loopback -+ mount, and its various attributes. -+o Initialize the xino file and whiteout bases if necessary. -+ See struct.txt. -+ -+o Check the owner/group/mode of the directory -+ When the owner/group/mode of the adding directory differs from the -+ existing branch, aufs issues a warning because it may impose a -+ security risk. -+ For example, when a upper writable branch has a world writable empty -+ top directory, a malicious user can create any files on the writable -+ branch directly, like copy-up and modify manually. If something like -+ /etc/{passwd,shadow} exists on the lower readonly branch but the upper -+ writable branch, and the writable branch is world-writable, then a -+ malicious guy may create /etc/passwd on the writable branch directly -+ and the infected file will be valid in aufs. -+ I am afraid it can be a security issue, but aufs can do nothing except -+ producing a warning. -+ -+ -+Delete a Branch -+---------------------------------------------------------------------- -+o Confirm the deleting branch is not busy -+ To be general, there is one merit to adopt "remount" interface to -+ manipulate branches. It is to discard caches. At deleting a branch, -+ aufs checks the still cached (and connected) dentries and inodes. If -+ there are any, then they are all in-use. An inode without its -+ corresponding dentry can be alive alone (for example, inotify/fsnotify case). -+ -+ For the cached one, aufs checks whether the same named entry exists on -+ other branches. -+ If the cached one is a directory, because aufs provides a merged view -+ to users, as long as one dir is left on any branch aufs can show the -+ dir to users. In this case, the branch can be removed from aufs. -+ Otherwise aufs rejects deleting the branch. -+ -+ If any file on the deleting branch is opened by aufs, then aufs -+ rejects deleting. -+ -+ -+Modify the Permission of a Branch -+---------------------------------------------------------------------- -+o Re-initialize or remove the xino file and whiteout bases if necessary. -+ See struct.txt. -+ -+o rw --> ro: Confirm the modifying branch is not busy -+ Aufs rejects the request if any of these conditions are true. -+ - a file on the branch is mmap-ed. -+ - a regular file on the branch is opened for write and there is no -+ same named entry on the upper branch. -diff --git a/Documentation/filesystems/aufs/design/05wbr_policy.txt b/Documentation/filesystems/aufs/design/05wbr_policy.txt -new file mode 100644 -index 000000000000..f9741c32cbf2 ---- /dev/null -+++ b/Documentation/filesystems/aufs/design/05wbr_policy.txt -@@ -0,0 +1,51 @@ -+ -+# Copyright (C) 2005-2020 Junjiro R. Okajima -+ -+Policies to Select One among Multiple Writable Branches -+---------------------------------------------------------------------- -+When the number of writable branch is more than one, aufs has to decide -+the target branch for file creation or copy-up. By default, the highest -+writable branch which has the parent (or ancestor) dir of the target -+file is chosen (top-down-parent policy). -+By user's request, aufs implements some other policies to select the -+writable branch, for file creation several policies, round-robin, -+most-free-space, and other policies. For copy-up, top-down-parent, -+bottom-up-parent, bottom-up and others. -+ -+As expected, the round-robin policy selects the branch in circular. When -+you have two writable branches and creates 10 new files, 5 files will be -+created for each branch. mkdir(2) systemcall is an exception. When you -+create 10 new directories, all will be created on the same branch. -+And the most-free-space policy selects the one which has most free -+space among the writable branches. The amount of free space will be -+checked by aufs internally, and users can specify its time interval. -+ -+The policies for copy-up is more simple, -+top-down-parent is equivalent to the same named on in create policy, -+bottom-up-parent selects the writable branch where the parent dir -+exists and the nearest upper one from the copyup-source, -+bottom-up selects the nearest upper writable branch from the -+copyup-source, regardless the existence of the parent dir. -+ -+There are some rules or exceptions to apply these policies. -+- If there is a readonly branch above the policy-selected branch and -+ the parent dir is marked as opaque (a variation of whiteout), or the -+ target (creating) file is whiteout-ed on the upper readonly branch, -+ then the result of the policy is ignored and the target file will be -+ created on the nearest upper writable branch than the readonly branch. -+- If there is a writable branch above the policy-selected branch and -+ the parent dir is marked as opaque or the target file is whiteouted -+ on the branch, then the result of the policy is ignored and the target -+ file will be created on the highest one among the upper writable -+ branches who has diropq or whiteout. In case of whiteout, aufs removes -+ it as usual. -+- link(2) and rename(2) systemcalls are exceptions in every policy. -+ They try selecting the branch where the source exists as possible -+ since copyup a large file will take long time. If it can't be, -+ ie. the branch where the source exists is readonly, then they will -+ follow the copyup policy. -+- There is an exception for rename(2) when the target exists. -+ If the rename target exists, aufs compares the index of the branches -+ where the source and the target exists and selects the higher -+ one. If the selected branch is readonly, then aufs follows the -+ copyup policy. -diff --git a/Documentation/filesystems/aufs/design/06dirren.dot b/Documentation/filesystems/aufs/design/06dirren.dot -new file mode 100644 -index 000000000000..2d62bb6dd55f ---- /dev/null -+++ b/Documentation/filesystems/aufs/design/06dirren.dot -@@ -0,0 +1,31 @@ -+ -+// to view this graph, run dot(1) command in GRAPHVIZ. -+ -+digraph G { -+node [shape=box]; -+whinfo [label="detailed info file\n(lower_brid_root-hinum, h_inum, namelen, old name)"]; -+ -+node [shape=oval]; -+ -+aufs_rename -> whinfo [label="store/remove"]; -+ -+node [shape=oval]; -+inode_list [label="h_inum list in branch\ncache"]; -+ -+node [shape=box]; -+whinode [label="h_inum list file"]; -+ -+node [shape=oval]; -+brmgmt [label="br_add/del/mod/umount"]; -+ -+brmgmt -> inode_list [label="create/remove"]; -+brmgmt -> whinode [label="load/store"]; -+ -+inode_list -> whinode [style=dashed,dir=both]; -+ -+aufs_rename -> inode_list [label="add/del"]; -+ -+aufs_lookup -> inode_list [label="search"]; -+ -+aufs_lookup -> whinfo [label="load/remove"]; -+} -diff --git a/Documentation/filesystems/aufs/design/06dirren.txt b/Documentation/filesystems/aufs/design/06dirren.txt -new file mode 100644 -index 000000000000..e23459758504 ---- /dev/null -+++ b/Documentation/filesystems/aufs/design/06dirren.txt -@@ -0,0 +1,89 @@ -+ -+# Copyright (C) 2017-2020 Junjiro R. Okajima -+ -+Special handling for renaming a directory (DIRREN) -+---------------------------------------------------------------------- -+First, let's assume we have a simple usecase. -+ -+- /u = /rw + /ro -+- /rw/dirA exists -+- /ro/dirA and /ro/dirA/file exist too -+- there is no dirB on both branches -+- a user issues rename("dirA", "dirB") -+ -+Now, what should aufs behave against this rename(2)? -+There are a few possible cases. -+ -+A. returns EROFS. -+ since dirA exists on a readonly branch which cannot be renamed. -+B. returns EXDEV. -+ it is possible to copy-up dirA (only the dir itself), but the child -+ entries ("file" in this case) should not be. it must be a bad -+ approach to copy-up recursively. -+C. returns a success. -+ even the branch /ro is readonly, aufs tries renaming it. Obviously it -+ is a violation of aufs' policy. -+D. construct an extra information which indicates that /ro/dirA should -+ be handled as the name of dirB. -+ overlayfs has a similar feature called REDIRECT. -+ -+Until now, aufs implements the case B only which returns EXDEV, and -+expects the userspace application behaves like mv(1) which tries -+issueing rename(2) recursively. -+ -+A new aufs feature called DIRREN is introduced which implements the case -+D. There are several "extra information" added. -+ -+1. detailed info per renamed directory -+ path: /rw/dirB/$AUFS_WH_DR_INFO_PFX. -+2. the inode-number list of directories on a branch -+ path: /rw/dirB/$AUFS_WH_DR_BRHINO -+ -+The filename of "detailed info per directory" represents the lower -+branch, and its format is -+- a type of the branch id -+ one of these. -+ + uuid (not implemented yet) -+ + fsid -+ + dev -+- the inode-number of the branch root dir -+ -+And it contains these info in a single regular file. -+- magic number -+- branch's inode-number of the logically renamed dir -+- the name of the before-renamed dir -+ -+The "detailed info per directory" file is created in aufs rename(2), and -+loaded in any lookup. -+The info is considered in lookup for the matching case only. Here -+"matching" means that the root of branch (in the info filename) is same -+to the current looking-up branch. After looking-up the before-renamed -+name, the inode-number is compared. And the matched dentry is used. -+ -+The "inode-number list of directories" is a regular file which contains -+simply the inode-numbers on the branch. The file is created or updated -+in removing the branch, and loaded in adding the branch. Its lifetime is -+equal to the branch. -+The list is refered in lookup, and when the current target inode is -+found in the list, the aufs tries loading the "detailed info per -+directory" and get the changed and valid name of the dir. -+ -+Theoretically these "extra informaiton" may be able to be put into XATTR -+in the dir inode. But aufs doesn't choose this way because -+1. XATTR may not be supported by the branch (or its configuration) -+2. XATTR may have its size limit. -+3. XATTR may be less easy to convert than a regular file, when the -+ format of the info is changed in the future. -+At the same time, I agree that the regular file approach is much slower -+than XATTR approach. So, in the future, aufs may take the XATTR or other -+better approach. -+ -+This DIRREN feature is enabled by aufs configuration, and is activated -+by a new mount option. -+ -+For the more complicated case, there is a work with UDBA option, which -+is to dected the direct access to the branches (by-passing aufs) and to -+maintain the cashes in aufs. Since a single cached aufs dentry may -+contains two names, before- and after-rename, the name comparision in -+UDBA handler may not work correctly. In this case, the behaviour will be -+equivalen to udba=reval case. -diff --git a/Documentation/filesystems/aufs/design/06fhsm.txt b/Documentation/filesystems/aufs/design/06fhsm.txt -new file mode 100644 -index 000000000000..5322ca3b7151 ---- /dev/null -+++ b/Documentation/filesystems/aufs/design/06fhsm.txt -@@ -0,0 +1,105 @@ -+ -+# Copyright (C) 2011-2020 Junjiro R. Okajima -+ -+File-based Hierarchical Storage Management (FHSM) -+---------------------------------------------------------------------- -+Hierarchical Storage Management (or HSM) is a well-known feature in the -+storage world. Aufs provides this feature as file-based with multiple -+writable branches, based upon the principle of "Colder, the Lower". -+Here the word "colder" means that the less used files, and "lower" means -+that the position in the order of the stacked branches vertically. -+These multiple writable branches are prioritized, ie. the topmost one -+should be the fastest drive and be used heavily. -+ -+o Characters in aufs FHSM story -+- aufs itself and a new branch attribute. -+- a new ioctl interface to move-down and to establish a connection with -+ the daemon ("move-down" is a converse of "copy-up"). -+- userspace tool and daemon. -+ -+The userspace daemon establishes a connection with aufs and waits for -+the notification. The notified information is very similar to struct -+statfs containing the number of consumed blocks and inodes. -+When the consumed blocks/inodes of a branch exceeds the user-specified -+upper watermark, the daemon activates its move-down process until the -+consumed blocks/inodes reaches the user-specified lower watermark. -+ -+The actual move-down is done by aufs based upon the request from -+user-space since we need to maintain the inode number and the internal -+pointer arrays in aufs. -+ -+Currently aufs FHSM handles the regular files only. Additionally they -+must not be hard-linked nor pseudo-linked. -+ -+ -+o Cowork of aufs and the user-space daemon -+ During the userspace daemon established the connection, aufs sends a -+ small notification to it whenever aufs writes something into the -+ writable branch. But it may cost high since aufs issues statfs(2) -+ internally. So user can specify a new option to cache the -+ info. Actually the notification is controlled by these factors. -+ + the specified cache time. -+ + classified as "force" by aufs internally. -+ Until the specified time expires, aufs doesn't send the info -+ except the forced cases. When aufs decide forcing, the info is always -+ notified to userspace. -+ For example, the number of free inodes is generally large enough and -+ the shortage of it happens rarely. So aufs doesn't force the -+ notification when creating a new file, directory and others. This is -+ the typical case which aufs doesn't force. -+ When aufs writes the actual filedata and the files consumes any of new -+ blocks, the aufs forces notifying. -+ -+ -+o Interfaces in aufs -+- New branch attribute. -+ + fhsm -+ Specifies that the branch is managed by FHSM feature. In other word, -+ participant in the FHSM. -+ When nofhsm is set to the branch, it will not be the source/target -+ branch of the move-down operation. This attribute is set -+ independently from coo and moo attributes, and if you want full -+ FHSM, you should specify them as well. -+- New mount option. -+ + fhsm_sec -+ Specifies a second to suppress many less important info to be -+ notified. -+- New ioctl. -+ + AUFS_CTL_FHSM_FD -+ create a new file descriptor which userspace can read the notification -+ (a subset of struct statfs) from aufs. -+- Module parameter 'brs' -+ It has to be set to 1. Otherwise the new mount option 'fhsm' will not -+ be set. -+- mount helpers /sbin/mount.aufs and /sbin/umount.aufs -+ When there are two or more branches with fhsm attributes, -+ /sbin/mount.aufs invokes the user-space daemon and /sbin/umount.aufs -+ terminates it. As a result of remounting and branch-manipulation, the -+ number of branches with fhsm attribute can be one. In this case, -+ /sbin/mount.aufs will terminate the user-space daemon. -+ -+ -+Finally the operation is done as these steps in kernel-space. -+- make sure that, -+ + no one else is using the file. -+ + the file is not hard-linked. -+ + the file is not pseudo-linked. -+ + the file is a regular file. -+ + the parent dir is not opaqued. -+- find the target writable branch. -+- make sure the file is not whiteout-ed by the upper (than the target) -+ branch. -+- make the parent dir on the target branch. -+- mutex lock the inode on the branch. -+- unlink the whiteout on the target branch (if exists). -+- lookup and create the whiteout-ed temporary name on the target branch. -+- copy the file as the whiteout-ed temporary name on the target branch. -+- rename the whiteout-ed temporary name to the original name. -+- unlink the file on the source branch. -+- maintain the internal pointer array and the external inode number -+ table (XINO). -+- maintain the timestamps and other attributes of the parent dir and the -+ file. -+ -+And of course, in every step, an error may happen. So the operation -+should restore the original file state after an error happens. -diff --git a/Documentation/filesystems/aufs/design/06mmap.txt b/Documentation/filesystems/aufs/design/06mmap.txt -new file mode 100644 -index 000000000000..03b71096d508 ---- /dev/null -+++ b/Documentation/filesystems/aufs/design/06mmap.txt -@@ -0,0 +1,59 @@ -+ -+# Copyright (C) 2005-2020 Junjiro R. Okajima -+ -+mmap(2) -- File Memory Mapping -+---------------------------------------------------------------------- -+In aufs, the file-mapped pages are handled by a branch fs directly, no -+interaction with aufs. It means aufs_mmap() calls the branch fs's -+->mmap(). -+This approach is simple and good, but there is one problem. -+Under /proc, several entries show the mmapped files by its path (with -+device and inode number), and the printed path will be the path on the -+branch fs's instead of virtual aufs's. -+This is not a problem in most cases, but some utilities lsof(1) (and its -+user) may expect the path on aufs. -+ -+To address this issue, aufs adds a new member called vm_prfile in struct -+vm_area_struct (and struct vm_region). The original vm_file points to -+the file on the branch fs in order to handle everything correctly as -+usual. The new vm_prfile points to a virtual file in aufs, and the -+show-functions in procfs refers to vm_prfile if it is set. -+Also we need to maintain several other places where touching vm_file -+such like -+- fork()/clone() copies vma and the reference count of vm_file is -+ incremented. -+- merging vma maintains the ref count too. -+ -+This is not a good approach. It just fakes the printed path. But it -+leaves all behaviour around f_mapping unchanged. This is surely an -+advantage. -+Actually aufs had adopted another complicated approach which calls -+generic_file_mmap() and handles struct vm_operations_struct. In this -+approach, aufs met a hard problem and I could not solve it without -+switching the approach. -+ -+There may be one more another approach which is -+- bind-mount the branch-root onto the aufs-root internally -+- grab the new vfsmount (ie. struct mount) -+- lazy-umount the branch-root internally -+- in open(2) the aufs-file, open the branch-file with the hidden -+ vfsmount (instead of the original branch's vfsmount) -+- ideally this "bind-mount and lazy-umount" should be done atomically, -+ but it may be possible from userspace by the mount helper. -+ -+Adding the internal hidden vfsmount and using it in opening a file, the -+file path under /proc will be printed correctly. This approach looks -+smarter, but is not possible I am afraid. -+- aufs-root may be bind-mount later. when it happens, another hidden -+ vfsmount will be required. -+- it is hard to get the chance to bind-mount and lazy-umount -+ + in kernel-space, FS can have vfsmount in open(2) via -+ file->f_path, and aufs can know its vfsmount. But several locks are -+ already acquired, and if aufs tries to bind-mount and lazy-umount -+ here, then it may cause a deadlock. -+ + in user-space, bind-mount doesn't invoke the mount helper. -+- since /proc shows dev and ino, aufs has to give vma these info. it -+ means a new member vm_prinode will be necessary. this is essentially -+ equivalent to vm_prfile described above. -+ -+I have to give up this "looks-smater" approach. -diff --git a/Documentation/filesystems/aufs/design/06xattr.txt b/Documentation/filesystems/aufs/design/06xattr.txt -new file mode 100644 -index 000000000000..f4076a04a335 ---- /dev/null -+++ b/Documentation/filesystems/aufs/design/06xattr.txt -@@ -0,0 +1,81 @@ -+ -+# Copyright (C) 2014-2020 Junjiro R. Okajima -+ -+Listing XATTR/EA and getting the value -+---------------------------------------------------------------------- -+For the inode standard attributes (owner, group, timestamps, etc.), aufs -+shows the values from the topmost existing file. This behaviour is good -+for the non-dir entries since the bahaviour exactly matches the shown -+information. But for the directories, aufs considers all the same named -+entries on the lower branches. Which means, if one of the lower entry -+rejects readdir call, then aufs returns an error even if the topmost -+entry allows it. This behaviour is necessary to respect the branch fs's -+security, but can make users confused since the user-visible standard -+attributes don't match the behaviour. -+To address this issue, aufs has a mount option called dirperm1 which -+checks the permission for the topmost entry only, and ignores the lower -+entry's permission. -+ -+A similar issue can happen around XATTR. -+getxattr(2) and listxattr(2) families behave as if dirperm1 option is -+always set. Otherwise these very unpleasant situation would happen. -+- listxattr(2) may return the duplicated entries. -+- users may not be able to remove or reset the XATTR forever, -+ -+ -+XATTR/EA support in the internal (copy,move)-(up,down) -+---------------------------------------------------------------------- -+Generally the extended attributes of inode are categorized as these. -+- "security" for LSM and capability. -+- "system" for posix ACL, 'acl' mount option is required for the branch -+ fs generally. -+- "trusted" for userspace, CAP_SYS_ADMIN is required. -+- "user" for userspace, 'user_xattr' mount option is required for the -+ branch fs generally. -+ -+Moreover there are some other categories. Aufs handles these rather -+unpopular categories as the ordinary ones, ie. there is no special -+condition nor exception. -+ -+In copy-up, the support for XATTR on the dst branch may differ from the -+src branch. In this case, the copy-up operation will get an error and -+the original user operation which triggered the copy-up will fail. It -+can happen that even all copy-up will fail. -+When both of src and dst branches support XATTR and if an error occurs -+during copying XATTR, then the copy-up should fail obviously. That is a -+good reason and aufs should return an error to userspace. But when only -+the src branch support that XATTR, aufs should not return an error. -+For example, the src branch supports ACL but the dst branch doesn't -+because the dst branch may natively un-support it or temporary -+un-support it due to "noacl" mount option. Of course, the dst branch fs -+may NOT return an error even if the XATTR is not supported. It is -+totally up to the branch fs. -+ -+Anyway when the aufs internal copy-up gets an error from the dst branch -+fs, then aufs tries removing the just copied entry and returns the error -+to the userspace. The worst case of this situation will be all copy-up -+will fail. -+ -+For the copy-up operation, there two basic approaches. -+- copy the specified XATTR only (by category above), and return the -+ error unconditionally if it happens. -+- copy all XATTR, and ignore the error on the specified category only. -+ -+In order to support XATTR and to implement the correct behaviour, aufs -+chooses the latter approach and introduces some new branch attributes, -+"icexsec", "icexsys", "icextr", "icexusr", and "icexoth". -+They correspond to the XATTR namespaces (see above). Additionally, to be -+convenient, "icex" is also provided which means all "icex*" attributes -+are set (here the word "icex" stands for "ignore copy-error on XATTR"). -+ -+The meaning of these attributes is to ignore the error from setting -+XATTR on that branch. -+Note that aufs tries copying all XATTR unconditionally, and ignores the -+error from the dst branch according to the specified attributes. -+ -+Some XATTR may have its default value. The default value may come from -+the parent dir or the environment. If the default value is set at the -+file creating-time, it will be overwritten by copy-up. -+Some contradiction may happen I am afraid. -+Do we need another attribute to stop copying XATTR? I am unsure. For -+now, aufs implements the branch attributes to ignore the error. -diff --git a/Documentation/filesystems/aufs/design/07export.txt b/Documentation/filesystems/aufs/design/07export.txt -new file mode 100644 -index 000000000000..fcd3a3489bf8 ---- /dev/null -+++ b/Documentation/filesystems/aufs/design/07export.txt -@@ -0,0 +1,45 @@ -+ -+# Copyright (C) 2005-2020 Junjiro R. Okajima -+ -+Export Aufs via NFS -+---------------------------------------------------------------------- -+Here is an approach. -+- like xino/xib, add a new file 'xigen' which stores aufs inode -+ generation. -+- iget_locked(): initialize aufs inode generation for a new inode, and -+ store it in xigen file. -+- destroy_inode(): increment aufs inode generation and store it in xigen -+ file. it is necessary even if it is not unlinked, because any data of -+ inode may be changed by UDBA. -+- encode_fh(): for a root dir, simply return FILEID_ROOT. otherwise -+ build file handle by -+ + branch id (4 bytes) -+ + superblock generation (4 bytes) -+ + inode number (4 or 8 bytes) -+ + parent dir inode number (4 or 8 bytes) -+ + inode generation (4 bytes)) -+ + return value of exportfs_encode_fh() for the parent on a branch (4 -+ bytes) -+ + file handle for a branch (by exportfs_encode_fh()) -+- fh_to_dentry(): -+ + find the index of a branch from its id in handle, and check it is -+ still exist in aufs. -+ + 1st level: get the inode number from handle and search it in cache. -+ + 2nd level: if not found in cache, get the parent inode number from -+ the handle and search it in cache. and then open the found parent -+ dir, find the matching inode number by vfs_readdir() and get its -+ name, and call lookup_one_len() for the target dentry. -+ + 3rd level: if the parent dir is not cached, call -+ exportfs_decode_fh() for a branch and get the parent on a branch, -+ build a pathname of it, convert it a pathname in aufs, call -+ path_lookup(). now aufs gets a parent dir dentry, then handle it as -+ the 2nd level. -+ + to open the dir, aufs needs struct vfsmount. aufs keeps vfsmount -+ for every branch, but not itself. to get this, (currently) aufs -+ searches in current->nsproxy->mnt_ns list. it may not be a good -+ idea, but I didn't get other approach. -+ + test the generation of the gotten inode. -+- every inode operation: they may get EBUSY due to UDBA. in this case, -+ convert it into ESTALE for NFSD. -+- readdir(): call lockdep_on/off() because filldir in NFSD calls -+ lookup_one_len(), vfs_getattr(), encode_fh() and others. -diff --git a/Documentation/filesystems/aufs/design/08shwh.txt b/Documentation/filesystems/aufs/design/08shwh.txt -new file mode 100644 -index 000000000000..f252e17154b1 ---- /dev/null -+++ b/Documentation/filesystems/aufs/design/08shwh.txt -@@ -0,0 +1,39 @@ -+ -+# Copyright (C) 2005-2020 Junjiro R. Okajima -+ -+Show Whiteout Mode (shwh) -+---------------------------------------------------------------------- -+Generally aufs hides the name of whiteouts. But in some cases, to show -+them is very useful for users. For instance, creating a new middle layer -+(branch) by merging existing layers. -+ -+(borrowing aufs1 HOW-TO from a user, Michael Towers) -+When you have three branches, -+- Bottom: 'system', squashfs (underlying base system), read-only -+- Middle: 'mods', squashfs, read-only -+- Top: 'overlay', ram (tmpfs), read-write -+ -+The top layer is loaded at boot time and saved at shutdown, to preserve -+the changes made to the system during the session. -+When larger changes have been made, or smaller changes have accumulated, -+the size of the saved top layer data grows. At this point, it would be -+nice to be able to merge the two overlay branches ('mods' and 'overlay') -+and rewrite the 'mods' squashfs, clearing the top layer and thus -+restoring save and load speed. -+ -+This merging is simplified by the use of another aufs mount, of just the -+two overlay branches using the 'shwh' option. -+# mount -t aufs -o ro,shwh,br:/livesys/overlay=ro+wh:/livesys/mods=rr+wh \ -+ aufs /livesys/merge_union -+ -+A merged view of these two branches is then available at -+/livesys/merge_union, and the new feature is that the whiteouts are -+visible! -+Note that in 'shwh' mode the aufs mount must be 'ro', which will disable -+writing to all branches. Also the default mode for all branches is 'ro'. -+It is now possible to save the combined contents of the two overlay -+branches to a new squashfs, e.g.: -+# mksquashfs /livesys/merge_union /path/to/newmods.squash -+ -+This new squashfs archive can be stored on the boot device and the -+initramfs will use it to replace the old one at the next boot. -diff --git a/Documentation/filesystems/aufs/design/10dynop.txt b/Documentation/filesystems/aufs/design/10dynop.txt -new file mode 100644 -index 000000000000..2b90eecb267d ---- /dev/null -+++ b/Documentation/filesystems/aufs/design/10dynop.txt -@@ -0,0 +1,34 @@ -+ -+# Copyright (C) 2010-2020 Junjiro R. Okajima -+ -+Dynamically customizable FS operations -+---------------------------------------------------------------------- -+Generally FS operations (struct inode_operations, struct -+address_space_operations, struct file_operations, etc.) are defined as -+"static const", but it never means that FS have only one set of -+operation. Some FS have multiple sets of them. For instance, ext2 has -+three sets, one for XIP, for NOBH, and for normal. -+Since aufs overrides and redirects these operations, sometimes aufs has -+to change its behaviour according to the branch FS type. More importantly -+VFS acts differently if a function (member in the struct) is set or -+not. It means aufs should have several sets of operations and select one -+among them according to the branch FS definition. -+ -+In order to solve this problem and not to affect the behaviour of VFS, -+aufs defines these operations dynamically. For instance, aufs defines -+dummy direct_IO function for struct address_space_operations, but it may -+not be set to the address_space_operations actually. When the branch FS -+doesn't have it, aufs doesn't set it to its address_space_operations -+while the function definition itself is still alive. So the behaviour -+itself will not change, and it will return an error when direct_IO is -+not set. -+ -+The lifetime of these dynamically generated operation object is -+maintained by aufs branch object. When the branch is removed from aufs, -+the reference counter of the object is decremented. When it reaches -+zero, the dynamically generated operation object will be freed. -+ -+This approach is designed to support AIO (io_submit), Direct I/O and -+XIP (DAX) mainly. -+Currently this approach is applied to address_space_operations for -+regular files only. -diff --git a/MAINTAINERS b/MAINTAINERS -index 4e2698cc7e23..491f32f3b072 100644 ---- a/MAINTAINERS -+++ b/MAINTAINERS -@@ -2984,6 +2984,19 @@ F: include/linux/audit.h - F: include/uapi/linux/audit.h - F: kernel/audit* - -+AUFS (advanced multi layered unification filesystem) FILESYSTEM -+M: "J. R. Okajima" -+L: aufs-users@lists.sourceforge.net (members only) -+L: linux-unionfs@vger.kernel.org -+W: http://aufs.sourceforge.net -+T: git://github.com/sfjro/aufs4-linux.git -+S: Supported -+F: Documentation/filesystems/aufs/ -+F: Documentation/ABI/testing/debugfs-aufs -+F: Documentation/ABI/testing/sysfs-aufs -+F: fs/aufs/ -+F: include/uapi/linux/aufs_type.h -+ - AUXILIARY DISPLAY DRIVERS - M: Miguel Ojeda Sandonis - S: Maintained -diff --git a/drivers/block/loop.c b/drivers/block/loop.c -index 475e1a738560..8d77e68aa52b 100644 ---- a/drivers/block/loop.c -+++ b/drivers/block/loop.c -@@ -763,6 +763,24 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev, - return error; - } - -+/* -+ * for AUFS -+ * no get/put for file. -+ */ -+struct file *loop_backing_file(struct super_block *sb) -+{ -+ struct file *ret; -+ struct loop_device *l; -+ -+ ret = NULL; -+ if (MAJOR(sb->s_dev) == LOOP_MAJOR) { -+ l = sb->s_bdev->bd_disk->private_data; -+ ret = l->lo_backing_file; -+ } -+ return ret; -+} -+EXPORT_SYMBOL_GPL(loop_backing_file); -+ - /* loop sysfs attributes */ - - static ssize_t loop_attr_show(struct device *dev, char *page, -diff --git a/fs/Kconfig b/fs/Kconfig -index a88aa3af73c1..0f0caa023fb9 100644 ---- a/fs/Kconfig -+++ b/fs/Kconfig -@@ -267,6 +267,7 @@ source "fs/sysv/Kconfig" - source "fs/ufs/Kconfig" - source "fs/erofs/Kconfig" - source "fs/vboxsf/Kconfig" -+source "fs/aufs/Kconfig" - - endif # MISC_FILESYSTEMS - -diff --git a/fs/Makefile b/fs/Makefile -index 2ce5112b02c8..d9b4a5198553 100644 ---- a/fs/Makefile -+++ b/fs/Makefile -@@ -136,3 +136,4 @@ obj-$(CONFIG_EFIVAR_FS) += efivarfs/ - obj-$(CONFIG_EROFS_FS) += erofs/ - obj-$(CONFIG_VBOXSF_FS) += vboxsf/ - obj-$(CONFIG_ZONEFS_FS) += zonefs/ -+obj-$(CONFIG_AUFS_FS) += aufs/ -diff --git a/fs/aufs/Kconfig b/fs/aufs/Kconfig -new file mode 100644 -index 000000000000..d9ef85bc962e ---- /dev/null -+++ b/fs/aufs/Kconfig -@@ -0,0 +1,199 @@ -+# SPDX-License-Identifier: GPL-2.0 -+config AUFS_FS -+ tristate "Aufs (Advanced multi layered unification filesystem) support" -+ help -+ Aufs is a stackable unification filesystem such as Unionfs, -+ which unifies several directories and provides a merged single -+ directory. -+ In the early days, aufs was entirely re-designed and -+ re-implemented Unionfs Version 1.x series. Introducing many -+ original ideas, approaches and improvements, it becomes totally -+ different from Unionfs while keeping the basic features. -+ -+if AUFS_FS -+choice -+ prompt "Maximum number of branches" -+ default AUFS_BRANCH_MAX_127 -+ help -+ Specifies the maximum number of branches (or member directories) -+ in a single aufs. The larger value consumes more system -+ resources and has a minor impact to performance. -+config AUFS_BRANCH_MAX_127 -+ bool "127" -+ help -+ Specifies the maximum number of branches (or member directories) -+ in a single aufs. The larger value consumes more system -+ resources and has a minor impact to performance. -+config AUFS_BRANCH_MAX_511 -+ bool "511" -+ help -+ Specifies the maximum number of branches (or member directories) -+ in a single aufs. The larger value consumes more system -+ resources and has a minor impact to performance. -+config AUFS_BRANCH_MAX_1023 -+ bool "1023" -+ help -+ Specifies the maximum number of branches (or member directories) -+ in a single aufs. The larger value consumes more system -+ resources and has a minor impact to performance. -+config AUFS_BRANCH_MAX_32767 -+ bool "32767" -+ help -+ Specifies the maximum number of branches (or member directories) -+ in a single aufs. The larger value consumes more system -+ resources and has a minor impact to performance. -+endchoice -+ -+config AUFS_SBILIST -+ bool -+ depends on AUFS_MAGIC_SYSRQ || PROC_FS -+ default y -+ help -+ Automatic configuration for internal use. -+ When aufs supports Magic SysRq or /proc, enabled automatically. -+ -+config AUFS_HNOTIFY -+ bool "Detect direct branch access (bypassing aufs)" -+ help -+ If you want to modify files on branches directly, eg. bypassing aufs, -+ and want aufs to detect the changes of them fully, then enable this -+ option and use 'udba=notify' mount option. -+ Currently there is only one available configuration, "fsnotify". -+ It will have a negative impact to the performance. -+ See detail in aufs.5. -+ -+choice -+ prompt "method" if AUFS_HNOTIFY -+ default AUFS_HFSNOTIFY -+config AUFS_HFSNOTIFY -+ bool "fsnotify" -+ select FSNOTIFY -+endchoice -+ -+config AUFS_EXPORT -+ bool "NFS-exportable aufs" -+ depends on EXPORTFS = y -+ help -+ If you want to export your mounted aufs via NFS, then enable this -+ option. There are several requirements for this configuration. -+ See detail in aufs.5. -+ -+config AUFS_INO_T_64 -+ bool -+ depends on AUFS_EXPORT -+ depends on 64BIT && !(ALPHA || S390) -+ default y -+ help -+ Automatic configuration for internal use. -+ /* typedef unsigned long/int __kernel_ino_t */ -+ /* alpha and s390x are int */ -+ -+config AUFS_XATTR -+ bool "support for XATTR/EA (including Security Labels)" -+ help -+ If your branch fs supports XATTR/EA and you want to make them -+ available in aufs too, then enable this opsion and specify the -+ branch attributes for EA. -+ See detail in aufs.5. -+ -+config AUFS_FHSM -+ bool "File-based Hierarchical Storage Management" -+ help -+ Hierarchical Storage Management (or HSM) is a well-known feature -+ in the storage world. Aufs provides this feature as file-based. -+ with multiple branches. -+ These multiple branches are prioritized, ie. the topmost one -+ should be the fastest drive and be used heavily. -+ -+config AUFS_RDU -+ bool "Readdir in userspace" -+ help -+ Aufs has two methods to provide a merged view for a directory, -+ by a user-space library and by kernel-space natively. The latter -+ is always enabled but sometimes large and slow. -+ If you enable this option, install the library in aufs2-util -+ package, and set some environment variables for your readdir(3), -+ then the work will be handled in user-space which generally -+ shows better performance in most cases. -+ See detail in aufs.5. -+ -+config AUFS_DIRREN -+ bool "Workaround for rename(2)-ing a directory" -+ help -+ By default, aufs returns EXDEV error in renameing a dir who has -+ his child on the lower branch, since it is a bad idea to issue -+ rename(2) internally for every lower branch. But user may not -+ accept this behaviour. So here is a workaround to allow such -+ rename(2) and store some extra infromation on the writable -+ branch. Obviously this costs high (and I don't like it). -+ To use this feature, you need to enable this configuration AND -+ to specify the mount option `dirren.' -+ See details in aufs.5 and the design documents. -+ -+config AUFS_SHWH -+ bool "Show whiteouts" -+ help -+ If you want to make the whiteouts in aufs visible, then enable -+ this option and specify 'shwh' mount option. Although it may -+ sounds like philosophy or something, but in technically it -+ simply shows the name of whiteout with keeping its behaviour. -+ -+config AUFS_BR_RAMFS -+ bool "Ramfs (initramfs/rootfs) as an aufs branch" -+ help -+ If you want to use ramfs as an aufs branch fs, then enable this -+ option. Generally tmpfs is recommended. -+ Aufs prohibited them to be a branch fs by default, because -+ initramfs becomes unusable after switch_root or something -+ generally. If you sets initramfs as an aufs branch and boot your -+ system by switch_root, you will meet a problem easily since the -+ files in initramfs may be inaccessible. -+ Unless you are going to use ramfs as an aufs branch fs without -+ switch_root or something, leave it N. -+ -+config AUFS_BR_FUSE -+ bool "Fuse fs as an aufs branch" -+ depends on FUSE_FS -+ select AUFS_POLL -+ help -+ If you want to use fuse-based userspace filesystem as an aufs -+ branch fs, then enable this option. -+ It implements the internal poll(2) operation which is -+ implemented by fuse only (curretnly). -+ -+config AUFS_POLL -+ bool -+ help -+ Automatic configuration for internal use. -+ -+config AUFS_BR_HFSPLUS -+ bool "Hfsplus as an aufs branch" -+ depends on HFSPLUS_FS -+ default y -+ help -+ If you want to use hfsplus fs as an aufs branch fs, then enable -+ this option. This option introduces a small overhead at -+ copying-up a file on hfsplus. -+ -+config AUFS_BDEV_LOOP -+ bool -+ depends on BLK_DEV_LOOP -+ default y -+ help -+ Automatic configuration for internal use. -+ Convert =[ym] into =y. -+ -+config AUFS_DEBUG -+ bool "Debug aufs" -+ help -+ Enable this to compile aufs internal debug code. -+ It will have a negative impact to the performance. -+ -+config AUFS_MAGIC_SYSRQ -+ bool -+ depends on AUFS_DEBUG && MAGIC_SYSRQ -+ default y -+ help -+ Automatic configuration for internal use. -+ When aufs supports Magic SysRq, enabled automatically. -+endif -diff --git a/fs/aufs/Makefile b/fs/aufs/Makefile -new file mode 100644 -index 000000000000..9de70de0f337 ---- /dev/null -+++ b/fs/aufs/Makefile -@@ -0,0 +1,39 @@ -+# SPDX-License-Identifier: GPL-2.0 -+ -+include ${srctree}/${src}/magic.mk -+-include ${srctree}/${src}/priv_def.mk -+ -+# cf. include/linux/kernel.h -+# enable pr_debug -+ccflags-y += -DDEBUG -+# sparse requires the full pathname -+ccflags-y += -include ${srctree}/include/uapi/linux/aufs_type.h -+ -+obj-$(CONFIG_AUFS_FS) += aufs.o -+aufs-y := module.o sbinfo.o super.o branch.o xino.o sysaufs.o opts.o \ -+ wkq.o vfsub.o dcsub.o \ -+ cpup.o whout.o wbr_policy.o \ -+ dinfo.o dentry.o \ -+ dynop.o \ -+ finfo.o file.o f_op.o \ -+ dir.o vdir.o \ -+ iinfo.o inode.o i_op.o i_op_add.o i_op_del.o i_op_ren.o \ -+ mvdown.o ioctl.o -+ -+# all are boolean -+aufs-$(CONFIG_PROC_FS) += procfs.o plink.o -+aufs-$(CONFIG_SYSFS) += sysfs.o -+aufs-$(CONFIG_DEBUG_FS) += dbgaufs.o -+aufs-$(CONFIG_AUFS_BDEV_LOOP) += loop.o -+aufs-$(CONFIG_AUFS_HNOTIFY) += hnotify.o -+aufs-$(CONFIG_AUFS_HFSNOTIFY) += hfsnotify.o -+aufs-$(CONFIG_AUFS_EXPORT) += export.o -+aufs-$(CONFIG_AUFS_XATTR) += xattr.o -+aufs-$(CONFIG_FS_POSIX_ACL) += posix_acl.o -+aufs-$(CONFIG_AUFS_DIRREN) += dirren.o -+aufs-$(CONFIG_AUFS_FHSM) += fhsm.o -+aufs-$(CONFIG_AUFS_POLL) += poll.o -+aufs-$(CONFIG_AUFS_RDU) += rdu.o -+aufs-$(CONFIG_AUFS_BR_HFSPLUS) += hfsplus.o -+aufs-$(CONFIG_AUFS_DEBUG) += debug.o -+aufs-$(CONFIG_AUFS_MAGIC_SYSRQ) += sysrq.o -diff --git a/fs/aufs/aufs.h b/fs/aufs/aufs.h -new file mode 100644 -index 000000000000..c50f959844e8 ---- /dev/null -+++ b/fs/aufs/aufs.h -@@ -0,0 +1,49 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * all header files -+ */ -+ -+#ifndef __AUFS_H__ -+#define __AUFS_H__ -+ -+#ifdef __KERNEL__ -+ -+#define AuStub(type, name, body, ...) \ -+ static inline type name(__VA_ARGS__) { body; } -+ -+#define AuStubVoid(name, ...) \ -+ AuStub(void, name, , __VA_ARGS__) -+#define AuStubInt0(name, ...) \ -+ AuStub(int, name, return 0, __VA_ARGS__) -+ -+#include "debug.h" -+ -+#include "branch.h" -+#include "cpup.h" -+#include "dcsub.h" -+#include "dbgaufs.h" -+#include "dentry.h" -+#include "dir.h" -+#include "dirren.h" -+#include "dynop.h" -+#include "file.h" -+#include "fstype.h" -+#include "hbl.h" -+#include "inode.h" -+#include "lcnt.h" -+#include "loop.h" -+#include "module.h" -+#include "opts.h" -+#include "rwsem.h" -+#include "super.h" -+#include "sysaufs.h" -+#include "vfsub.h" -+#include "whout.h" -+#include "wkq.h" -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_H__ */ -diff --git a/fs/aufs/branch.c b/fs/aufs/branch.c -new file mode 100644 -index 000000000000..3319245c0361 ---- /dev/null -+++ b/fs/aufs/branch.c -@@ -0,0 +1,1414 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * branch management -+ */ -+ -+#include -+#include -+#include "aufs.h" -+ -+/* -+ * free a single branch -+ */ -+static void au_br_do_free(struct au_branch *br) -+{ -+ int i; -+ struct au_wbr *wbr; -+ struct au_dykey **key; -+ -+ au_hnotify_fin_br(br); -+ /* always, regardless the mount option */ -+ au_dr_hino_free(&br->br_dirren); -+ au_xino_put(br); -+ -+ AuLCntZero(au_lcnt_read(&br->br_nfiles, /*do_rev*/0)); -+ au_lcnt_fin(&br->br_nfiles, /*do_sync*/0); -+ AuLCntZero(au_lcnt_read(&br->br_count, /*do_rev*/0)); -+ au_lcnt_fin(&br->br_count, /*do_sync*/0); -+ -+ wbr = br->br_wbr; -+ if (wbr) { -+ for (i = 0; i < AuBrWh_Last; i++) -+ dput(wbr->wbr_wh[i]); -+ AuDebugOn(atomic_read(&wbr->wbr_wh_running)); -+ AuRwDestroy(&wbr->wbr_wh_rwsem); -+ } -+ -+ if (br->br_fhsm) { -+ au_br_fhsm_fin(br->br_fhsm); -+ au_kfree_try_rcu(br->br_fhsm); -+ } -+ -+ key = br->br_dykey; -+ for (i = 0; i < AuBrDynOp; i++, key++) -+ if (*key) -+ au_dy_put(*key); -+ else -+ break; -+ -+ /* recursive lock, s_umount of branch's */ -+ /* synchronize_rcu(); */ /* why? */ -+ lockdep_off(); -+ path_put(&br->br_path); -+ lockdep_on(); -+ au_kfree_rcu(wbr); -+ au_lcnt_wait_for_fin(&br->br_nfiles); -+ au_lcnt_wait_for_fin(&br->br_count); -+ /* I don't know why, but percpu_refcount requires this */ -+ /* synchronize_rcu(); */ -+ au_kfree_rcu(br); -+} -+ -+/* -+ * frees all branches -+ */ -+void au_br_free(struct au_sbinfo *sbinfo) -+{ -+ aufs_bindex_t bmax; -+ struct au_branch **br; -+ -+ AuRwMustWriteLock(&sbinfo->si_rwsem); -+ -+ bmax = sbinfo->si_bbot + 1; -+ br = sbinfo->si_branch; -+ while (bmax--) -+ au_br_do_free(*br++); -+} -+ -+/* -+ * find the index of a branch which is specified by @br_id. -+ */ -+int au_br_index(struct super_block *sb, aufs_bindex_t br_id) -+{ -+ aufs_bindex_t bindex, bbot; -+ -+ bbot = au_sbbot(sb); -+ for (bindex = 0; bindex <= bbot; bindex++) -+ if (au_sbr_id(sb, bindex) == br_id) -+ return bindex; -+ return -1; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * add a branch -+ */ -+ -+static int test_overlap(struct super_block *sb, struct dentry *h_adding, -+ struct dentry *h_root) -+{ -+ if (unlikely(h_adding == h_root -+ || au_test_loopback_overlap(sb, h_adding))) -+ return 1; -+ if (h_adding->d_sb != h_root->d_sb) -+ return 0; -+ return au_test_subdir(h_adding, h_root) -+ || au_test_subdir(h_root, h_adding); -+} -+ -+/* -+ * returns a newly allocated branch. @new_nbranch is a number of branches -+ * after adding a branch. -+ */ -+static struct au_branch *au_br_alloc(struct super_block *sb, int new_nbranch, -+ int perm) -+{ -+ struct au_branch *add_branch; -+ struct dentry *root; -+ struct inode *inode; -+ int err; -+ -+ err = -ENOMEM; -+ add_branch = kzalloc(sizeof(*add_branch), GFP_NOFS); -+ if (unlikely(!add_branch)) -+ goto out; -+ add_branch->br_xino = au_xino_alloc(/*nfile*/1); -+ if (unlikely(!add_branch->br_xino)) -+ goto out_br; -+ err = au_hnotify_init_br(add_branch, perm); -+ if (unlikely(err)) -+ goto out_xino; -+ -+ if (au_br_writable(perm)) { -+ /* may be freed separately at changing the branch permission */ -+ add_branch->br_wbr = kzalloc(sizeof(*add_branch->br_wbr), -+ GFP_NOFS); -+ if (unlikely(!add_branch->br_wbr)) -+ goto out_hnotify; -+ } -+ -+ if (au_br_fhsm(perm)) { -+ err = au_fhsm_br_alloc(add_branch); -+ if (unlikely(err)) -+ goto out_wbr; -+ } -+ -+ root = sb->s_root; -+ err = au_sbr_realloc(au_sbi(sb), new_nbranch, /*may_shrink*/0); -+ if (!err) -+ err = au_di_realloc(au_di(root), new_nbranch, /*may_shrink*/0); -+ if (!err) { -+ inode = d_inode(root); -+ err = au_hinode_realloc(au_ii(inode), new_nbranch, -+ /*may_shrink*/0); -+ } -+ if (!err) -+ return add_branch; /* success */ -+ -+out_wbr: -+ au_kfree_rcu(add_branch->br_wbr); -+out_hnotify: -+ au_hnotify_fin_br(add_branch); -+out_xino: -+ au_xino_put(add_branch); -+out_br: -+ au_kfree_rcu(add_branch); -+out: -+ return ERR_PTR(err); -+} -+ -+/* -+ * test if the branch permission is legal or not. -+ */ -+static int test_br(struct inode *inode, int brperm, char *path) -+{ -+ int err; -+ -+ err = (au_br_writable(brperm) && IS_RDONLY(inode)); -+ if (!err) -+ goto out; -+ -+ err = -EINVAL; -+ pr_err("write permission for readonly mount or inode, %s\n", path); -+ -+out: -+ return err; -+} -+ -+/* -+ * returns: -+ * 0: success, the caller will add it -+ * plus: success, it is already unified, the caller should ignore it -+ * minus: error -+ */ -+static int test_add(struct super_block *sb, struct au_opt_add *add, int remount) -+{ -+ int err; -+ aufs_bindex_t bbot, bindex; -+ struct dentry *root, *h_dentry; -+ struct inode *inode, *h_inode; -+ -+ root = sb->s_root; -+ bbot = au_sbbot(sb); -+ if (unlikely(bbot >= 0 -+ && au_find_dbindex(root, add->path.dentry) >= 0)) { -+ err = 1; -+ if (!remount) { -+ err = -EINVAL; -+ pr_err("%s duplicated\n", add->pathname); -+ } -+ goto out; -+ } -+ -+ err = -ENOSPC; /* -E2BIG; */ -+ if (unlikely(AUFS_BRANCH_MAX <= add->bindex -+ || AUFS_BRANCH_MAX - 1 <= bbot)) { -+ pr_err("number of branches exceeded %s\n", add->pathname); -+ goto out; -+ } -+ -+ err = -EDOM; -+ if (unlikely(add->bindex < 0 || bbot + 1 < add->bindex)) { -+ pr_err("bad index %d\n", add->bindex); -+ goto out; -+ } -+ -+ inode = d_inode(add->path.dentry); -+ err = -ENOENT; -+ if (unlikely(!inode->i_nlink)) { -+ pr_err("no existence %s\n", add->pathname); -+ goto out; -+ } -+ -+ err = -EINVAL; -+ if (unlikely(inode->i_sb == sb)) { -+ pr_err("%s must be outside\n", add->pathname); -+ goto out; -+ } -+ -+ if (unlikely(au_test_fs_unsuppoted(inode->i_sb))) { -+ pr_err("unsupported filesystem, %s (%s)\n", -+ add->pathname, au_sbtype(inode->i_sb)); -+ goto out; -+ } -+ -+ if (unlikely(inode->i_sb->s_stack_depth)) { -+ pr_err("already stacked, %s (%s)\n", -+ add->pathname, au_sbtype(inode->i_sb)); -+ goto out; -+ } -+ -+ err = test_br(d_inode(add->path.dentry), add->perm, add->pathname); -+ if (unlikely(err)) -+ goto out; -+ -+ if (bbot < 0) -+ return 0; /* success */ -+ -+ err = -EINVAL; -+ for (bindex = 0; bindex <= bbot; bindex++) -+ if (unlikely(test_overlap(sb, add->path.dentry, -+ au_h_dptr(root, bindex)))) { -+ pr_err("%s is overlapped\n", add->pathname); -+ goto out; -+ } -+ -+ err = 0; -+ if (au_opt_test(au_mntflags(sb), WARN_PERM)) { -+ h_dentry = au_h_dptr(root, 0); -+ h_inode = d_inode(h_dentry); -+ if ((h_inode->i_mode & S_IALLUGO) != (inode->i_mode & S_IALLUGO) -+ || !uid_eq(h_inode->i_uid, inode->i_uid) -+ || !gid_eq(h_inode->i_gid, inode->i_gid)) -+ pr_warn("uid/gid/perm %s %u/%u/0%o, %u/%u/0%o\n", -+ add->pathname, -+ i_uid_read(inode), i_gid_read(inode), -+ (inode->i_mode & S_IALLUGO), -+ i_uid_read(h_inode), i_gid_read(h_inode), -+ (h_inode->i_mode & S_IALLUGO)); -+ } -+ -+out: -+ return err; -+} -+ -+/* -+ * initialize or clean the whiteouts for an adding branch -+ */ -+static int au_br_init_wh(struct super_block *sb, struct au_branch *br, -+ int new_perm) -+{ -+ int err, old_perm; -+ aufs_bindex_t bindex; -+ struct inode *h_inode; -+ struct au_wbr *wbr; -+ struct au_hinode *hdir; -+ struct dentry *h_dentry; -+ -+ err = vfsub_mnt_want_write(au_br_mnt(br)); -+ if (unlikely(err)) -+ goto out; -+ -+ wbr = br->br_wbr; -+ old_perm = br->br_perm; -+ br->br_perm = new_perm; -+ hdir = NULL; -+ h_inode = NULL; -+ bindex = au_br_index(sb, br->br_id); -+ if (0 <= bindex) { -+ hdir = au_hi(d_inode(sb->s_root), bindex); -+ au_hn_inode_lock_nested(hdir, AuLsc_I_PARENT); -+ } else { -+ h_dentry = au_br_dentry(br); -+ h_inode = d_inode(h_dentry); -+ inode_lock_nested(h_inode, AuLsc_I_PARENT); -+ } -+ if (!wbr) -+ err = au_wh_init(br, sb); -+ else { -+ wbr_wh_write_lock(wbr); -+ err = au_wh_init(br, sb); -+ wbr_wh_write_unlock(wbr); -+ } -+ if (hdir) -+ au_hn_inode_unlock(hdir); -+ else -+ inode_unlock(h_inode); -+ vfsub_mnt_drop_write(au_br_mnt(br)); -+ br->br_perm = old_perm; -+ -+ if (!err && wbr && !au_br_writable(new_perm)) { -+ au_kfree_rcu(wbr); -+ br->br_wbr = NULL; -+ } -+ -+out: -+ return err; -+} -+ -+static int au_wbr_init(struct au_branch *br, struct super_block *sb, -+ int perm) -+{ -+ int err; -+ struct kstatfs kst; -+ struct au_wbr *wbr; -+ -+ wbr = br->br_wbr; -+ au_rw_init(&wbr->wbr_wh_rwsem); -+ atomic_set(&wbr->wbr_wh_running, 0); -+ -+ /* -+ * a limit for rmdir/rename a dir -+ * cf. AUFS_MAX_NAMELEN in include/uapi/linux/aufs_type.h -+ */ -+ err = vfs_statfs(&br->br_path, &kst); -+ if (unlikely(err)) -+ goto out; -+ err = -EINVAL; -+ if (kst.f_namelen >= NAME_MAX) -+ err = au_br_init_wh(sb, br, perm); -+ else -+ pr_err("%pd(%s), unsupported namelen %ld\n", -+ au_br_dentry(br), -+ au_sbtype(au_br_dentry(br)->d_sb), kst.f_namelen); -+ -+out: -+ return err; -+} -+ -+/* initialize a new branch */ -+static int au_br_init(struct au_branch *br, struct super_block *sb, -+ struct au_opt_add *add) -+{ -+ int err; -+ struct au_branch *brbase; -+ struct file *xf; -+ struct inode *h_inode; -+ -+ err = 0; -+ br->br_perm = add->perm; -+ br->br_path = add->path; /* set first, path_get() later */ -+ spin_lock_init(&br->br_dykey_lock); -+ au_lcnt_init(&br->br_nfiles, /*release*/NULL); -+ au_lcnt_init(&br->br_count, /*release*/NULL); -+ br->br_id = au_new_br_id(sb); -+ AuDebugOn(br->br_id < 0); -+ -+ /* always, regardless the given option */ -+ err = au_dr_br_init(sb, br, &add->path); -+ if (unlikely(err)) -+ goto out_err; -+ -+ if (au_br_writable(add->perm)) { -+ err = au_wbr_init(br, sb, add->perm); -+ if (unlikely(err)) -+ goto out_err; -+ } -+ -+ if (au_opt_test(au_mntflags(sb), XINO)) { -+ brbase = au_sbr(sb, 0); -+ xf = au_xino_file(brbase->br_xino, /*idx*/-1); -+ AuDebugOn(!xf); -+ h_inode = d_inode(add->path.dentry); -+ err = au_xino_init_br(sb, br, h_inode->i_ino, &xf->f_path); -+ if (unlikely(err)) { -+ AuDebugOn(au_xino_file(br->br_xino, /*idx*/-1)); -+ goto out_err; -+ } -+ } -+ -+ sysaufs_br_init(br); -+ path_get(&br->br_path); -+ goto out; /* success */ -+ -+out_err: -+ memset(&br->br_path, 0, sizeof(br->br_path)); -+out: -+ return err; -+} -+ -+static void au_br_do_add_brp(struct au_sbinfo *sbinfo, aufs_bindex_t bindex, -+ struct au_branch *br, aufs_bindex_t bbot, -+ aufs_bindex_t amount) -+{ -+ struct au_branch **brp; -+ -+ AuRwMustWriteLock(&sbinfo->si_rwsem); -+ -+ brp = sbinfo->si_branch + bindex; -+ memmove(brp + 1, brp, sizeof(*brp) * amount); -+ *brp = br; -+ sbinfo->si_bbot++; -+ if (unlikely(bbot < 0)) -+ sbinfo->si_bbot = 0; -+} -+ -+static void au_br_do_add_hdp(struct au_dinfo *dinfo, aufs_bindex_t bindex, -+ aufs_bindex_t bbot, aufs_bindex_t amount) -+{ -+ struct au_hdentry *hdp; -+ -+ AuRwMustWriteLock(&dinfo->di_rwsem); -+ -+ hdp = au_hdentry(dinfo, bindex); -+ memmove(hdp + 1, hdp, sizeof(*hdp) * amount); -+ au_h_dentry_init(hdp); -+ dinfo->di_bbot++; -+ if (unlikely(bbot < 0)) -+ dinfo->di_btop = 0; -+} -+ -+static void au_br_do_add_hip(struct au_iinfo *iinfo, aufs_bindex_t bindex, -+ aufs_bindex_t bbot, aufs_bindex_t amount) -+{ -+ struct au_hinode *hip; -+ -+ AuRwMustWriteLock(&iinfo->ii_rwsem); -+ -+ hip = au_hinode(iinfo, bindex); -+ memmove(hip + 1, hip, sizeof(*hip) * amount); -+ au_hinode_init(hip); -+ iinfo->ii_bbot++; -+ if (unlikely(bbot < 0)) -+ iinfo->ii_btop = 0; -+} -+ -+static void au_br_do_add(struct super_block *sb, struct au_branch *br, -+ aufs_bindex_t bindex) -+{ -+ struct dentry *root, *h_dentry; -+ struct inode *root_inode, *h_inode; -+ aufs_bindex_t bbot, amount; -+ -+ root = sb->s_root; -+ root_inode = d_inode(root); -+ bbot = au_sbbot(sb); -+ amount = bbot + 1 - bindex; -+ h_dentry = au_br_dentry(br); -+ au_sbilist_lock(); -+ au_br_do_add_brp(au_sbi(sb), bindex, br, bbot, amount); -+ au_br_do_add_hdp(au_di(root), bindex, bbot, amount); -+ au_br_do_add_hip(au_ii(root_inode), bindex, bbot, amount); -+ au_set_h_dptr(root, bindex, dget(h_dentry)); -+ h_inode = d_inode(h_dentry); -+ au_set_h_iptr(root_inode, bindex, au_igrab(h_inode), /*flags*/0); -+ au_sbilist_unlock(); -+} -+ -+int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount) -+{ -+ int err; -+ aufs_bindex_t bbot, add_bindex; -+ struct dentry *root, *h_dentry; -+ struct inode *root_inode; -+ struct au_branch *add_branch; -+ -+ root = sb->s_root; -+ root_inode = d_inode(root); -+ IMustLock(root_inode); -+ IiMustWriteLock(root_inode); -+ err = test_add(sb, add, remount); -+ if (unlikely(err < 0)) -+ goto out; -+ if (err) { -+ err = 0; -+ goto out; /* success */ -+ } -+ -+ bbot = au_sbbot(sb); -+ add_branch = au_br_alloc(sb, bbot + 2, add->perm); -+ err = PTR_ERR(add_branch); -+ if (IS_ERR(add_branch)) -+ goto out; -+ -+ err = au_br_init(add_branch, sb, add); -+ if (unlikely(err)) { -+ au_br_do_free(add_branch); -+ goto out; -+ } -+ -+ add_bindex = add->bindex; -+ sysaufs_brs_del(sb, add_bindex); /* remove successors */ -+ au_br_do_add(sb, add_branch, add_bindex); -+ sysaufs_brs_add(sb, add_bindex); /* append successors */ -+ dbgaufs_brs_add(sb, add_bindex, /*topdown*/0); /* rename successors */ -+ -+ h_dentry = add->path.dentry; -+ if (!add_bindex) { -+ au_cpup_attr_all(root_inode, /*force*/1); -+ sb->s_maxbytes = h_dentry->d_sb->s_maxbytes; -+ } else -+ au_add_nlink(root_inode, d_inode(h_dentry)); -+ -+out: -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static unsigned long long au_farray_cb(struct super_block *sb, void *a, -+ unsigned long long max __maybe_unused, -+ void *arg) -+{ -+ unsigned long long n; -+ struct file **p, *f; -+ struct hlist_bl_head *files; -+ struct hlist_bl_node *pos; -+ struct au_finfo *finfo; -+ -+ n = 0; -+ p = a; -+ files = &au_sbi(sb)->si_files; -+ hlist_bl_lock(files); -+ hlist_bl_for_each_entry(finfo, pos, files, fi_hlist) { -+ f = finfo->fi_file; -+ if (file_count(f) -+ && !special_file(file_inode(f)->i_mode)) { -+ get_file(f); -+ *p++ = f; -+ n++; -+ AuDebugOn(n > max); -+ } -+ } -+ hlist_bl_unlock(files); -+ -+ return n; -+} -+ -+static struct file **au_farray_alloc(struct super_block *sb, -+ unsigned long long *max) -+{ -+ struct au_sbinfo *sbi; -+ -+ sbi = au_sbi(sb); -+ *max = au_lcnt_read(&sbi->si_nfiles, /*do_rev*/1); -+ return au_array_alloc(max, au_farray_cb, sb, /*arg*/NULL); -+} -+ -+static void au_farray_free(struct file **a, unsigned long long max) -+{ -+ unsigned long long ull; -+ -+ for (ull = 0; ull < max; ull++) -+ if (a[ull]) -+ fput(a[ull]); -+ kvfree(a); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * delete a branch -+ */ -+ -+/* to show the line number, do not make it inlined function */ -+#define AuVerbose(do_info, fmt, ...) do { \ -+ if (do_info) \ -+ pr_info(fmt, ##__VA_ARGS__); \ -+} while (0) -+ -+static int au_test_ibusy(struct inode *inode, aufs_bindex_t btop, -+ aufs_bindex_t bbot) -+{ -+ return (inode && !S_ISDIR(inode->i_mode)) || btop == bbot; -+} -+ -+static int au_test_dbusy(struct dentry *dentry, aufs_bindex_t btop, -+ aufs_bindex_t bbot) -+{ -+ return au_test_ibusy(d_inode(dentry), btop, bbot); -+} -+ -+/* -+ * test if the branch is deletable or not. -+ */ -+static int test_dentry_busy(struct dentry *root, aufs_bindex_t bindex, -+ unsigned int sigen, const unsigned int verbose) -+{ -+ int err, i, j, ndentry; -+ aufs_bindex_t btop, bbot; -+ struct au_dcsub_pages dpages; -+ struct au_dpage *dpage; -+ struct dentry *d; -+ -+ err = au_dpages_init(&dpages, GFP_NOFS); -+ if (unlikely(err)) -+ goto out; -+ err = au_dcsub_pages(&dpages, root, NULL, NULL); -+ if (unlikely(err)) -+ goto out_dpages; -+ -+ for (i = 0; !err && i < dpages.ndpage; i++) { -+ dpage = dpages.dpages + i; -+ ndentry = dpage->ndentry; -+ for (j = 0; !err && j < ndentry; j++) { -+ d = dpage->dentries[j]; -+ AuDebugOn(au_dcount(d) <= 0); -+ if (!au_digen_test(d, sigen)) { -+ di_read_lock_child(d, AuLock_IR); -+ if (unlikely(au_dbrange_test(d))) { -+ di_read_unlock(d, AuLock_IR); -+ continue; -+ } -+ } else { -+ di_write_lock_child(d); -+ if (unlikely(au_dbrange_test(d))) { -+ di_write_unlock(d); -+ continue; -+ } -+ err = au_reval_dpath(d, sigen); -+ if (!err) -+ di_downgrade_lock(d, AuLock_IR); -+ else { -+ di_write_unlock(d); -+ break; -+ } -+ } -+ -+ /* AuDbgDentry(d); */ -+ btop = au_dbtop(d); -+ bbot = au_dbbot(d); -+ if (btop <= bindex -+ && bindex <= bbot -+ && au_h_dptr(d, bindex) -+ && au_test_dbusy(d, btop, bbot)) { -+ err = -EBUSY; -+ AuVerbose(verbose, "busy %pd\n", d); -+ AuDbgDentry(d); -+ } -+ di_read_unlock(d, AuLock_IR); -+ } -+ } -+ -+out_dpages: -+ au_dpages_free(&dpages); -+out: -+ return err; -+} -+ -+static int test_inode_busy(struct super_block *sb, aufs_bindex_t bindex, -+ unsigned int sigen, const unsigned int verbose) -+{ -+ int err; -+ unsigned long long max, ull; -+ struct inode *i, **array; -+ aufs_bindex_t btop, bbot; -+ -+ array = au_iarray_alloc(sb, &max); -+ err = PTR_ERR(array); -+ if (IS_ERR(array)) -+ goto out; -+ -+ err = 0; -+ AuDbg("b%d\n", bindex); -+ for (ull = 0; !err && ull < max; ull++) { -+ i = array[ull]; -+ if (unlikely(!i)) -+ break; -+ if (i->i_ino == AUFS_ROOT_INO) -+ continue; -+ -+ /* AuDbgInode(i); */ -+ if (au_iigen(i, NULL) == sigen) -+ ii_read_lock_child(i); -+ else { -+ ii_write_lock_child(i); -+ err = au_refresh_hinode_self(i); -+ au_iigen_dec(i); -+ if (!err) -+ ii_downgrade_lock(i); -+ else { -+ ii_write_unlock(i); -+ break; -+ } -+ } -+ -+ btop = au_ibtop(i); -+ bbot = au_ibbot(i); -+ if (btop <= bindex -+ && bindex <= bbot -+ && au_h_iptr(i, bindex) -+ && au_test_ibusy(i, btop, bbot)) { -+ err = -EBUSY; -+ AuVerbose(verbose, "busy i%lu\n", i->i_ino); -+ AuDbgInode(i); -+ } -+ ii_read_unlock(i); -+ } -+ au_iarray_free(array, max); -+ -+out: -+ return err; -+} -+ -+static int test_children_busy(struct dentry *root, aufs_bindex_t bindex, -+ const unsigned int verbose) -+{ -+ int err; -+ unsigned int sigen; -+ -+ sigen = au_sigen(root->d_sb); -+ DiMustNoWaiters(root); -+ IiMustNoWaiters(d_inode(root)); -+ di_write_unlock(root); -+ err = test_dentry_busy(root, bindex, sigen, verbose); -+ if (!err) -+ err = test_inode_busy(root->d_sb, bindex, sigen, verbose); -+ di_write_lock_child(root); /* aufs_write_lock() calls ..._child() */ -+ -+ return err; -+} -+ -+static int test_dir_busy(struct file *file, aufs_bindex_t br_id, -+ struct file **to_free, int *idx) -+{ -+ int err; -+ unsigned char matched, root; -+ aufs_bindex_t bindex, bbot; -+ struct au_fidir *fidir; -+ struct au_hfile *hfile; -+ -+ err = 0; -+ root = IS_ROOT(file->f_path.dentry); -+ if (root) { -+ get_file(file); -+ to_free[*idx] = file; -+ (*idx)++; -+ goto out; -+ } -+ -+ matched = 0; -+ fidir = au_fi(file)->fi_hdir; -+ AuDebugOn(!fidir); -+ bbot = au_fbbot_dir(file); -+ for (bindex = au_fbtop(file); bindex <= bbot; bindex++) { -+ hfile = fidir->fd_hfile + bindex; -+ if (!hfile->hf_file) -+ continue; -+ -+ if (hfile->hf_br->br_id == br_id) { -+ matched = 1; -+ break; -+ } -+ } -+ if (matched) -+ err = -EBUSY; -+ -+out: -+ return err; -+} -+ -+static int test_file_busy(struct super_block *sb, aufs_bindex_t br_id, -+ struct file **to_free, int opened) -+{ -+ int err, idx; -+ unsigned long long ull, max; -+ aufs_bindex_t btop; -+ struct file *file, **array; -+ struct dentry *root; -+ struct au_hfile *hfile; -+ -+ array = au_farray_alloc(sb, &max); -+ err = PTR_ERR(array); -+ if (IS_ERR(array)) -+ goto out; -+ -+ err = 0; -+ idx = 0; -+ root = sb->s_root; -+ di_write_unlock(root); -+ for (ull = 0; ull < max; ull++) { -+ file = array[ull]; -+ if (unlikely(!file)) -+ break; -+ -+ /* AuDbg("%pD\n", file); */ -+ fi_read_lock(file); -+ btop = au_fbtop(file); -+ if (!d_is_dir(file->f_path.dentry)) { -+ hfile = &au_fi(file)->fi_htop; -+ if (hfile->hf_br->br_id == br_id) -+ err = -EBUSY; -+ } else -+ err = test_dir_busy(file, br_id, to_free, &idx); -+ fi_read_unlock(file); -+ if (unlikely(err)) -+ break; -+ } -+ di_write_lock_child(root); -+ au_farray_free(array, max); -+ AuDebugOn(idx > opened); -+ -+out: -+ return err; -+} -+ -+static void br_del_file(struct file **to_free, unsigned long long opened, -+ aufs_bindex_t br_id) -+{ -+ unsigned long long ull; -+ aufs_bindex_t bindex, btop, bbot, bfound; -+ struct file *file; -+ struct au_fidir *fidir; -+ struct au_hfile *hfile; -+ -+ for (ull = 0; ull < opened; ull++) { -+ file = to_free[ull]; -+ if (unlikely(!file)) -+ break; -+ -+ /* AuDbg("%pD\n", file); */ -+ AuDebugOn(!d_is_dir(file->f_path.dentry)); -+ bfound = -1; -+ fidir = au_fi(file)->fi_hdir; -+ AuDebugOn(!fidir); -+ fi_write_lock(file); -+ btop = au_fbtop(file); -+ bbot = au_fbbot_dir(file); -+ for (bindex = btop; bindex <= bbot; bindex++) { -+ hfile = fidir->fd_hfile + bindex; -+ if (!hfile->hf_file) -+ continue; -+ -+ if (hfile->hf_br->br_id == br_id) { -+ bfound = bindex; -+ break; -+ } -+ } -+ AuDebugOn(bfound < 0); -+ au_set_h_fptr(file, bfound, NULL); -+ if (bfound == btop) { -+ for (btop++; btop <= bbot; btop++) -+ if (au_hf_dir(file, btop)) { -+ au_set_fbtop(file, btop); -+ break; -+ } -+ } -+ fi_write_unlock(file); -+ } -+} -+ -+static void au_br_do_del_brp(struct au_sbinfo *sbinfo, -+ const aufs_bindex_t bindex, -+ const aufs_bindex_t bbot) -+{ -+ struct au_branch **brp, **p; -+ -+ AuRwMustWriteLock(&sbinfo->si_rwsem); -+ -+ brp = sbinfo->si_branch + bindex; -+ if (bindex < bbot) -+ memmove(brp, brp + 1, sizeof(*brp) * (bbot - bindex)); -+ sbinfo->si_branch[0 + bbot] = NULL; -+ sbinfo->si_bbot--; -+ -+ p = au_krealloc(sbinfo->si_branch, sizeof(*p) * bbot, AuGFP_SBILIST, -+ /*may_shrink*/1); -+ if (p) -+ sbinfo->si_branch = p; -+ /* harmless error */ -+} -+ -+static void au_br_do_del_hdp(struct au_dinfo *dinfo, const aufs_bindex_t bindex, -+ const aufs_bindex_t bbot) -+{ -+ struct au_hdentry *hdp, *p; -+ -+ AuRwMustWriteLock(&dinfo->di_rwsem); -+ -+ hdp = au_hdentry(dinfo, bindex); -+ if (bindex < bbot) -+ memmove(hdp, hdp + 1, sizeof(*hdp) * (bbot - bindex)); -+ /* au_h_dentry_init(au_hdentry(dinfo, bbot); */ -+ dinfo->di_bbot--; -+ -+ p = au_krealloc(dinfo->di_hdentry, sizeof(*p) * bbot, AuGFP_SBILIST, -+ /*may_shrink*/1); -+ if (p) -+ dinfo->di_hdentry = p; -+ /* harmless error */ -+} -+ -+static void au_br_do_del_hip(struct au_iinfo *iinfo, const aufs_bindex_t bindex, -+ const aufs_bindex_t bbot) -+{ -+ struct au_hinode *hip, *p; -+ -+ AuRwMustWriteLock(&iinfo->ii_rwsem); -+ -+ hip = au_hinode(iinfo, bindex); -+ if (bindex < bbot) -+ memmove(hip, hip + 1, sizeof(*hip) * (bbot - bindex)); -+ /* au_hinode_init(au_hinode(iinfo, bbot)); */ -+ iinfo->ii_bbot--; -+ -+ p = au_krealloc(iinfo->ii_hinode, sizeof(*p) * bbot, AuGFP_SBILIST, -+ /*may_shrink*/1); -+ if (p) -+ iinfo->ii_hinode = p; -+ /* harmless error */ -+} -+ -+static void au_br_do_del(struct super_block *sb, aufs_bindex_t bindex, -+ struct au_branch *br) -+{ -+ aufs_bindex_t bbot; -+ struct au_sbinfo *sbinfo; -+ struct dentry *root, *h_root; -+ struct inode *inode, *h_inode; -+ struct au_hinode *hinode; -+ -+ SiMustWriteLock(sb); -+ -+ root = sb->s_root; -+ inode = d_inode(root); -+ sbinfo = au_sbi(sb); -+ bbot = sbinfo->si_bbot; -+ -+ h_root = au_h_dptr(root, bindex); -+ hinode = au_hi(inode, bindex); -+ h_inode = au_igrab(hinode->hi_inode); -+ au_hiput(hinode); -+ -+ au_sbilist_lock(); -+ au_br_do_del_brp(sbinfo, bindex, bbot); -+ au_br_do_del_hdp(au_di(root), bindex, bbot); -+ au_br_do_del_hip(au_ii(inode), bindex, bbot); -+ au_sbilist_unlock(); -+ -+ /* ignore an error */ -+ au_dr_br_fin(sb, br); /* always, regardless the mount option */ -+ -+ dput(h_root); -+ iput(h_inode); -+ au_br_do_free(br); -+} -+ -+static unsigned long long empty_cb(struct super_block *sb, void *array, -+ unsigned long long max, void *arg) -+{ -+ return max; -+} -+ -+int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount) -+{ -+ int err, rerr, i; -+ unsigned long long opened; -+ unsigned int mnt_flags; -+ aufs_bindex_t bindex, bbot, br_id; -+ unsigned char do_wh, verbose; -+ struct au_branch *br; -+ struct au_wbr *wbr; -+ struct dentry *root; -+ struct file **to_free; -+ -+ err = 0; -+ opened = 0; -+ to_free = NULL; -+ root = sb->s_root; -+ bindex = au_find_dbindex(root, del->h_path.dentry); -+ if (bindex < 0) { -+ if (remount) -+ goto out; /* success */ -+ err = -ENOENT; -+ pr_err("%s no such branch\n", del->pathname); -+ goto out; -+ } -+ AuDbg("bindex b%d\n", bindex); -+ -+ err = -EBUSY; -+ mnt_flags = au_mntflags(sb); -+ verbose = !!au_opt_test(mnt_flags, VERBOSE); -+ bbot = au_sbbot(sb); -+ if (unlikely(!bbot)) { -+ AuVerbose(verbose, "no more branches left\n"); -+ goto out; -+ } -+ -+ br = au_sbr(sb, bindex); -+ AuDebugOn(!path_equal(&br->br_path, &del->h_path)); -+ if (unlikely(au_lcnt_read(&br->br_count, /*do_rev*/1))) { -+ AuVerbose(verbose, "br %pd2 is busy now\n", del->h_path.dentry); -+ goto out; -+ } -+ -+ br_id = br->br_id; -+ opened = au_lcnt_read(&br->br_nfiles, /*do_rev*/1); -+ if (unlikely(opened)) { -+ to_free = au_array_alloc(&opened, empty_cb, sb, NULL); -+ err = PTR_ERR(to_free); -+ if (IS_ERR(to_free)) -+ goto out; -+ -+ err = test_file_busy(sb, br_id, to_free, opened); -+ if (unlikely(err)) { -+ AuVerbose(verbose, "%llu file(s) opened\n", opened); -+ goto out; -+ } -+ } -+ -+ wbr = br->br_wbr; -+ do_wh = wbr && (wbr->wbr_whbase || wbr->wbr_plink || wbr->wbr_orph); -+ if (do_wh) { -+ /* instead of WbrWhMustWriteLock(wbr) */ -+ SiMustWriteLock(sb); -+ for (i = 0; i < AuBrWh_Last; i++) { -+ dput(wbr->wbr_wh[i]); -+ wbr->wbr_wh[i] = NULL; -+ } -+ } -+ -+ err = test_children_busy(root, bindex, verbose); -+ if (unlikely(err)) { -+ if (do_wh) -+ goto out_wh; -+ goto out; -+ } -+ -+ err = 0; -+ if (to_free) { -+ /* -+ * now we confirmed the branch is deletable. -+ * let's free the remaining opened dirs on the branch. -+ */ -+ di_write_unlock(root); -+ br_del_file(to_free, opened, br_id); -+ di_write_lock_child(root); -+ } -+ -+ sysaufs_brs_del(sb, bindex); /* remove successors */ -+ dbgaufs_xino_del(br); /* remove one */ -+ au_br_do_del(sb, bindex, br); -+ sysaufs_brs_add(sb, bindex); /* append successors */ -+ dbgaufs_brs_add(sb, bindex, /*topdown*/1); /* rename successors */ -+ -+ if (!bindex) { -+ au_cpup_attr_all(d_inode(root), /*force*/1); -+ sb->s_maxbytes = au_sbr_sb(sb, 0)->s_maxbytes; -+ } else -+ au_sub_nlink(d_inode(root), d_inode(del->h_path.dentry)); -+ if (au_opt_test(mnt_flags, PLINK)) -+ au_plink_half_refresh(sb, br_id); -+ -+ goto out; /* success */ -+ -+out_wh: -+ /* revert */ -+ rerr = au_br_init_wh(sb, br, br->br_perm); -+ if (rerr) -+ pr_warn("failed re-creating base whiteout, %s. (%d)\n", -+ del->pathname, rerr); -+out: -+ if (to_free) -+ au_farray_free(to_free, opened); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int au_ibusy(struct super_block *sb, struct aufs_ibusy __user *arg) -+{ -+ int err; -+ aufs_bindex_t btop, bbot; -+ struct aufs_ibusy ibusy; -+ struct inode *inode, *h_inode; -+ -+ err = -EPERM; -+ if (unlikely(!capable(CAP_SYS_ADMIN))) -+ goto out; -+ -+ err = copy_from_user(&ibusy, arg, sizeof(ibusy)); -+ if (!err) -+ /* VERIFY_WRITE */ -+ err = !access_ok(&arg->h_ino, sizeof(arg->h_ino)); -+ if (unlikely(err)) { -+ err = -EFAULT; -+ AuTraceErr(err); -+ goto out; -+ } -+ -+ err = -EINVAL; -+ si_read_lock(sb, AuLock_FLUSH); -+ if (unlikely(ibusy.bindex < 0 || ibusy.bindex > au_sbbot(sb))) -+ goto out_unlock; -+ -+ err = 0; -+ ibusy.h_ino = 0; /* invalid */ -+ inode = ilookup(sb, ibusy.ino); -+ if (!inode -+ || inode->i_ino == AUFS_ROOT_INO -+ || au_is_bad_inode(inode)) -+ goto out_unlock; -+ -+ ii_read_lock_child(inode); -+ btop = au_ibtop(inode); -+ bbot = au_ibbot(inode); -+ if (btop <= ibusy.bindex && ibusy.bindex <= bbot) { -+ h_inode = au_h_iptr(inode, ibusy.bindex); -+ if (h_inode && au_test_ibusy(inode, btop, bbot)) -+ ibusy.h_ino = h_inode->i_ino; -+ } -+ ii_read_unlock(inode); -+ iput(inode); -+ -+out_unlock: -+ si_read_unlock(sb); -+ if (!err) { -+ err = __put_user(ibusy.h_ino, &arg->h_ino); -+ if (unlikely(err)) { -+ err = -EFAULT; -+ AuTraceErr(err); -+ } -+ } -+out: -+ return err; -+} -+ -+long au_ibusy_ioctl(struct file *file, unsigned long arg) -+{ -+ return au_ibusy(file->f_path.dentry->d_sb, (void __user *)arg); -+} -+ -+#ifdef CONFIG_COMPAT -+long au_ibusy_compat_ioctl(struct file *file, unsigned long arg) -+{ -+ return au_ibusy(file->f_path.dentry->d_sb, compat_ptr(arg)); -+} -+#endif -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * change a branch permission -+ */ -+ -+static void au_warn_ima(void) -+{ -+#ifdef CONFIG_IMA -+ /* since it doesn't support mark_files_ro() */ -+ AuWarn1("RW -> RO makes IMA to produce wrong message\n"); -+#endif -+} -+ -+static int do_need_sigen_inc(int a, int b) -+{ -+ return au_br_whable(a) && !au_br_whable(b); -+} -+ -+static int need_sigen_inc(int old, int new) -+{ -+ return do_need_sigen_inc(old, new) -+ || do_need_sigen_inc(new, old); -+} -+ -+static int au_br_mod_files_ro(struct super_block *sb, aufs_bindex_t bindex) -+{ -+ int err, do_warn; -+ unsigned int mnt_flags; -+ unsigned long long ull, max; -+ aufs_bindex_t br_id; -+ unsigned char verbose, writer; -+ struct file *file, *hf, **array; -+ struct au_hfile *hfile; -+ struct inode *h_inode; -+ -+ mnt_flags = au_mntflags(sb); -+ verbose = !!au_opt_test(mnt_flags, VERBOSE); -+ -+ array = au_farray_alloc(sb, &max); -+ err = PTR_ERR(array); -+ if (IS_ERR(array)) -+ goto out; -+ -+ do_warn = 0; -+ br_id = au_sbr_id(sb, bindex); -+ for (ull = 0; ull < max; ull++) { -+ file = array[ull]; -+ if (unlikely(!file)) -+ break; -+ -+ /* AuDbg("%pD\n", file); */ -+ fi_read_lock(file); -+ if (unlikely(au_test_mmapped(file))) { -+ err = -EBUSY; -+ AuVerbose(verbose, "mmapped %pD\n", file); -+ AuDbgFile(file); -+ FiMustNoWaiters(file); -+ fi_read_unlock(file); -+ goto out_array; -+ } -+ -+ hfile = &au_fi(file)->fi_htop; -+ hf = hfile->hf_file; -+ if (!d_is_reg(file->f_path.dentry) -+ || !(file->f_mode & FMODE_WRITE) -+ || hfile->hf_br->br_id != br_id -+ || !(hf->f_mode & FMODE_WRITE)) -+ array[ull] = NULL; -+ else { -+ do_warn = 1; -+ get_file(file); -+ } -+ -+ FiMustNoWaiters(file); -+ fi_read_unlock(file); -+ fput(file); -+ } -+ -+ err = 0; -+ if (do_warn) -+ au_warn_ima(); -+ -+ for (ull = 0; ull < max; ull++) { -+ file = array[ull]; -+ if (!file) -+ continue; -+ -+ /* todo: already flushed? */ -+ /* -+ * fs/super.c:mark_files_ro() is gone, but aufs keeps its -+ * approach which resets f_mode and calls mnt_drop_write() and -+ * file_release_write() for each file, because the branch -+ * attribute in aufs world is totally different from the native -+ * fs rw/ro mode. -+ */ -+ /* fi_read_lock(file); */ -+ hfile = &au_fi(file)->fi_htop; -+ hf = hfile->hf_file; -+ /* fi_read_unlock(file); */ -+ spin_lock(&hf->f_lock); -+ writer = !!(hf->f_mode & FMODE_WRITER); -+ hf->f_mode &= ~(FMODE_WRITE | FMODE_WRITER); -+ spin_unlock(&hf->f_lock); -+ if (writer) { -+ h_inode = file_inode(hf); -+ if (hf->f_mode & FMODE_READ) -+ i_readcount_inc(h_inode); -+ put_write_access(h_inode); -+ __mnt_drop_write(hf->f_path.mnt); -+ } -+ } -+ -+out_array: -+ au_farray_free(array, max); -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount, -+ int *do_refresh) -+{ -+ int err, rerr; -+ aufs_bindex_t bindex; -+ struct dentry *root; -+ struct au_branch *br; -+ struct au_br_fhsm *bf; -+ -+ root = sb->s_root; -+ bindex = au_find_dbindex(root, mod->h_root); -+ if (bindex < 0) { -+ if (remount) -+ return 0; /* success */ -+ err = -ENOENT; -+ pr_err("%s no such branch\n", mod->path); -+ goto out; -+ } -+ AuDbg("bindex b%d\n", bindex); -+ -+ err = test_br(d_inode(mod->h_root), mod->perm, mod->path); -+ if (unlikely(err)) -+ goto out; -+ -+ br = au_sbr(sb, bindex); -+ AuDebugOn(mod->h_root != au_br_dentry(br)); -+ if (br->br_perm == mod->perm) -+ return 0; /* success */ -+ -+ /* pre-allocate for non-fhsm --> fhsm */ -+ bf = NULL; -+ if (!au_br_fhsm(br->br_perm) && au_br_fhsm(mod->perm)) { -+ err = au_fhsm_br_alloc(br); -+ if (unlikely(err)) -+ goto out; -+ bf = br->br_fhsm; -+ br->br_fhsm = NULL; -+ } -+ -+ if (au_br_writable(br->br_perm)) { -+ /* remove whiteout base */ -+ err = au_br_init_wh(sb, br, mod->perm); -+ if (unlikely(err)) -+ goto out_bf; -+ -+ if (!au_br_writable(mod->perm)) { -+ /* rw --> ro, file might be mmapped */ -+ DiMustNoWaiters(root); -+ IiMustNoWaiters(d_inode(root)); -+ di_write_unlock(root); -+ err = au_br_mod_files_ro(sb, bindex); -+ /* aufs_write_lock() calls ..._child() */ -+ di_write_lock_child(root); -+ -+ if (unlikely(err)) { -+ rerr = -ENOMEM; -+ br->br_wbr = kzalloc(sizeof(*br->br_wbr), -+ GFP_NOFS); -+ if (br->br_wbr) -+ rerr = au_wbr_init(br, sb, br->br_perm); -+ if (unlikely(rerr)) { -+ AuIOErr("nested error %d (%d)\n", -+ rerr, err); -+ br->br_perm = mod->perm; -+ } -+ } -+ } -+ } else if (au_br_writable(mod->perm)) { -+ /* ro --> rw */ -+ err = -ENOMEM; -+ br->br_wbr = kzalloc(sizeof(*br->br_wbr), GFP_NOFS); -+ if (br->br_wbr) { -+ err = au_wbr_init(br, sb, mod->perm); -+ if (unlikely(err)) { -+ au_kfree_rcu(br->br_wbr); -+ br->br_wbr = NULL; -+ } -+ } -+ } -+ if (unlikely(err)) -+ goto out_bf; -+ -+ if (au_br_fhsm(br->br_perm)) { -+ if (!au_br_fhsm(mod->perm)) { -+ /* fhsm --> non-fhsm */ -+ au_br_fhsm_fin(br->br_fhsm); -+ au_kfree_rcu(br->br_fhsm); -+ br->br_fhsm = NULL; -+ } -+ } else if (au_br_fhsm(mod->perm)) -+ /* non-fhsm --> fhsm */ -+ br->br_fhsm = bf; -+ -+ *do_refresh |= need_sigen_inc(br->br_perm, mod->perm); -+ br->br_perm = mod->perm; -+ goto out; /* success */ -+ -+out_bf: -+ au_kfree_try_rcu(bf); -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+int au_br_stfs(struct au_branch *br, struct aufs_stfs *stfs) -+{ -+ int err; -+ struct kstatfs kstfs; -+ -+ err = vfs_statfs(&br->br_path, &kstfs); -+ if (!err) { -+ stfs->f_blocks = kstfs.f_blocks; -+ stfs->f_bavail = kstfs.f_bavail; -+ stfs->f_files = kstfs.f_files; -+ stfs->f_ffree = kstfs.f_ffree; -+ } -+ -+ return err; -+} -diff --git a/fs/aufs/branch.h b/fs/aufs/branch.h -new file mode 100644 -index 000000000000..0bac9a6c9557 ---- /dev/null -+++ b/fs/aufs/branch.h -@@ -0,0 +1,353 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * branch filesystems and xino for them -+ */ -+ -+#ifndef __AUFS_BRANCH_H__ -+#define __AUFS_BRANCH_H__ -+ -+#ifdef __KERNEL__ -+ -+#include -+#include "dirren.h" -+#include "dynop.h" -+#include "lcnt.h" -+#include "rwsem.h" -+#include "super.h" -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* a xino file */ -+struct au_xino { -+ struct file **xi_file; -+ unsigned int xi_nfile; -+ -+ struct { -+ spinlock_t spin; -+ ino_t *array; -+ int total; -+ /* reserved for future use */ -+ /* unsigned long *bitmap; */ -+ wait_queue_head_t wqh; -+ } xi_nondir; -+ -+ struct mutex xi_mtx; /* protects xi_file array */ -+ struct hlist_bl_head xi_writing; -+ -+ atomic_t xi_truncating; -+ -+ struct kref xi_kref; -+}; -+ -+/* File-based Hierarchical Storage Management */ -+struct au_br_fhsm { -+#ifdef CONFIG_AUFS_FHSM -+ struct mutex bf_lock; -+ unsigned long bf_jiffy; -+ struct aufs_stfs bf_stfs; -+ int bf_readable; -+#endif -+}; -+ -+/* members for writable branch only */ -+enum {AuBrWh_BASE, AuBrWh_PLINK, AuBrWh_ORPH, AuBrWh_Last}; -+struct au_wbr { -+ struct au_rwsem wbr_wh_rwsem; -+ struct dentry *wbr_wh[AuBrWh_Last]; -+ atomic_t wbr_wh_running; -+#define wbr_whbase wbr_wh[AuBrWh_BASE] /* whiteout base */ -+#define wbr_plink wbr_wh[AuBrWh_PLINK] /* pseudo-link dir */ -+#define wbr_orph wbr_wh[AuBrWh_ORPH] /* dir for orphans */ -+ -+ /* mfs mode */ -+ unsigned long long wbr_bytes; -+}; -+ -+/* ext2 has 3 types of operations at least, ext3 has 4 */ -+#define AuBrDynOp (AuDyLast * 4) -+ -+#ifdef CONFIG_AUFS_HFSNOTIFY -+/* support for asynchronous destruction */ -+struct au_br_hfsnotify { -+ struct fsnotify_group *hfsn_group; -+}; -+#endif -+ -+/* sysfs entries */ -+struct au_brsysfs { -+ char name[16]; -+ struct attribute attr; -+}; -+ -+enum { -+ AuBrSysfs_BR, -+ AuBrSysfs_BRID, -+ AuBrSysfs_Last -+}; -+ -+/* protected by superblock rwsem */ -+struct au_branch { -+ struct au_xino *br_xino; -+ -+ aufs_bindex_t br_id; -+ -+ int br_perm; -+ struct path br_path; -+ spinlock_t br_dykey_lock; -+ struct au_dykey *br_dykey[AuBrDynOp]; -+ au_lcnt_t br_nfiles; /* opened files */ -+ au_lcnt_t br_count; /* in-use for other */ -+ -+ struct au_wbr *br_wbr; -+ struct au_br_fhsm *br_fhsm; -+ -+#ifdef CONFIG_AUFS_HFSNOTIFY -+ struct au_br_hfsnotify *br_hfsn; -+#endif -+ -+#ifdef CONFIG_SYSFS -+ /* entries under sysfs per mount-point */ -+ struct au_brsysfs br_sysfs[AuBrSysfs_Last]; -+#endif -+ -+#ifdef CONFIG_DEBUG_FS -+ struct dentry *br_dbgaufs; /* xino */ -+#endif -+ -+ struct au_dr_br br_dirren; -+}; -+ -+/* ---------------------------------------------------------------------- */ -+ -+static inline struct vfsmount *au_br_mnt(struct au_branch *br) -+{ -+ return br->br_path.mnt; -+} -+ -+static inline struct dentry *au_br_dentry(struct au_branch *br) -+{ -+ return br->br_path.dentry; -+} -+ -+static inline struct super_block *au_br_sb(struct au_branch *br) -+{ -+ return au_br_mnt(br)->mnt_sb; -+} -+ -+static inline int au_br_rdonly(struct au_branch *br) -+{ -+ return (sb_rdonly(au_br_sb(br)) -+ || !au_br_writable(br->br_perm)) -+ ? -EROFS : 0; -+} -+ -+static inline int au_br_hnotifyable(int brperm __maybe_unused) -+{ -+#ifdef CONFIG_AUFS_HNOTIFY -+ return !(brperm & AuBrPerm_RR); -+#else -+ return 0; -+#endif -+} -+ -+static inline int au_br_test_oflag(int oflag, struct au_branch *br) -+{ -+ int err, exec_flag; -+ -+ err = 0; -+ exec_flag = oflag & __FMODE_EXEC; -+ if (unlikely(exec_flag && path_noexec(&br->br_path))) -+ err = -EACCES; -+ -+ return err; -+} -+ -+static inline void au_xino_get(struct au_branch *br) -+{ -+ struct au_xino *xi; -+ -+ xi = br->br_xino; -+ if (xi) -+ kref_get(&xi->xi_kref); -+} -+ -+static inline int au_xino_count(struct au_branch *br) -+{ -+ int v; -+ struct au_xino *xi; -+ -+ v = 0; -+ xi = br->br_xino; -+ if (xi) -+ v = kref_read(&xi->xi_kref); -+ -+ return v; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* branch.c */ -+struct au_sbinfo; -+void au_br_free(struct au_sbinfo *sinfo); -+int au_br_index(struct super_block *sb, aufs_bindex_t br_id); -+struct au_opt_add; -+int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount); -+struct au_opt_del; -+int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount); -+long au_ibusy_ioctl(struct file *file, unsigned long arg); -+#ifdef CONFIG_COMPAT -+long au_ibusy_compat_ioctl(struct file *file, unsigned long arg); -+#endif -+struct au_opt_mod; -+int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount, -+ int *do_refresh); -+struct aufs_stfs; -+int au_br_stfs(struct au_branch *br, struct aufs_stfs *stfs); -+ -+/* xino.c */ -+static const loff_t au_loff_max = LLONG_MAX; -+ -+aufs_bindex_t au_xi_root(struct super_block *sb, struct dentry *dentry); -+struct file *au_xino_create(struct super_block *sb, char *fpath, int silent, -+ int wbrtop); -+struct file *au_xino_create2(struct super_block *sb, struct path *base, -+ struct file *copy_src); -+struct au_xi_new { -+ struct au_xino *xi; /* switch between xino and xigen */ -+ int idx; -+ struct path *base; -+ struct file *copy_src; -+}; -+struct file *au_xi_new(struct super_block *sb, struct au_xi_new *xinew); -+ -+int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, -+ ino_t *ino); -+int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, -+ ino_t ino); -+ssize_t xino_fread(vfs_readf_t func, struct file *file, void *buf, size_t size, -+ loff_t *pos); -+ssize_t xino_fwrite(vfs_writef_t func, struct file *file, void *buf, -+ size_t size, loff_t *pos); -+ -+int au_xib_trunc(struct super_block *sb); -+int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex, int idx_begin); -+ -+struct au_xino *au_xino_alloc(unsigned int nfile); -+int au_xino_put(struct au_branch *br); -+struct file *au_xino_file1(struct au_xino *xi); -+ -+struct au_opt_xino; -+void au_xino_clr(struct super_block *sb); -+int au_xino_set(struct super_block *sb, struct au_opt_xino *xiopt, int remount); -+struct file *au_xino_def(struct super_block *sb); -+int au_xino_init_br(struct super_block *sb, struct au_branch *br, ino_t hino, -+ struct path *base); -+ -+ino_t au_xino_new_ino(struct super_block *sb); -+void au_xino_delete_inode(struct inode *inode, const int unlinked); -+ -+void au_xinondir_leave(struct super_block *sb, aufs_bindex_t bindex, -+ ino_t h_ino, int idx); -+int au_xinondir_enter(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, -+ int *idx); -+ -+int au_xino_path(struct seq_file *seq, struct file *file); -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* @idx is signed to accept -1 meaning the first file */ -+static inline struct file *au_xino_file(struct au_xino *xi, int idx) -+{ -+ struct file *file; -+ -+ file = NULL; -+ if (!xi) -+ goto out; -+ -+ if (idx >= 0) { -+ if (idx < xi->xi_nfile) -+ file = xi->xi_file[idx]; -+ } else -+ file = au_xino_file1(xi); -+ -+out: -+ return file; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* Superblock to branch */ -+static inline -+aufs_bindex_t au_sbr_id(struct super_block *sb, aufs_bindex_t bindex) -+{ -+ return au_sbr(sb, bindex)->br_id; -+} -+ -+static inline -+struct vfsmount *au_sbr_mnt(struct super_block *sb, aufs_bindex_t bindex) -+{ -+ return au_br_mnt(au_sbr(sb, bindex)); -+} -+ -+static inline -+struct super_block *au_sbr_sb(struct super_block *sb, aufs_bindex_t bindex) -+{ -+ return au_br_sb(au_sbr(sb, bindex)); -+} -+ -+static inline int au_sbr_perm(struct super_block *sb, aufs_bindex_t bindex) -+{ -+ return au_sbr(sb, bindex)->br_perm; -+} -+ -+static inline int au_sbr_whable(struct super_block *sb, aufs_bindex_t bindex) -+{ -+ return au_br_whable(au_sbr_perm(sb, bindex)); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+#define wbr_wh_read_lock(wbr) au_rw_read_lock(&(wbr)->wbr_wh_rwsem) -+#define wbr_wh_write_lock(wbr) au_rw_write_lock(&(wbr)->wbr_wh_rwsem) -+#define wbr_wh_read_trylock(wbr) au_rw_read_trylock(&(wbr)->wbr_wh_rwsem) -+#define wbr_wh_write_trylock(wbr) au_rw_write_trylock(&(wbr)->wbr_wh_rwsem) -+/* -+#define wbr_wh_read_trylock_nested(wbr) \ -+ au_rw_read_trylock_nested(&(wbr)->wbr_wh_rwsem) -+#define wbr_wh_write_trylock_nested(wbr) \ -+ au_rw_write_trylock_nested(&(wbr)->wbr_wh_rwsem) -+*/ -+ -+#define wbr_wh_read_unlock(wbr) au_rw_read_unlock(&(wbr)->wbr_wh_rwsem) -+#define wbr_wh_write_unlock(wbr) au_rw_write_unlock(&(wbr)->wbr_wh_rwsem) -+#define wbr_wh_downgrade_lock(wbr) au_rw_dgrade_lock(&(wbr)->wbr_wh_rwsem) -+ -+#define WbrWhMustNoWaiters(wbr) AuRwMustNoWaiters(&(wbr)->wbr_wh_rwsem) -+#define WbrWhMustAnyLock(wbr) AuRwMustAnyLock(&(wbr)->wbr_wh_rwsem) -+#define WbrWhMustWriteLock(wbr) AuRwMustWriteLock(&(wbr)->wbr_wh_rwsem) -+ -+/* ---------------------------------------------------------------------- */ -+ -+#ifdef CONFIG_AUFS_FHSM -+static inline void au_br_fhsm_init(struct au_br_fhsm *brfhsm) -+{ -+ mutex_init(&brfhsm->bf_lock); -+ brfhsm->bf_jiffy = 0; -+ brfhsm->bf_readable = 0; -+} -+ -+static inline void au_br_fhsm_fin(struct au_br_fhsm *brfhsm) -+{ -+ mutex_destroy(&brfhsm->bf_lock); -+} -+#else -+AuStubVoid(au_br_fhsm_init, struct au_br_fhsm *brfhsm) -+AuStubVoid(au_br_fhsm_fin, struct au_br_fhsm *brfhsm) -+#endif -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_BRANCH_H__ */ -diff --git a/fs/aufs/cpup.c b/fs/aufs/cpup.c -new file mode 100644 -index 000000000000..69a60ddc3474 ---- /dev/null -+++ b/fs/aufs/cpup.c -@@ -0,0 +1,1445 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * copy-up functions, see wbr_policy.c for copy-down -+ */ -+ -+#include -+#include -+#include -+#include "aufs.h" -+ -+void au_cpup_attr_flags(struct inode *dst, unsigned int iflags) -+{ -+ const unsigned int mask = S_DEAD | S_SWAPFILE | S_PRIVATE -+ | S_NOATIME | S_NOCMTIME | S_AUTOMOUNT; -+ -+ BUILD_BUG_ON(sizeof(iflags) != sizeof(dst->i_flags)); -+ -+ dst->i_flags |= iflags & ~mask; -+ if (au_test_fs_notime(dst->i_sb)) -+ dst->i_flags |= S_NOATIME | S_NOCMTIME; -+} -+ -+void au_cpup_attr_timesizes(struct inode *inode) -+{ -+ struct inode *h_inode; -+ -+ h_inode = au_h_iptr(inode, au_ibtop(inode)); -+ fsstack_copy_attr_times(inode, h_inode); -+ fsstack_copy_inode_size(inode, h_inode); -+} -+ -+void au_cpup_attr_nlink(struct inode *inode, int force) -+{ -+ struct inode *h_inode; -+ struct super_block *sb; -+ aufs_bindex_t bindex, bbot; -+ -+ sb = inode->i_sb; -+ bindex = au_ibtop(inode); -+ h_inode = au_h_iptr(inode, bindex); -+ if (!force -+ && !S_ISDIR(h_inode->i_mode) -+ && au_opt_test(au_mntflags(sb), PLINK) -+ && au_plink_test(inode)) -+ return; -+ -+ /* -+ * 0 can happen in revalidating. -+ * h_inode->i_mutex may not be held here, but it is harmless since once -+ * i_nlink reaches 0, it will never become positive except O_TMPFILE -+ * case. -+ * todo: O_TMPFILE+linkat(AT_SYMLINK_FOLLOW) bypassing aufs may cause -+ * the incorrect link count. -+ */ -+ set_nlink(inode, h_inode->i_nlink); -+ -+ /* -+ * fewer nlink makes find(1) noisy, but larger nlink doesn't. -+ * it may includes whplink directory. -+ */ -+ if (S_ISDIR(h_inode->i_mode)) { -+ bbot = au_ibbot(inode); -+ for (bindex++; bindex <= bbot; bindex++) { -+ h_inode = au_h_iptr(inode, bindex); -+ if (h_inode) -+ au_add_nlink(inode, h_inode); -+ } -+ } -+} -+ -+void au_cpup_attr_changeable(struct inode *inode) -+{ -+ struct inode *h_inode; -+ -+ h_inode = au_h_iptr(inode, au_ibtop(inode)); -+ inode->i_mode = h_inode->i_mode; -+ inode->i_uid = h_inode->i_uid; -+ inode->i_gid = h_inode->i_gid; -+ au_cpup_attr_timesizes(inode); -+ au_cpup_attr_flags(inode, h_inode->i_flags); -+} -+ -+void au_cpup_igen(struct inode *inode, struct inode *h_inode) -+{ -+ struct au_iinfo *iinfo = au_ii(inode); -+ -+ IiMustWriteLock(inode); -+ -+ iinfo->ii_higen = h_inode->i_generation; -+ iinfo->ii_hsb1 = h_inode->i_sb; -+} -+ -+void au_cpup_attr_all(struct inode *inode, int force) -+{ -+ struct inode *h_inode; -+ -+ h_inode = au_h_iptr(inode, au_ibtop(inode)); -+ au_cpup_attr_changeable(inode); -+ if (inode->i_nlink > 0) -+ au_cpup_attr_nlink(inode, force); -+ inode->i_rdev = h_inode->i_rdev; -+ inode->i_blkbits = h_inode->i_blkbits; -+ au_cpup_igen(inode, h_inode); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* Note: dt_dentry and dt_h_dentry are not dget/dput-ed */ -+ -+/* keep the timestamps of the parent dir when cpup */ -+void au_dtime_store(struct au_dtime *dt, struct dentry *dentry, -+ struct path *h_path) -+{ -+ struct inode *h_inode; -+ -+ dt->dt_dentry = dentry; -+ dt->dt_h_path = *h_path; -+ h_inode = d_inode(h_path->dentry); -+ dt->dt_atime = h_inode->i_atime; -+ dt->dt_mtime = h_inode->i_mtime; -+ /* smp_mb(); */ -+} -+ -+void au_dtime_revert(struct au_dtime *dt) -+{ -+ struct iattr attr; -+ int err; -+ -+ attr.ia_atime = dt->dt_atime; -+ attr.ia_mtime = dt->dt_mtime; -+ attr.ia_valid = ATTR_FORCE | ATTR_MTIME | ATTR_MTIME_SET -+ | ATTR_ATIME | ATTR_ATIME_SET; -+ -+ /* no delegation since this is a directory */ -+ err = vfsub_notify_change(&dt->dt_h_path, &attr, /*delegated*/NULL); -+ if (unlikely(err)) -+ pr_warn("restoring timestamps failed(%d). ignored\n", err); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* internal use only */ -+struct au_cpup_reg_attr { -+ int valid; -+ struct kstat st; -+ unsigned int iflags; /* inode->i_flags */ -+}; -+ -+static noinline_for_stack -+int cpup_iattr(struct dentry *dst, aufs_bindex_t bindex, struct dentry *h_src, -+ struct au_cpup_reg_attr *h_src_attr) -+{ -+ int err, sbits, icex; -+ unsigned int mnt_flags; -+ unsigned char verbose; -+ struct iattr ia; -+ struct path h_path; -+ struct inode *h_isrc, *h_idst; -+ struct kstat *h_st; -+ struct au_branch *br; -+ -+ h_path.dentry = au_h_dptr(dst, bindex); -+ h_idst = d_inode(h_path.dentry); -+ br = au_sbr(dst->d_sb, bindex); -+ h_path.mnt = au_br_mnt(br); -+ h_isrc = d_inode(h_src); -+ ia.ia_valid = ATTR_FORCE | ATTR_UID | ATTR_GID -+ | ATTR_ATIME | ATTR_MTIME -+ | ATTR_ATIME_SET | ATTR_MTIME_SET; -+ if (h_src_attr && h_src_attr->valid) { -+ h_st = &h_src_attr->st; -+ ia.ia_uid = h_st->uid; -+ ia.ia_gid = h_st->gid; -+ ia.ia_atime = h_st->atime; -+ ia.ia_mtime = h_st->mtime; -+ if (h_idst->i_mode != h_st->mode -+ && !S_ISLNK(h_idst->i_mode)) { -+ ia.ia_valid |= ATTR_MODE; -+ ia.ia_mode = h_st->mode; -+ } -+ sbits = !!(h_st->mode & (S_ISUID | S_ISGID)); -+ au_cpup_attr_flags(h_idst, h_src_attr->iflags); -+ } else { -+ ia.ia_uid = h_isrc->i_uid; -+ ia.ia_gid = h_isrc->i_gid; -+ ia.ia_atime = h_isrc->i_atime; -+ ia.ia_mtime = h_isrc->i_mtime; -+ if (h_idst->i_mode != h_isrc->i_mode -+ && !S_ISLNK(h_idst->i_mode)) { -+ ia.ia_valid |= ATTR_MODE; -+ ia.ia_mode = h_isrc->i_mode; -+ } -+ sbits = !!(h_isrc->i_mode & (S_ISUID | S_ISGID)); -+ au_cpup_attr_flags(h_idst, h_isrc->i_flags); -+ } -+ /* no delegation since it is just created */ -+ err = vfsub_notify_change(&h_path, &ia, /*delegated*/NULL); -+ -+ /* is this nfs only? */ -+ if (!err && sbits && au_test_nfs(h_path.dentry->d_sb)) { -+ ia.ia_valid = ATTR_FORCE | ATTR_MODE; -+ ia.ia_mode = h_isrc->i_mode; -+ err = vfsub_notify_change(&h_path, &ia, /*delegated*/NULL); -+ } -+ -+ icex = br->br_perm & AuBrAttr_ICEX; -+ if (!err) { -+ mnt_flags = au_mntflags(dst->d_sb); -+ verbose = !!au_opt_test(mnt_flags, VERBOSE); -+ err = au_cpup_xattr(h_path.dentry, h_src, icex, verbose); -+ } -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int au_do_copy_file(struct file *dst, struct file *src, loff_t len, -+ char *buf, unsigned long blksize) -+{ -+ int err; -+ size_t sz, rbytes, wbytes; -+ unsigned char all_zero; -+ char *p, *zp; -+ struct inode *h_inode; -+ /* reduce stack usage */ -+ struct iattr *ia; -+ -+ zp = page_address(ZERO_PAGE(0)); -+ if (unlikely(!zp)) -+ return -ENOMEM; /* possible? */ -+ -+ err = 0; -+ all_zero = 0; -+ while (len) { -+ AuDbg("len %lld\n", len); -+ sz = blksize; -+ if (len < blksize) -+ sz = len; -+ -+ rbytes = 0; -+ /* todo: signal_pending? */ -+ while (!rbytes || err == -EAGAIN || err == -EINTR) { -+ rbytes = vfsub_read_k(src, buf, sz, &src->f_pos); -+ err = rbytes; -+ } -+ if (unlikely(err < 0)) -+ break; -+ -+ all_zero = 0; -+ if (len >= rbytes && rbytes == blksize) -+ all_zero = !memcmp(buf, zp, rbytes); -+ if (!all_zero) { -+ wbytes = rbytes; -+ p = buf; -+ while (wbytes) { -+ size_t b; -+ -+ b = vfsub_write_k(dst, p, wbytes, &dst->f_pos); -+ err = b; -+ /* todo: signal_pending? */ -+ if (unlikely(err == -EAGAIN || err == -EINTR)) -+ continue; -+ if (unlikely(err < 0)) -+ break; -+ wbytes -= b; -+ p += b; -+ } -+ if (unlikely(err < 0)) -+ break; -+ } else { -+ loff_t res; -+ -+ AuLabel(hole); -+ res = vfsub_llseek(dst, rbytes, SEEK_CUR); -+ err = res; -+ if (unlikely(res < 0)) -+ break; -+ } -+ len -= rbytes; -+ err = 0; -+ } -+ -+ /* the last block may be a hole */ -+ if (!err && all_zero) { -+ AuLabel(last hole); -+ -+ err = 1; -+ if (au_test_nfs(dst->f_path.dentry->d_sb)) { -+ /* nfs requires this step to make last hole */ -+ /* is this only nfs? */ -+ do { -+ /* todo: signal_pending? */ -+ err = vfsub_write_k(dst, "\0", 1, &dst->f_pos); -+ } while (err == -EAGAIN || err == -EINTR); -+ if (err == 1) -+ dst->f_pos--; -+ } -+ -+ if (err == 1) { -+ ia = (void *)buf; -+ ia->ia_size = dst->f_pos; -+ ia->ia_valid = ATTR_SIZE | ATTR_FILE; -+ ia->ia_file = dst; -+ h_inode = file_inode(dst); -+ inode_lock_nested(h_inode, AuLsc_I_CHILD2); -+ /* no delegation since it is just created */ -+ err = vfsub_notify_change(&dst->f_path, ia, -+ /*delegated*/NULL); -+ inode_unlock(h_inode); -+ } -+ } -+ -+ return err; -+} -+ -+int au_copy_file(struct file *dst, struct file *src, loff_t len) -+{ -+ int err; -+ unsigned long blksize; -+ unsigned char do_kfree; -+ char *buf; -+ struct super_block *h_sb; -+ -+ err = -ENOMEM; -+ h_sb = file_inode(dst)->i_sb; -+ blksize = h_sb->s_blocksize; -+ if (!blksize || PAGE_SIZE < blksize) -+ blksize = PAGE_SIZE; -+ AuDbg("blksize %lu\n", blksize); -+ do_kfree = (blksize != PAGE_SIZE && blksize >= sizeof(struct iattr *)); -+ if (do_kfree) -+ buf = kmalloc(blksize, GFP_NOFS); -+ else -+ buf = (void *)__get_free_page(GFP_NOFS); -+ if (unlikely(!buf)) -+ goto out; -+ -+ if (len > (1 << 22)) -+ AuDbg("copying a large file %lld\n", (long long)len); -+ -+ src->f_pos = 0; -+ dst->f_pos = 0; -+ err = au_do_copy_file(dst, src, len, buf, blksize); -+ if (do_kfree) { -+ AuDebugOn(!au_kfree_do_sz_test(blksize)); -+ au_kfree_do_rcu(buf); -+ } else -+ free_page((unsigned long)buf); -+ -+out: -+ return err; -+} -+ -+static int au_do_copy(struct file *dst, struct file *src, loff_t len) -+{ -+ int err; -+ struct super_block *h_src_sb; -+ struct inode *h_src_inode; -+ -+ h_src_inode = file_inode(src); -+ h_src_sb = h_src_inode->i_sb; -+ -+ /* XFS acquires inode_lock */ -+ if (!au_test_xfs(h_src_sb)) -+ err = au_copy_file(dst, src, len); -+ else { -+ inode_unlock_shared(h_src_inode); -+ err = au_copy_file(dst, src, len); -+ inode_lock_shared_nested(h_src_inode, AuLsc_I_CHILD); -+ } -+ -+ return err; -+} -+ -+static int au_clone_or_copy(struct file *dst, struct file *src, loff_t len) -+{ -+ int err; -+ loff_t lo; -+ struct super_block *h_src_sb; -+ struct inode *h_src_inode; -+ -+ h_src_inode = file_inode(src); -+ h_src_sb = h_src_inode->i_sb; -+ if (h_src_sb != file_inode(dst)->i_sb -+ || !dst->f_op->remap_file_range) { -+ err = au_do_copy(dst, src, len); -+ goto out; -+ } -+ -+ if (!au_test_nfs(h_src_sb)) { -+ inode_unlock_shared(h_src_inode); -+ lo = vfsub_clone_file_range(src, dst, len); -+ inode_lock_shared_nested(h_src_inode, AuLsc_I_CHILD); -+ } else -+ lo = vfsub_clone_file_range(src, dst, len); -+ if (lo == len) { -+ err = 0; -+ goto out; /* success */ -+ } else if (lo >= 0) -+ /* todo: possible? */ -+ /* paritially succeeded */ -+ AuDbg("lo %lld, len %lld. Retrying.\n", lo, len); -+ else if (lo != -EOPNOTSUPP) { -+ /* older XFS has a condition in cloning */ -+ err = lo; -+ goto out; -+ } -+ -+ /* the backend fs on NFS may not support cloning */ -+ err = au_do_copy(dst, src, len); -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+/* -+ * to support a sparse file which is opened with O_APPEND, -+ * we need to close the file. -+ */ -+static int au_cp_regular(struct au_cp_generic *cpg) -+{ -+ int err, i; -+ enum { SRC, DST }; -+ struct { -+ aufs_bindex_t bindex; -+ unsigned int flags; -+ struct dentry *dentry; -+ int force_wr; -+ struct file *file; -+ } *f, file[] = { -+ { -+ .bindex = cpg->bsrc, -+ .flags = O_RDONLY | O_NOATIME | O_LARGEFILE, -+ }, -+ { -+ .bindex = cpg->bdst, -+ .flags = O_WRONLY | O_NOATIME | O_LARGEFILE, -+ .force_wr = !!au_ftest_cpup(cpg->flags, RWDST), -+ } -+ }; -+ struct au_branch *br; -+ struct super_block *sb, *h_src_sb; -+ struct inode *h_src_inode; -+ struct task_struct *tsk = current; -+ -+ /* bsrc branch can be ro/rw. */ -+ sb = cpg->dentry->d_sb; -+ f = file; -+ for (i = 0; i < 2; i++, f++) { -+ f->dentry = au_h_dptr(cpg->dentry, f->bindex); -+ f->file = au_h_open(cpg->dentry, f->bindex, f->flags, -+ /*file*/NULL, f->force_wr); -+ if (IS_ERR(f->file)) { -+ err = PTR_ERR(f->file); -+ if (i == SRC) -+ goto out; -+ else -+ goto out_src; -+ } -+ } -+ -+ /* try stopping to update while we copyup */ -+ h_src_inode = d_inode(file[SRC].dentry); -+ h_src_sb = h_src_inode->i_sb; -+ if (!au_test_nfs(h_src_sb)) -+ IMustLock(h_src_inode); -+ err = au_clone_or_copy(file[DST].file, file[SRC].file, cpg->len); -+ -+ /* i wonder if we had O_NO_DELAY_FPUT flag */ -+ if (tsk->flags & PF_KTHREAD) -+ __fput_sync(file[DST].file); -+ else { -+ /* it happened actually */ -+ fput(file[DST].file); -+ /* -+ * too bad. -+ * we have to call both since we don't know which place the file -+ * was added to. -+ */ -+ task_work_run(); -+ flush_delayed_fput(); -+ } -+ br = au_sbr(sb, file[DST].bindex); -+ au_lcnt_dec(&br->br_nfiles); -+ -+out_src: -+ fput(file[SRC].file); -+ br = au_sbr(sb, file[SRC].bindex); -+ au_lcnt_dec(&br->br_nfiles); -+out: -+ return err; -+} -+ -+static int au_do_cpup_regular(struct au_cp_generic *cpg, -+ struct au_cpup_reg_attr *h_src_attr) -+{ -+ int err, rerr; -+ loff_t l; -+ struct path h_path; -+ struct inode *h_src_inode, *h_dst_inode; -+ -+ err = 0; -+ h_src_inode = au_h_iptr(d_inode(cpg->dentry), cpg->bsrc); -+ l = i_size_read(h_src_inode); -+ if (cpg->len == -1 || l < cpg->len) -+ cpg->len = l; -+ if (cpg->len) { -+ /* try stopping to update while we are referencing */ -+ inode_lock_shared_nested(h_src_inode, AuLsc_I_CHILD); -+ au_pin_hdir_unlock(cpg->pin); -+ -+ h_path.dentry = au_h_dptr(cpg->dentry, cpg->bsrc); -+ h_path.mnt = au_sbr_mnt(cpg->dentry->d_sb, cpg->bsrc); -+ h_src_attr->iflags = h_src_inode->i_flags; -+ if (!au_test_nfs(h_src_inode->i_sb)) -+ err = vfsub_getattr(&h_path, &h_src_attr->st); -+ else { -+ inode_unlock_shared(h_src_inode); -+ err = vfsub_getattr(&h_path, &h_src_attr->st); -+ inode_lock_shared_nested(h_src_inode, AuLsc_I_CHILD); -+ } -+ if (unlikely(err)) { -+ inode_unlock_shared(h_src_inode); -+ goto out; -+ } -+ h_src_attr->valid = 1; -+ if (!au_test_nfs(h_src_inode->i_sb)) { -+ err = au_cp_regular(cpg); -+ inode_unlock_shared(h_src_inode); -+ } else { -+ inode_unlock_shared(h_src_inode); -+ err = au_cp_regular(cpg); -+ } -+ rerr = au_pin_hdir_relock(cpg->pin); -+ if (!err && rerr) -+ err = rerr; -+ } -+ if (!err && (h_src_inode->i_state & I_LINKABLE)) { -+ h_path.dentry = au_h_dptr(cpg->dentry, cpg->bdst); -+ h_dst_inode = d_inode(h_path.dentry); -+ spin_lock(&h_dst_inode->i_lock); -+ h_dst_inode->i_state |= I_LINKABLE; -+ spin_unlock(&h_dst_inode->i_lock); -+ } -+ -+out: -+ return err; -+} -+ -+static int au_do_cpup_symlink(struct path *h_path, struct dentry *h_src, -+ struct inode *h_dir) -+{ -+ int err, symlen; -+ mm_segment_t old_fs; -+ union { -+ char *k; -+ char __user *u; -+ } sym; -+ -+ err = -ENOMEM; -+ sym.k = (void *)__get_free_page(GFP_NOFS); -+ if (unlikely(!sym.k)) -+ goto out; -+ -+ /* unnecessary to support mmap_sem since symlink is not mmap-able */ -+ old_fs = get_fs(); -+ set_fs(KERNEL_DS); -+ symlen = vfs_readlink(h_src, sym.u, PATH_MAX); -+ err = symlen; -+ set_fs(old_fs); -+ -+ if (symlen > 0) { -+ sym.k[symlen] = 0; -+ err = vfsub_symlink(h_dir, h_path, sym.k); -+ } -+ free_page((unsigned long)sym.k); -+ -+out: -+ return err; -+} -+ -+/* -+ * regardless 'acl' option, reset all ACL. -+ * All ACL will be copied up later from the original entry on the lower branch. -+ */ -+static int au_reset_acl(struct inode *h_dir, struct path *h_path, umode_t mode) -+{ -+ int err; -+ struct dentry *h_dentry; -+ struct inode *h_inode; -+ -+ h_dentry = h_path->dentry; -+ h_inode = d_inode(h_dentry); -+ /* forget_all_cached_acls(h_inode)); */ -+ err = vfsub_removexattr(h_dentry, XATTR_NAME_POSIX_ACL_ACCESS); -+ AuTraceErr(err); -+ if (err == -EOPNOTSUPP) -+ err = 0; -+ if (!err) -+ err = vfsub_acl_chmod(h_inode, mode); -+ -+ AuTraceErr(err); -+ return err; -+} -+ -+static int au_do_cpup_dir(struct au_cp_generic *cpg, struct dentry *dst_parent, -+ struct inode *h_dir, struct path *h_path) -+{ -+ int err; -+ struct inode *dir, *inode; -+ -+ err = vfsub_removexattr(h_path->dentry, XATTR_NAME_POSIX_ACL_DEFAULT); -+ AuTraceErr(err); -+ if (err == -EOPNOTSUPP) -+ err = 0; -+ if (unlikely(err)) -+ goto out; -+ -+ /* -+ * strange behaviour from the users view, -+ * particularly setattr case -+ */ -+ dir = d_inode(dst_parent); -+ if (au_ibtop(dir) == cpg->bdst) -+ au_cpup_attr_nlink(dir, /*force*/1); -+ inode = d_inode(cpg->dentry); -+ au_cpup_attr_nlink(inode, /*force*/1); -+ -+out: -+ return err; -+} -+ -+static noinline_for_stack -+int cpup_entry(struct au_cp_generic *cpg, struct dentry *dst_parent, -+ struct au_cpup_reg_attr *h_src_attr) -+{ -+ int err; -+ umode_t mode; -+ unsigned int mnt_flags; -+ unsigned char isdir, isreg, force; -+ const unsigned char do_dt = !!au_ftest_cpup(cpg->flags, DTIME); -+ struct au_dtime dt; -+ struct path h_path; -+ struct dentry *h_src, *h_dst, *h_parent; -+ struct inode *h_inode, *h_dir; -+ struct super_block *sb; -+ -+ /* bsrc branch can be ro/rw. */ -+ h_src = au_h_dptr(cpg->dentry, cpg->bsrc); -+ h_inode = d_inode(h_src); -+ AuDebugOn(h_inode != au_h_iptr(d_inode(cpg->dentry), cpg->bsrc)); -+ -+ /* try stopping to be referenced while we are creating */ -+ h_dst = au_h_dptr(cpg->dentry, cpg->bdst); -+ if (au_ftest_cpup(cpg->flags, RENAME)) -+ AuDebugOn(strncmp(h_dst->d_name.name, AUFS_WH_PFX, -+ AUFS_WH_PFX_LEN)); -+ h_parent = h_dst->d_parent; /* dir inode is locked */ -+ h_dir = d_inode(h_parent); -+ IMustLock(h_dir); -+ AuDebugOn(h_parent != h_dst->d_parent); -+ -+ sb = cpg->dentry->d_sb; -+ h_path.mnt = au_sbr_mnt(sb, cpg->bdst); -+ if (do_dt) { -+ h_path.dentry = h_parent; -+ au_dtime_store(&dt, dst_parent, &h_path); -+ } -+ h_path.dentry = h_dst; -+ -+ isreg = 0; -+ isdir = 0; -+ mode = h_inode->i_mode; -+ switch (mode & S_IFMT) { -+ case S_IFREG: -+ isreg = 1; -+ err = vfsub_create(h_dir, &h_path, 0600, /*want_excl*/true); -+ if (!err) -+ err = au_do_cpup_regular(cpg, h_src_attr); -+ break; -+ case S_IFDIR: -+ isdir = 1; -+ err = vfsub_mkdir(h_dir, &h_path, mode); -+ if (!err) -+ err = au_do_cpup_dir(cpg, dst_parent, h_dir, &h_path); -+ break; -+ case S_IFLNK: -+ err = au_do_cpup_symlink(&h_path, h_src, h_dir); -+ break; -+ case S_IFCHR: -+ case S_IFBLK: -+ AuDebugOn(!capable(CAP_MKNOD)); -+ /*FALLTHROUGH*/ -+ case S_IFIFO: -+ case S_IFSOCK: -+ err = vfsub_mknod(h_dir, &h_path, mode, h_inode->i_rdev); -+ break; -+ default: -+ AuIOErr("Unknown inode type 0%o\n", mode); -+ err = -EIO; -+ } -+ if (!err) -+ err = au_reset_acl(h_dir, &h_path, mode); -+ -+ mnt_flags = au_mntflags(sb); -+ if (!au_opt_test(mnt_flags, UDBA_NONE) -+ && !isdir -+ && au_opt_test(mnt_flags, XINO) -+ && (h_inode->i_nlink == 1 -+ || (h_inode->i_state & I_LINKABLE)) -+ /* todo: unnecessary? */ -+ /* && d_inode(cpg->dentry)->i_nlink == 1 */ -+ && cpg->bdst < cpg->bsrc -+ && !au_ftest_cpup(cpg->flags, KEEPLINO)) -+ au_xino_write(sb, cpg->bsrc, h_inode->i_ino, /*ino*/0); -+ /* ignore this error */ -+ -+ if (!err) { -+ force = 0; -+ if (isreg) { -+ force = !!cpg->len; -+ if (cpg->len == -1) -+ force = !!i_size_read(h_inode); -+ } -+ au_fhsm_wrote(sb, cpg->bdst, force); -+ } -+ -+ if (do_dt) -+ au_dtime_revert(&dt); -+ return err; -+} -+ -+static int au_do_ren_after_cpup(struct au_cp_generic *cpg, struct path *h_path) -+{ -+ int err; -+ struct dentry *dentry, *h_dentry, *h_parent, *parent; -+ struct inode *h_dir; -+ aufs_bindex_t bdst; -+ -+ dentry = cpg->dentry; -+ bdst = cpg->bdst; -+ h_dentry = au_h_dptr(dentry, bdst); -+ if (!au_ftest_cpup(cpg->flags, OVERWRITE)) { -+ dget(h_dentry); -+ au_set_h_dptr(dentry, bdst, NULL); -+ err = au_lkup_neg(dentry, bdst, /*wh*/0); -+ if (!err) -+ h_path->dentry = dget(au_h_dptr(dentry, bdst)); -+ au_set_h_dptr(dentry, bdst, h_dentry); -+ } else { -+ err = 0; -+ parent = dget_parent(dentry); -+ h_parent = au_h_dptr(parent, bdst); -+ dput(parent); -+ h_path->dentry = vfsub_lkup_one(&dentry->d_name, h_parent); -+ if (IS_ERR(h_path->dentry)) -+ err = PTR_ERR(h_path->dentry); -+ } -+ if (unlikely(err)) -+ goto out; -+ -+ h_parent = h_dentry->d_parent; /* dir inode is locked */ -+ h_dir = d_inode(h_parent); -+ IMustLock(h_dir); -+ AuDbg("%pd %pd\n", h_dentry, h_path->dentry); -+ /* no delegation since it is just created */ -+ err = vfsub_rename(h_dir, h_dentry, h_dir, h_path, /*delegated*/NULL, -+ /*flags*/0); -+ dput(h_path->dentry); -+ -+out: -+ return err; -+} -+ -+/* -+ * copyup the @dentry from @bsrc to @bdst. -+ * the caller must set the both of lower dentries. -+ * @len is for truncating when it is -1 copyup the entire file. -+ * in link/rename cases, @dst_parent may be different from the real one. -+ * basic->bsrc can be larger than basic->bdst. -+ * aufs doesn't touch the credential so -+ * security_inode_copy_up{,_xattr}() are unnecessary. -+ */ -+static int au_cpup_single(struct au_cp_generic *cpg, struct dentry *dst_parent) -+{ -+ int err, rerr; -+ aufs_bindex_t old_ibtop; -+ unsigned char isdir, plink; -+ struct dentry *h_src, *h_dst, *h_parent; -+ struct inode *dst_inode, *h_dir, *inode, *delegated, *src_inode; -+ struct super_block *sb; -+ struct au_branch *br; -+ /* to reduce stack size */ -+ struct { -+ struct au_dtime dt; -+ struct path h_path; -+ struct au_cpup_reg_attr h_src_attr; -+ } *a; -+ -+ err = -ENOMEM; -+ a = kmalloc(sizeof(*a), GFP_NOFS); -+ if (unlikely(!a)) -+ goto out; -+ a->h_src_attr.valid = 0; -+ -+ sb = cpg->dentry->d_sb; -+ br = au_sbr(sb, cpg->bdst); -+ a->h_path.mnt = au_br_mnt(br); -+ h_dst = au_h_dptr(cpg->dentry, cpg->bdst); -+ h_parent = h_dst->d_parent; /* dir inode is locked */ -+ h_dir = d_inode(h_parent); -+ IMustLock(h_dir); -+ -+ h_src = au_h_dptr(cpg->dentry, cpg->bsrc); -+ inode = d_inode(cpg->dentry); -+ -+ if (!dst_parent) -+ dst_parent = dget_parent(cpg->dentry); -+ else -+ dget(dst_parent); -+ -+ plink = !!au_opt_test(au_mntflags(sb), PLINK); -+ dst_inode = au_h_iptr(inode, cpg->bdst); -+ if (dst_inode) { -+ if (unlikely(!plink)) { -+ err = -EIO; -+ AuIOErr("hi%lu(i%lu) exists on b%d " -+ "but plink is disabled\n", -+ dst_inode->i_ino, inode->i_ino, cpg->bdst); -+ goto out_parent; -+ } -+ -+ if (dst_inode->i_nlink) { -+ const int do_dt = au_ftest_cpup(cpg->flags, DTIME); -+ -+ h_src = au_plink_lkup(inode, cpg->bdst); -+ err = PTR_ERR(h_src); -+ if (IS_ERR(h_src)) -+ goto out_parent; -+ if (unlikely(d_is_negative(h_src))) { -+ err = -EIO; -+ AuIOErr("i%lu exists on b%d " -+ "but not pseudo-linked\n", -+ inode->i_ino, cpg->bdst); -+ dput(h_src); -+ goto out_parent; -+ } -+ -+ if (do_dt) { -+ a->h_path.dentry = h_parent; -+ au_dtime_store(&a->dt, dst_parent, &a->h_path); -+ } -+ -+ a->h_path.dentry = h_dst; -+ delegated = NULL; -+ err = vfsub_link(h_src, h_dir, &a->h_path, &delegated); -+ if (!err && au_ftest_cpup(cpg->flags, RENAME)) -+ err = au_do_ren_after_cpup(cpg, &a->h_path); -+ if (do_dt) -+ au_dtime_revert(&a->dt); -+ if (unlikely(err == -EWOULDBLOCK)) { -+ pr_warn("cannot retry for NFSv4 delegation" -+ " for an internal link\n"); -+ iput(delegated); -+ } -+ dput(h_src); -+ goto out_parent; -+ } else -+ /* todo: cpup_wh_file? */ -+ /* udba work */ -+ au_update_ibrange(inode, /*do_put_zero*/1); -+ } -+ -+ isdir = S_ISDIR(inode->i_mode); -+ old_ibtop = au_ibtop(inode); -+ err = cpup_entry(cpg, dst_parent, &a->h_src_attr); -+ if (unlikely(err)) -+ goto out_rev; -+ dst_inode = d_inode(h_dst); -+ inode_lock_nested(dst_inode, AuLsc_I_CHILD2); -+ /* todo: necessary? */ -+ /* au_pin_hdir_unlock(cpg->pin); */ -+ -+ err = cpup_iattr(cpg->dentry, cpg->bdst, h_src, &a->h_src_attr); -+ if (unlikely(err)) { -+ /* todo: necessary? */ -+ /* au_pin_hdir_relock(cpg->pin); */ /* ignore an error */ -+ inode_unlock(dst_inode); -+ goto out_rev; -+ } -+ -+ if (cpg->bdst < old_ibtop) { -+ if (S_ISREG(inode->i_mode)) { -+ err = au_dy_iaop(inode, cpg->bdst, dst_inode); -+ if (unlikely(err)) { -+ /* ignore an error */ -+ /* au_pin_hdir_relock(cpg->pin); */ -+ inode_unlock(dst_inode); -+ goto out_rev; -+ } -+ } -+ au_set_ibtop(inode, cpg->bdst); -+ } else -+ au_set_ibbot(inode, cpg->bdst); -+ au_set_h_iptr(inode, cpg->bdst, au_igrab(dst_inode), -+ au_hi_flags(inode, isdir)); -+ -+ /* todo: necessary? */ -+ /* err = au_pin_hdir_relock(cpg->pin); */ -+ inode_unlock(dst_inode); -+ if (unlikely(err)) -+ goto out_rev; -+ -+ src_inode = d_inode(h_src); -+ if (!isdir -+ && (src_inode->i_nlink > 1 -+ || src_inode->i_state & I_LINKABLE) -+ && plink) -+ au_plink_append(inode, cpg->bdst, h_dst); -+ -+ if (au_ftest_cpup(cpg->flags, RENAME)) { -+ a->h_path.dentry = h_dst; -+ err = au_do_ren_after_cpup(cpg, &a->h_path); -+ } -+ if (!err) -+ goto out_parent; /* success */ -+ -+ /* revert */ -+out_rev: -+ a->h_path.dentry = h_parent; -+ au_dtime_store(&a->dt, dst_parent, &a->h_path); -+ a->h_path.dentry = h_dst; -+ rerr = 0; -+ if (d_is_positive(h_dst)) { -+ if (!isdir) { -+ /* no delegation since it is just created */ -+ rerr = vfsub_unlink(h_dir, &a->h_path, -+ /*delegated*/NULL, /*force*/0); -+ } else -+ rerr = vfsub_rmdir(h_dir, &a->h_path); -+ } -+ au_dtime_revert(&a->dt); -+ if (rerr) { -+ AuIOErr("failed removing broken entry(%d, %d)\n", err, rerr); -+ err = -EIO; -+ } -+out_parent: -+ dput(dst_parent); -+ au_kfree_rcu(a); -+out: -+ return err; -+} -+ -+#if 0 /* reserved */ -+struct au_cpup_single_args { -+ int *errp; -+ struct au_cp_generic *cpg; -+ struct dentry *dst_parent; -+}; -+ -+static void au_call_cpup_single(void *args) -+{ -+ struct au_cpup_single_args *a = args; -+ -+ au_pin_hdir_acquire_nest(a->cpg->pin); -+ *a->errp = au_cpup_single(a->cpg, a->dst_parent); -+ au_pin_hdir_release(a->cpg->pin); -+} -+#endif -+ -+/* -+ * prevent SIGXFSZ in copy-up. -+ * testing CAP_MKNOD is for generic fs, -+ * but CAP_FSETID is for xfs only, currently. -+ */ -+static int au_cpup_sio_test(struct au_pin *pin, umode_t mode) -+{ -+ int do_sio; -+ struct super_block *sb; -+ struct inode *h_dir; -+ -+ do_sio = 0; -+ sb = au_pinned_parent(pin)->d_sb; -+ if (!au_wkq_test() -+ && (!au_sbi(sb)->si_plink_maint_pid -+ || au_plink_maint(sb, AuLock_NOPLM))) { -+ switch (mode & S_IFMT) { -+ case S_IFREG: -+ /* no condition about RLIMIT_FSIZE and the file size */ -+ do_sio = 1; -+ break; -+ case S_IFCHR: -+ case S_IFBLK: -+ do_sio = !capable(CAP_MKNOD); -+ break; -+ } -+ if (!do_sio) -+ do_sio = ((mode & (S_ISUID | S_ISGID)) -+ && !capable(CAP_FSETID)); -+ /* this workaround may be removed in the future */ -+ if (!do_sio) { -+ h_dir = au_pinned_h_dir(pin); -+ do_sio = h_dir->i_mode & S_ISVTX; -+ } -+ } -+ -+ return do_sio; -+} -+ -+#if 0 /* reserved */ -+int au_sio_cpup_single(struct au_cp_generic *cpg, struct dentry *dst_parent) -+{ -+ int err, wkq_err; -+ struct dentry *h_dentry; -+ -+ h_dentry = au_h_dptr(cpg->dentry, cpg->bsrc); -+ if (!au_cpup_sio_test(pin, d_inode(h_dentry)->i_mode)) -+ err = au_cpup_single(cpg, dst_parent); -+ else { -+ struct au_cpup_single_args args = { -+ .errp = &err, -+ .cpg = cpg, -+ .dst_parent = dst_parent -+ }; -+ wkq_err = au_wkq_wait(au_call_cpup_single, &args); -+ if (unlikely(wkq_err)) -+ err = wkq_err; -+ } -+ -+ return err; -+} -+#endif -+ -+/* -+ * copyup the @dentry from the first active lower branch to @bdst, -+ * using au_cpup_single(). -+ */ -+static int au_cpup_simple(struct au_cp_generic *cpg) -+{ -+ int err; -+ unsigned int flags_orig; -+ struct dentry *dentry; -+ -+ AuDebugOn(cpg->bsrc < 0); -+ -+ dentry = cpg->dentry; -+ DiMustWriteLock(dentry); -+ -+ err = au_lkup_neg(dentry, cpg->bdst, /*wh*/1); -+ if (!err) { -+ flags_orig = cpg->flags; -+ au_fset_cpup(cpg->flags, RENAME); -+ err = au_cpup_single(cpg, NULL); -+ cpg->flags = flags_orig; -+ if (!err) -+ return 0; /* success */ -+ -+ /* revert */ -+ au_set_h_dptr(dentry, cpg->bdst, NULL); -+ au_set_dbtop(dentry, cpg->bsrc); -+ } -+ -+ return err; -+} -+ -+struct au_cpup_simple_args { -+ int *errp; -+ struct au_cp_generic *cpg; -+}; -+ -+static void au_call_cpup_simple(void *args) -+{ -+ struct au_cpup_simple_args *a = args; -+ -+ au_pin_hdir_acquire_nest(a->cpg->pin); -+ *a->errp = au_cpup_simple(a->cpg); -+ au_pin_hdir_release(a->cpg->pin); -+} -+ -+static int au_do_sio_cpup_simple(struct au_cp_generic *cpg) -+{ -+ int err, wkq_err; -+ struct dentry *dentry, *parent; -+ struct file *h_file; -+ struct inode *h_dir; -+ -+ dentry = cpg->dentry; -+ h_file = NULL; -+ if (au_ftest_cpup(cpg->flags, HOPEN)) { -+ AuDebugOn(cpg->bsrc < 0); -+ h_file = au_h_open_pre(dentry, cpg->bsrc, /*force_wr*/0); -+ err = PTR_ERR(h_file); -+ if (IS_ERR(h_file)) -+ goto out; -+ } -+ -+ parent = dget_parent(dentry); -+ h_dir = au_h_iptr(d_inode(parent), cpg->bdst); -+ if (!au_test_h_perm_sio(h_dir, MAY_EXEC | MAY_WRITE) -+ && !au_cpup_sio_test(cpg->pin, d_inode(dentry)->i_mode)) -+ err = au_cpup_simple(cpg); -+ else { -+ struct au_cpup_simple_args args = { -+ .errp = &err, -+ .cpg = cpg -+ }; -+ wkq_err = au_wkq_wait(au_call_cpup_simple, &args); -+ if (unlikely(wkq_err)) -+ err = wkq_err; -+ } -+ -+ dput(parent); -+ if (h_file) -+ au_h_open_post(dentry, cpg->bsrc, h_file); -+ -+out: -+ return err; -+} -+ -+int au_sio_cpup_simple(struct au_cp_generic *cpg) -+{ -+ aufs_bindex_t bsrc, bbot; -+ struct dentry *dentry, *h_dentry; -+ -+ if (cpg->bsrc < 0) { -+ dentry = cpg->dentry; -+ bbot = au_dbbot(dentry); -+ for (bsrc = cpg->bdst + 1; bsrc <= bbot; bsrc++) { -+ h_dentry = au_h_dptr(dentry, bsrc); -+ if (h_dentry) { -+ AuDebugOn(d_is_negative(h_dentry)); -+ break; -+ } -+ } -+ AuDebugOn(bsrc > bbot); -+ cpg->bsrc = bsrc; -+ } -+ AuDebugOn(cpg->bsrc <= cpg->bdst); -+ return au_do_sio_cpup_simple(cpg); -+} -+ -+int au_sio_cpdown_simple(struct au_cp_generic *cpg) -+{ -+ AuDebugOn(cpg->bdst <= cpg->bsrc); -+ return au_do_sio_cpup_simple(cpg); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * copyup the deleted file for writing. -+ */ -+static int au_do_cpup_wh(struct au_cp_generic *cpg, struct dentry *wh_dentry, -+ struct file *file) -+{ -+ int err; -+ unsigned int flags_orig; -+ aufs_bindex_t bsrc_orig; -+ struct au_dinfo *dinfo; -+ struct { -+ struct au_hdentry *hd; -+ struct dentry *h_dentry; -+ } hdst, hsrc; -+ -+ dinfo = au_di(cpg->dentry); -+ AuRwMustWriteLock(&dinfo->di_rwsem); -+ -+ bsrc_orig = cpg->bsrc; -+ cpg->bsrc = dinfo->di_btop; -+ hdst.hd = au_hdentry(dinfo, cpg->bdst); -+ hdst.h_dentry = hdst.hd->hd_dentry; -+ hdst.hd->hd_dentry = wh_dentry; -+ dinfo->di_btop = cpg->bdst; -+ -+ hsrc.h_dentry = NULL; -+ if (file) { -+ hsrc.hd = au_hdentry(dinfo, cpg->bsrc); -+ hsrc.h_dentry = hsrc.hd->hd_dentry; -+ hsrc.hd->hd_dentry = au_hf_top(file)->f_path.dentry; -+ } -+ flags_orig = cpg->flags; -+ cpg->flags = !AuCpup_DTIME; -+ err = au_cpup_single(cpg, /*h_parent*/NULL); -+ cpg->flags = flags_orig; -+ if (file) { -+ if (!err) -+ err = au_reopen_nondir(file); -+ hsrc.hd->hd_dentry = hsrc.h_dentry; -+ } -+ hdst.hd->hd_dentry = hdst.h_dentry; -+ dinfo->di_btop = cpg->bsrc; -+ cpg->bsrc = bsrc_orig; -+ -+ return err; -+} -+ -+static int au_cpup_wh(struct au_cp_generic *cpg, struct file *file) -+{ -+ int err; -+ aufs_bindex_t bdst; -+ struct au_dtime dt; -+ struct dentry *dentry, *parent, *h_parent, *wh_dentry; -+ struct au_branch *br; -+ struct path h_path; -+ -+ dentry = cpg->dentry; -+ bdst = cpg->bdst; -+ br = au_sbr(dentry->d_sb, bdst); -+ parent = dget_parent(dentry); -+ h_parent = au_h_dptr(parent, bdst); -+ wh_dentry = au_whtmp_lkup(h_parent, br, &dentry->d_name); -+ err = PTR_ERR(wh_dentry); -+ if (IS_ERR(wh_dentry)) -+ goto out; -+ -+ h_path.dentry = h_parent; -+ h_path.mnt = au_br_mnt(br); -+ au_dtime_store(&dt, parent, &h_path); -+ err = au_do_cpup_wh(cpg, wh_dentry, file); -+ if (unlikely(err)) -+ goto out_wh; -+ -+ dget(wh_dentry); -+ h_path.dentry = wh_dentry; -+ if (!d_is_dir(wh_dentry)) { -+ /* no delegation since it is just created */ -+ err = vfsub_unlink(d_inode(h_parent), &h_path, -+ /*delegated*/NULL, /*force*/0); -+ } else -+ err = vfsub_rmdir(d_inode(h_parent), &h_path); -+ if (unlikely(err)) { -+ AuIOErr("failed remove copied-up tmp file %pd(%d)\n", -+ wh_dentry, err); -+ err = -EIO; -+ } -+ au_dtime_revert(&dt); -+ au_set_hi_wh(d_inode(dentry), bdst, wh_dentry); -+ -+out_wh: -+ dput(wh_dentry); -+out: -+ dput(parent); -+ return err; -+} -+ -+struct au_cpup_wh_args { -+ int *errp; -+ struct au_cp_generic *cpg; -+ struct file *file; -+}; -+ -+static void au_call_cpup_wh(void *args) -+{ -+ struct au_cpup_wh_args *a = args; -+ -+ au_pin_hdir_acquire_nest(a->cpg->pin); -+ *a->errp = au_cpup_wh(a->cpg, a->file); -+ au_pin_hdir_release(a->cpg->pin); -+} -+ -+int au_sio_cpup_wh(struct au_cp_generic *cpg, struct file *file) -+{ -+ int err, wkq_err; -+ aufs_bindex_t bdst; -+ struct dentry *dentry, *parent, *h_orph, *h_parent; -+ struct inode *dir, *h_dir, *h_tmpdir; -+ struct au_wbr *wbr; -+ struct au_pin wh_pin, *pin_orig; -+ -+ dentry = cpg->dentry; -+ bdst = cpg->bdst; -+ parent = dget_parent(dentry); -+ dir = d_inode(parent); -+ h_orph = NULL; -+ h_parent = NULL; -+ h_dir = au_igrab(au_h_iptr(dir, bdst)); -+ h_tmpdir = h_dir; -+ pin_orig = NULL; -+ if (!h_dir->i_nlink) { -+ wbr = au_sbr(dentry->d_sb, bdst)->br_wbr; -+ h_orph = wbr->wbr_orph; -+ -+ h_parent = dget(au_h_dptr(parent, bdst)); -+ au_set_h_dptr(parent, bdst, dget(h_orph)); -+ h_tmpdir = d_inode(h_orph); -+ au_set_h_iptr(dir, bdst, au_igrab(h_tmpdir), /*flags*/0); -+ -+ inode_lock_nested(h_tmpdir, AuLsc_I_PARENT3); -+ /* todo: au_h_open_pre()? */ -+ -+ pin_orig = cpg->pin; -+ au_pin_init(&wh_pin, dentry, bdst, AuLsc_DI_PARENT, -+ AuLsc_I_PARENT3, cpg->pin->udba, AuPin_DI_LOCKED); -+ cpg->pin = &wh_pin; -+ } -+ -+ if (!au_test_h_perm_sio(h_tmpdir, MAY_EXEC | MAY_WRITE) -+ && !au_cpup_sio_test(cpg->pin, d_inode(dentry)->i_mode)) -+ err = au_cpup_wh(cpg, file); -+ else { -+ struct au_cpup_wh_args args = { -+ .errp = &err, -+ .cpg = cpg, -+ .file = file -+ }; -+ wkq_err = au_wkq_wait(au_call_cpup_wh, &args); -+ if (unlikely(wkq_err)) -+ err = wkq_err; -+ } -+ -+ if (h_orph) { -+ inode_unlock(h_tmpdir); -+ /* todo: au_h_open_post()? */ -+ au_set_h_iptr(dir, bdst, au_igrab(h_dir), /*flags*/0); -+ au_set_h_dptr(parent, bdst, h_parent); -+ AuDebugOn(!pin_orig); -+ cpg->pin = pin_orig; -+ } -+ iput(h_dir); -+ dput(parent); -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * generic routine for both of copy-up and copy-down. -+ */ -+/* cf. revalidate function in file.c */ -+int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst, -+ int (*cp)(struct dentry *dentry, aufs_bindex_t bdst, -+ struct au_pin *pin, -+ struct dentry *h_parent, void *arg), -+ void *arg) -+{ -+ int err; -+ struct au_pin pin; -+ struct dentry *d, *parent, *h_parent, *real_parent, *h_dentry; -+ -+ err = 0; -+ parent = dget_parent(dentry); -+ if (IS_ROOT(parent)) -+ goto out; -+ -+ au_pin_init(&pin, dentry, bdst, AuLsc_DI_PARENT2, AuLsc_I_PARENT2, -+ au_opt_udba(dentry->d_sb), AuPin_MNT_WRITE); -+ -+ /* do not use au_dpage */ -+ real_parent = parent; -+ while (1) { -+ dput(parent); -+ parent = dget_parent(dentry); -+ h_parent = au_h_dptr(parent, bdst); -+ if (h_parent) -+ goto out; /* success */ -+ -+ /* find top dir which is necessary to cpup */ -+ do { -+ d = parent; -+ dput(parent); -+ parent = dget_parent(d); -+ di_read_lock_parent3(parent, !AuLock_IR); -+ h_parent = au_h_dptr(parent, bdst); -+ di_read_unlock(parent, !AuLock_IR); -+ } while (!h_parent); -+ -+ if (d != real_parent) -+ di_write_lock_child3(d); -+ -+ /* somebody else might create while we were sleeping */ -+ h_dentry = au_h_dptr(d, bdst); -+ if (!h_dentry || d_is_negative(h_dentry)) { -+ if (h_dentry) -+ au_update_dbtop(d); -+ -+ au_pin_set_dentry(&pin, d); -+ err = au_do_pin(&pin); -+ if (!err) { -+ err = cp(d, bdst, &pin, h_parent, arg); -+ au_unpin(&pin); -+ } -+ } -+ -+ if (d != real_parent) -+ di_write_unlock(d); -+ if (unlikely(err)) -+ break; -+ } -+ -+out: -+ dput(parent); -+ return err; -+} -+ -+static int au_cpup_dir(struct dentry *dentry, aufs_bindex_t bdst, -+ struct au_pin *pin, -+ struct dentry *h_parent __maybe_unused, -+ void *arg __maybe_unused) -+{ -+ struct au_cp_generic cpg = { -+ .dentry = dentry, -+ .bdst = bdst, -+ .bsrc = -1, -+ .len = 0, -+ .pin = pin, -+ .flags = AuCpup_DTIME -+ }; -+ return au_sio_cpup_simple(&cpg); -+} -+ -+int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst) -+{ -+ return au_cp_dirs(dentry, bdst, au_cpup_dir, NULL); -+} -+ -+int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst) -+{ -+ int err; -+ struct dentry *parent; -+ struct inode *dir; -+ -+ parent = dget_parent(dentry); -+ dir = d_inode(parent); -+ err = 0; -+ if (au_h_iptr(dir, bdst)) -+ goto out; -+ -+ di_read_unlock(parent, AuLock_IR); -+ di_write_lock_parent(parent); -+ /* someone else might change our inode while we were sleeping */ -+ if (!au_h_iptr(dir, bdst)) -+ err = au_cpup_dirs(dentry, bdst); -+ di_downgrade_lock(parent, AuLock_IR); -+ -+out: -+ dput(parent); -+ return err; -+} -diff --git a/fs/aufs/cpup.h b/fs/aufs/cpup.h -new file mode 100644 -index 000000000000..c23c1bbcee7e ---- /dev/null -+++ b/fs/aufs/cpup.h -@@ -0,0 +1,87 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * copy-up/down functions -+ */ -+ -+#ifndef __AUFS_CPUP_H__ -+#define __AUFS_CPUP_H__ -+ -+#ifdef __KERNEL__ -+ -+#include -+ -+struct inode; -+struct file; -+struct au_pin; -+ -+void au_cpup_attr_flags(struct inode *dst, unsigned int iflags); -+void au_cpup_attr_timesizes(struct inode *inode); -+void au_cpup_attr_nlink(struct inode *inode, int force); -+void au_cpup_attr_changeable(struct inode *inode); -+void au_cpup_igen(struct inode *inode, struct inode *h_inode); -+void au_cpup_attr_all(struct inode *inode, int force); -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct au_cp_generic { -+ struct dentry *dentry; -+ aufs_bindex_t bdst, bsrc; -+ loff_t len; -+ struct au_pin *pin; -+ unsigned int flags; -+}; -+ -+/* cpup flags */ -+#define AuCpup_DTIME 1 /* do dtime_store/revert */ -+#define AuCpup_KEEPLINO (1 << 1) /* do not clear the lower xino, -+ for link(2) */ -+#define AuCpup_RENAME (1 << 2) /* rename after cpup */ -+#define AuCpup_HOPEN (1 << 3) /* call h_open_pre/post() in -+ cpup */ -+#define AuCpup_OVERWRITE (1 << 4) /* allow overwriting the -+ existing entry */ -+#define AuCpup_RWDST (1 << 5) /* force write target even if -+ the branch is marked as RO */ -+ -+#ifndef CONFIG_AUFS_BR_HFSPLUS -+#undef AuCpup_HOPEN -+#define AuCpup_HOPEN 0 -+#endif -+ -+#define au_ftest_cpup(flags, name) ((flags) & AuCpup_##name) -+#define au_fset_cpup(flags, name) \ -+ do { (flags) |= AuCpup_##name; } while (0) -+#define au_fclr_cpup(flags, name) \ -+ do { (flags) &= ~AuCpup_##name; } while (0) -+ -+int au_copy_file(struct file *dst, struct file *src, loff_t len); -+int au_sio_cpup_simple(struct au_cp_generic *cpg); -+int au_sio_cpdown_simple(struct au_cp_generic *cpg); -+int au_sio_cpup_wh(struct au_cp_generic *cpg, struct file *file); -+ -+int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst, -+ int (*cp)(struct dentry *dentry, aufs_bindex_t bdst, -+ struct au_pin *pin, -+ struct dentry *h_parent, void *arg), -+ void *arg); -+int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst); -+int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst); -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* keep timestamps when copyup */ -+struct au_dtime { -+ struct dentry *dt_dentry; -+ struct path dt_h_path; -+ struct timespec64 dt_atime, dt_mtime; -+}; -+void au_dtime_store(struct au_dtime *dt, struct dentry *dentry, -+ struct path *h_path); -+void au_dtime_revert(struct au_dtime *dt); -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_CPUP_H__ */ -diff --git a/fs/aufs/dbgaufs.c b/fs/aufs/dbgaufs.c -new file mode 100644 -index 000000000000..63f40a324f1b ---- /dev/null -+++ b/fs/aufs/dbgaufs.c -@@ -0,0 +1,513 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * debugfs interface -+ */ -+ -+#include -+#include "aufs.h" -+ -+#ifndef CONFIG_SYSFS -+#error DEBUG_FS depends upon SYSFS -+#endif -+ -+static struct dentry *dbgaufs; -+static const mode_t dbgaufs_mode = 0444; -+ -+/* 20 is max digits length of ulong 64 */ -+struct dbgaufs_arg { -+ int n; -+ char a[20 * 4]; -+}; -+ -+/* -+ * common function for all XINO files -+ */ -+static int dbgaufs_xi_release(struct inode *inode __maybe_unused, -+ struct file *file) -+{ -+ void *p; -+ -+ p = file->private_data; -+ if (p) { -+ /* this is struct dbgaufs_arg */ -+ AuDebugOn(!au_kfree_sz_test(p)); -+ au_kfree_do_rcu(p); -+ } -+ return 0; -+} -+ -+static int dbgaufs_xi_open(struct file *xf, struct file *file, int do_fcnt, -+ int cnt) -+{ -+ int err; -+ struct kstat st; -+ struct dbgaufs_arg *p; -+ -+ err = -ENOMEM; -+ p = kmalloc(sizeof(*p), GFP_NOFS); -+ if (unlikely(!p)) -+ goto out; -+ -+ err = 0; -+ p->n = 0; -+ file->private_data = p; -+ if (!xf) -+ goto out; -+ -+ err = vfsub_getattr(&xf->f_path, &st); -+ if (!err) { -+ if (do_fcnt) -+ p->n = snprintf -+ (p->a, sizeof(p->a), "%d, %llux%u %lld\n", -+ cnt, st.blocks, st.blksize, -+ (long long)st.size); -+ else -+ p->n = snprintf(p->a, sizeof(p->a), "%llux%u %lld\n", -+ st.blocks, st.blksize, -+ (long long)st.size); -+ AuDebugOn(p->n >= sizeof(p->a)); -+ } else { -+ p->n = snprintf(p->a, sizeof(p->a), "err %d\n", err); -+ err = 0; -+ } -+ -+out: -+ return err; -+} -+ -+static ssize_t dbgaufs_xi_read(struct file *file, char __user *buf, -+ size_t count, loff_t *ppos) -+{ -+ struct dbgaufs_arg *p; -+ -+ p = file->private_data; -+ return simple_read_from_buffer(buf, count, ppos, p->a, p->n); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct dbgaufs_plink_arg { -+ int n; -+ char a[]; -+}; -+ -+static int dbgaufs_plink_release(struct inode *inode __maybe_unused, -+ struct file *file) -+{ -+ free_page((unsigned long)file->private_data); -+ return 0; -+} -+ -+static int dbgaufs_plink_open(struct inode *inode, struct file *file) -+{ -+ int err, i, limit; -+ unsigned long n, sum; -+ struct dbgaufs_plink_arg *p; -+ struct au_sbinfo *sbinfo; -+ struct super_block *sb; -+ struct hlist_bl_head *hbl; -+ -+ err = -ENOMEM; -+ p = (void *)get_zeroed_page(GFP_NOFS); -+ if (unlikely(!p)) -+ goto out; -+ -+ err = -EFBIG; -+ sbinfo = inode->i_private; -+ sb = sbinfo->si_sb; -+ si_noflush_read_lock(sb); -+ if (au_opt_test(au_mntflags(sb), PLINK)) { -+ limit = PAGE_SIZE - sizeof(p->n); -+ -+ /* the number of buckets */ -+ n = snprintf(p->a + p->n, limit, "%d\n", AuPlink_NHASH); -+ p->n += n; -+ limit -= n; -+ -+ sum = 0; -+ for (i = 0, hbl = sbinfo->si_plink; i < AuPlink_NHASH; -+ i++, hbl++) { -+ n = au_hbl_count(hbl); -+ sum += n; -+ -+ n = snprintf(p->a + p->n, limit, "%lu ", n); -+ p->n += n; -+ limit -= n; -+ if (unlikely(limit <= 0)) -+ goto out_free; -+ } -+ p->a[p->n - 1] = '\n'; -+ -+ /* the sum of plinks */ -+ n = snprintf(p->a + p->n, limit, "%lu\n", sum); -+ p->n += n; -+ limit -= n; -+ if (unlikely(limit <= 0)) -+ goto out_free; -+ } else { -+#define str "1\n0\n0\n" -+ p->n = sizeof(str) - 1; -+ strcpy(p->a, str); -+#undef str -+ } -+ si_read_unlock(sb); -+ -+ err = 0; -+ file->private_data = p; -+ goto out; /* success */ -+ -+out_free: -+ free_page((unsigned long)p); -+out: -+ return err; -+} -+ -+static ssize_t dbgaufs_plink_read(struct file *file, char __user *buf, -+ size_t count, loff_t *ppos) -+{ -+ struct dbgaufs_plink_arg *p; -+ -+ p = file->private_data; -+ return simple_read_from_buffer(buf, count, ppos, p->a, p->n); -+} -+ -+static const struct file_operations dbgaufs_plink_fop = { -+ .owner = THIS_MODULE, -+ .open = dbgaufs_plink_open, -+ .release = dbgaufs_plink_release, -+ .read = dbgaufs_plink_read -+}; -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int dbgaufs_xib_open(struct inode *inode, struct file *file) -+{ -+ int err; -+ struct au_sbinfo *sbinfo; -+ struct super_block *sb; -+ -+ sbinfo = inode->i_private; -+ sb = sbinfo->si_sb; -+ si_noflush_read_lock(sb); -+ err = dbgaufs_xi_open(sbinfo->si_xib, file, /*do_fcnt*/0, /*cnt*/0); -+ si_read_unlock(sb); -+ return err; -+} -+ -+static const struct file_operations dbgaufs_xib_fop = { -+ .owner = THIS_MODULE, -+ .open = dbgaufs_xib_open, -+ .release = dbgaufs_xi_release, -+ .read = dbgaufs_xi_read -+}; -+ -+/* ---------------------------------------------------------------------- */ -+ -+#define DbgaufsXi_PREFIX "xi" -+ -+static int dbgaufs_xino_open(struct inode *inode, struct file *file) -+{ -+ int err, idx; -+ long l; -+ aufs_bindex_t bindex; -+ char *p, a[sizeof(DbgaufsXi_PREFIX) + 8]; -+ struct au_sbinfo *sbinfo; -+ struct super_block *sb; -+ struct au_xino *xi; -+ struct file *xf; -+ struct qstr *name; -+ struct au_branch *br; -+ -+ err = -ENOENT; -+ name = &file->f_path.dentry->d_name; -+ if (unlikely(name->len < sizeof(DbgaufsXi_PREFIX) -+ || memcmp(name->name, DbgaufsXi_PREFIX, -+ sizeof(DbgaufsXi_PREFIX) - 1))) -+ goto out; -+ -+ AuDebugOn(name->len >= sizeof(a)); -+ memcpy(a, name->name, name->len); -+ a[name->len] = '\0'; -+ p = strchr(a, '-'); -+ if (p) -+ *p = '\0'; -+ err = kstrtol(a + sizeof(DbgaufsXi_PREFIX) - 1, 10, &l); -+ if (unlikely(err)) -+ goto out; -+ bindex = l; -+ idx = 0; -+ if (p) { -+ err = kstrtol(p + 1, 10, &l); -+ if (unlikely(err)) -+ goto out; -+ idx = l; -+ } -+ -+ err = -ENOENT; -+ sbinfo = inode->i_private; -+ sb = sbinfo->si_sb; -+ si_noflush_read_lock(sb); -+ if (unlikely(bindex < 0 || bindex > au_sbbot(sb))) -+ goto out_si; -+ br = au_sbr(sb, bindex); -+ xi = br->br_xino; -+ if (unlikely(idx >= xi->xi_nfile)) -+ goto out_si; -+ xf = au_xino_file(xi, idx); -+ if (xf) -+ err = dbgaufs_xi_open(xf, file, /*do_fcnt*/1, -+ au_xino_count(br)); -+ -+out_si: -+ si_read_unlock(sb); -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+static const struct file_operations dbgaufs_xino_fop = { -+ .owner = THIS_MODULE, -+ .open = dbgaufs_xino_open, -+ .release = dbgaufs_xi_release, -+ .read = dbgaufs_xi_read -+}; -+ -+void dbgaufs_xino_del(struct au_branch *br) -+{ -+ struct dentry *dbgaufs; -+ -+ dbgaufs = br->br_dbgaufs; -+ if (!dbgaufs) -+ return; -+ -+ br->br_dbgaufs = NULL; -+ /* debugfs acquires the parent i_mutex */ -+ lockdep_off(); -+ debugfs_remove(dbgaufs); -+ lockdep_on(); -+} -+ -+void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex) -+{ -+ aufs_bindex_t bbot; -+ struct au_branch *br; -+ -+ if (!au_sbi(sb)->si_dbgaufs) -+ return; -+ -+ bbot = au_sbbot(sb); -+ for (; bindex <= bbot; bindex++) { -+ br = au_sbr(sb, bindex); -+ dbgaufs_xino_del(br); -+ } -+} -+ -+static void dbgaufs_br_do_add(struct super_block *sb, aufs_bindex_t bindex, -+ unsigned int idx, struct dentry *parent, -+ struct au_sbinfo *sbinfo) -+{ -+ struct au_branch *br; -+ struct dentry *d; -+ /* "xi" bindex(5) "-" idx(2) NULL */ -+ char name[sizeof(DbgaufsXi_PREFIX) + 8]; -+ -+ if (!idx) -+ snprintf(name, sizeof(name), DbgaufsXi_PREFIX "%d", bindex); -+ else -+ snprintf(name, sizeof(name), DbgaufsXi_PREFIX "%d-%u", -+ bindex, idx); -+ br = au_sbr(sb, bindex); -+ if (br->br_dbgaufs) { -+ struct qstr qstr = QSTR_INIT(name, strlen(name)); -+ -+ if (!au_qstreq(&br->br_dbgaufs->d_name, &qstr)) { -+ /* debugfs acquires the parent i_mutex */ -+ lockdep_off(); -+ d = debugfs_rename(parent, br->br_dbgaufs, parent, -+ name); -+ lockdep_on(); -+ if (unlikely(!d)) -+ pr_warn("failed renaming %pd/%s, ignored.\n", -+ parent, name); -+ } -+ } else { -+ lockdep_off(); -+ br->br_dbgaufs = debugfs_create_file(name, dbgaufs_mode, parent, -+ sbinfo, &dbgaufs_xino_fop); -+ lockdep_on(); -+ if (unlikely(!br->br_dbgaufs)) -+ pr_warn("failed creating %pd/%s, ignored.\n", -+ parent, name); -+ } -+} -+ -+static void dbgaufs_br_add(struct super_block *sb, aufs_bindex_t bindex, -+ struct dentry *parent, struct au_sbinfo *sbinfo) -+{ -+ struct au_branch *br; -+ struct au_xino *xi; -+ unsigned int u; -+ -+ br = au_sbr(sb, bindex); -+ xi = br->br_xino; -+ for (u = 0; u < xi->xi_nfile; u++) -+ dbgaufs_br_do_add(sb, bindex, u, parent, sbinfo); -+} -+ -+void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex, int topdown) -+{ -+ struct au_sbinfo *sbinfo; -+ struct dentry *parent; -+ aufs_bindex_t bbot; -+ -+ if (!au_opt_test(au_mntflags(sb), XINO)) -+ return; -+ -+ sbinfo = au_sbi(sb); -+ parent = sbinfo->si_dbgaufs; -+ if (!parent) -+ return; -+ -+ bbot = au_sbbot(sb); -+ if (topdown) -+ for (; bindex <= bbot; bindex++) -+ dbgaufs_br_add(sb, bindex, parent, sbinfo); -+ else -+ for (; bbot >= bindex; bbot--) -+ dbgaufs_br_add(sb, bbot, parent, sbinfo); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+#ifdef CONFIG_AUFS_EXPORT -+static int dbgaufs_xigen_open(struct inode *inode, struct file *file) -+{ -+ int err; -+ struct au_sbinfo *sbinfo; -+ struct super_block *sb; -+ -+ sbinfo = inode->i_private; -+ sb = sbinfo->si_sb; -+ si_noflush_read_lock(sb); -+ err = dbgaufs_xi_open(sbinfo->si_xigen, file, /*do_fcnt*/0, /*cnt*/0); -+ si_read_unlock(sb); -+ return err; -+} -+ -+static const struct file_operations dbgaufs_xigen_fop = { -+ .owner = THIS_MODULE, -+ .open = dbgaufs_xigen_open, -+ .release = dbgaufs_xi_release, -+ .read = dbgaufs_xi_read -+}; -+ -+static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo) -+{ -+ int err; -+ -+ /* -+ * This function is a dynamic '__init' function actually, -+ * so the tiny check for si_rwsem is unnecessary. -+ */ -+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */ -+ -+ err = -EIO; -+ sbinfo->si_dbgaufs_xigen = debugfs_create_file -+ ("xigen", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo, -+ &dbgaufs_xigen_fop); -+ if (sbinfo->si_dbgaufs_xigen) -+ err = 0; -+ -+ return err; -+} -+#else -+static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo) -+{ -+ return 0; -+} -+#endif /* CONFIG_AUFS_EXPORT */ -+ -+/* ---------------------------------------------------------------------- */ -+ -+void dbgaufs_si_fin(struct au_sbinfo *sbinfo) -+{ -+ /* -+ * This function is a dynamic '__fin' function actually, -+ * so the tiny check for si_rwsem is unnecessary. -+ */ -+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */ -+ -+ debugfs_remove_recursive(sbinfo->si_dbgaufs); -+ sbinfo->si_dbgaufs = NULL; -+} -+ -+int dbgaufs_si_init(struct au_sbinfo *sbinfo) -+{ -+ int err; -+ char name[SysaufsSiNameLen]; -+ -+ /* -+ * This function is a dynamic '__init' function actually, -+ * so the tiny check for si_rwsem is unnecessary. -+ */ -+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */ -+ -+ err = -ENOENT; -+ if (!dbgaufs) { -+ AuErr1("/debug/aufs is uninitialized\n"); -+ goto out; -+ } -+ -+ err = -EIO; -+ sysaufs_name(sbinfo, name); -+ sbinfo->si_dbgaufs = debugfs_create_dir(name, dbgaufs); -+ if (unlikely(!sbinfo->si_dbgaufs)) -+ goto out; -+ -+ /* regardless plink/noplink option */ -+ sbinfo->si_dbgaufs_plink = debugfs_create_file -+ ("plink", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo, -+ &dbgaufs_plink_fop); -+ if (unlikely(!sbinfo->si_dbgaufs_plink)) -+ goto out_dir; -+ -+ /* regardless xino/noxino option */ -+ sbinfo->si_dbgaufs_xib = debugfs_create_file -+ ("xib", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo, -+ &dbgaufs_xib_fop); -+ if (unlikely(!sbinfo->si_dbgaufs_xib)) -+ goto out_dir; -+ -+ err = dbgaufs_xigen_init(sbinfo); -+ if (!err) -+ goto out; /* success */ -+ -+out_dir: -+ dbgaufs_si_fin(sbinfo); -+out: -+ if (unlikely(err)) -+ pr_err("debugfs/aufs failed\n"); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+void dbgaufs_fin(void) -+{ -+ debugfs_remove(dbgaufs); -+} -+ -+int __init dbgaufs_init(void) -+{ -+ int err; -+ -+ err = -EIO; -+ dbgaufs = debugfs_create_dir(AUFS_NAME, NULL); -+ if (dbgaufs) -+ err = 0; -+ return err; -+} -diff --git a/fs/aufs/dbgaufs.h b/fs/aufs/dbgaufs.h -new file mode 100644 -index 000000000000..ad26624a9345 ---- /dev/null -+++ b/fs/aufs/dbgaufs.h -@@ -0,0 +1,40 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * debugfs interface -+ */ -+ -+#ifndef __DBGAUFS_H__ -+#define __DBGAUFS_H__ -+ -+#ifdef __KERNEL__ -+ -+struct super_block; -+struct au_sbinfo; -+struct au_branch; -+ -+#ifdef CONFIG_DEBUG_FS -+/* dbgaufs.c */ -+void dbgaufs_xino_del(struct au_branch *br); -+void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex); -+void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex, int topdown); -+void dbgaufs_si_fin(struct au_sbinfo *sbinfo); -+int dbgaufs_si_init(struct au_sbinfo *sbinfo); -+void dbgaufs_fin(void); -+int __init dbgaufs_init(void); -+#else -+AuStubVoid(dbgaufs_xino_del, struct au_branch *br) -+AuStubVoid(dbgaufs_brs_del, struct super_block *sb, aufs_bindex_t bindex) -+AuStubVoid(dbgaufs_brs_add, struct super_block *sb, aufs_bindex_t bindex, -+ int topdown) -+AuStubVoid(dbgaufs_si_fin, struct au_sbinfo *sbinfo) -+AuStubInt0(dbgaufs_si_init, struct au_sbinfo *sbinfo) -+AuStubVoid(dbgaufs_fin, void) -+AuStubInt0(__init dbgaufs_init, void) -+#endif /* CONFIG_DEBUG_FS */ -+ -+#endif /* __KERNEL__ */ -+#endif /* __DBGAUFS_H__ */ -diff --git a/fs/aufs/dcsub.c b/fs/aufs/dcsub.c -new file mode 100644 -index 000000000000..000854da9075 ---- /dev/null -+++ b/fs/aufs/dcsub.c -@@ -0,0 +1,212 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * sub-routines for dentry cache -+ */ -+ -+#include "aufs.h" -+ -+static void au_dpage_free(struct au_dpage *dpage) -+{ -+ int i; -+ struct dentry **p; -+ -+ p = dpage->dentries; -+ for (i = 0; i < dpage->ndentry; i++) -+ dput(*p++); -+ free_page((unsigned long)dpage->dentries); -+} -+ -+int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp) -+{ -+ int err; -+ void *p; -+ -+ err = -ENOMEM; -+ dpages->dpages = kmalloc(sizeof(*dpages->dpages), gfp); -+ if (unlikely(!dpages->dpages)) -+ goto out; -+ -+ p = (void *)__get_free_page(gfp); -+ if (unlikely(!p)) -+ goto out_dpages; -+ -+ dpages->dpages[0].ndentry = 0; -+ dpages->dpages[0].dentries = p; -+ dpages->ndpage = 1; -+ return 0; /* success */ -+ -+out_dpages: -+ au_kfree_try_rcu(dpages->dpages); -+out: -+ return err; -+} -+ -+void au_dpages_free(struct au_dcsub_pages *dpages) -+{ -+ int i; -+ struct au_dpage *p; -+ -+ p = dpages->dpages; -+ for (i = 0; i < dpages->ndpage; i++) -+ au_dpage_free(p++); -+ au_kfree_try_rcu(dpages->dpages); -+} -+ -+static int au_dpages_append(struct au_dcsub_pages *dpages, -+ struct dentry *dentry, gfp_t gfp) -+{ -+ int err, sz; -+ struct au_dpage *dpage; -+ void *p; -+ -+ dpage = dpages->dpages + dpages->ndpage - 1; -+ sz = PAGE_SIZE / sizeof(dentry); -+ if (unlikely(dpage->ndentry >= sz)) { -+ AuLabel(new dpage); -+ err = -ENOMEM; -+ sz = dpages->ndpage * sizeof(*dpages->dpages); -+ p = au_kzrealloc(dpages->dpages, sz, -+ sz + sizeof(*dpages->dpages), gfp, -+ /*may_shrink*/0); -+ if (unlikely(!p)) -+ goto out; -+ -+ dpages->dpages = p; -+ dpage = dpages->dpages + dpages->ndpage; -+ p = (void *)__get_free_page(gfp); -+ if (unlikely(!p)) -+ goto out; -+ -+ dpage->ndentry = 0; -+ dpage->dentries = p; -+ dpages->ndpage++; -+ } -+ -+ AuDebugOn(au_dcount(dentry) <= 0); -+ dpage->dentries[dpage->ndentry++] = dget_dlock(dentry); -+ return 0; /* success */ -+ -+out: -+ return err; -+} -+ -+/* todo: BAD approach */ -+/* copied from linux/fs/dcache.c */ -+enum d_walk_ret { -+ D_WALK_CONTINUE, -+ D_WALK_QUIT, -+ D_WALK_NORETRY, -+ D_WALK_SKIP, -+}; -+ -+extern void d_walk(struct dentry *parent, void *data, -+ enum d_walk_ret (*enter)(void *, struct dentry *)); -+ -+struct ac_dpages_arg { -+ int err; -+ struct au_dcsub_pages *dpages; -+ struct super_block *sb; -+ au_dpages_test test; -+ void *arg; -+}; -+ -+static enum d_walk_ret au_call_dpages_append(void *_arg, struct dentry *dentry) -+{ -+ enum d_walk_ret ret; -+ struct ac_dpages_arg *arg = _arg; -+ -+ ret = D_WALK_CONTINUE; -+ if (dentry->d_sb == arg->sb -+ && !IS_ROOT(dentry) -+ && au_dcount(dentry) > 0 -+ && au_di(dentry) -+ && (!arg->test || arg->test(dentry, arg->arg))) { -+ arg->err = au_dpages_append(arg->dpages, dentry, GFP_ATOMIC); -+ if (unlikely(arg->err)) -+ ret = D_WALK_QUIT; -+ } -+ -+ return ret; -+} -+ -+int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root, -+ au_dpages_test test, void *arg) -+{ -+ struct ac_dpages_arg args = { -+ .err = 0, -+ .dpages = dpages, -+ .sb = root->d_sb, -+ .test = test, -+ .arg = arg -+ }; -+ -+ d_walk(root, &args, au_call_dpages_append); -+ -+ return args.err; -+} -+ -+int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry, -+ int do_include, au_dpages_test test, void *arg) -+{ -+ int err; -+ -+ err = 0; -+ write_seqlock(&rename_lock); -+ spin_lock(&dentry->d_lock); -+ if (do_include -+ && au_dcount(dentry) > 0 -+ && (!test || test(dentry, arg))) -+ err = au_dpages_append(dpages, dentry, GFP_ATOMIC); -+ spin_unlock(&dentry->d_lock); -+ if (unlikely(err)) -+ goto out; -+ -+ /* -+ * RCU for vfsmount is unnecessary since this is a traverse in a single -+ * mount -+ */ -+ while (!IS_ROOT(dentry)) { -+ dentry = dentry->d_parent; /* rename_lock is locked */ -+ spin_lock(&dentry->d_lock); -+ if (au_dcount(dentry) > 0 -+ && (!test || test(dentry, arg))) -+ err = au_dpages_append(dpages, dentry, GFP_ATOMIC); -+ spin_unlock(&dentry->d_lock); -+ if (unlikely(err)) -+ break; -+ } -+ -+out: -+ write_sequnlock(&rename_lock); -+ return err; -+} -+ -+static inline int au_dcsub_dpages_aufs(struct dentry *dentry, void *arg) -+{ -+ return au_di(dentry) && dentry->d_sb == arg; -+} -+ -+int au_dcsub_pages_rev_aufs(struct au_dcsub_pages *dpages, -+ struct dentry *dentry, int do_include) -+{ -+ return au_dcsub_pages_rev(dpages, dentry, do_include, -+ au_dcsub_dpages_aufs, dentry->d_sb); -+} -+ -+int au_test_subdir(struct dentry *d1, struct dentry *d2) -+{ -+ struct path path[2] = { -+ { -+ .dentry = d1 -+ }, -+ { -+ .dentry = d2 -+ } -+ }; -+ -+ return path_is_under(path + 0, path + 1); -+} -diff --git a/fs/aufs/dcsub.h b/fs/aufs/dcsub.h -new file mode 100644 -index 000000000000..9d207c2b4666 ---- /dev/null -+++ b/fs/aufs/dcsub.h -@@ -0,0 +1,124 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * sub-routines for dentry cache -+ */ -+ -+#ifndef __AUFS_DCSUB_H__ -+#define __AUFS_DCSUB_H__ -+ -+#ifdef __KERNEL__ -+ -+#include -+#include -+ -+struct au_dpage { -+ int ndentry; -+ struct dentry **dentries; -+}; -+ -+struct au_dcsub_pages { -+ int ndpage; -+ struct au_dpage *dpages; -+}; -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* dcsub.c */ -+int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp); -+void au_dpages_free(struct au_dcsub_pages *dpages); -+typedef int (*au_dpages_test)(struct dentry *dentry, void *arg); -+int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root, -+ au_dpages_test test, void *arg); -+int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry, -+ int do_include, au_dpages_test test, void *arg); -+int au_dcsub_pages_rev_aufs(struct au_dcsub_pages *dpages, -+ struct dentry *dentry, int do_include); -+int au_test_subdir(struct dentry *d1, struct dentry *d2); -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * todo: in linux-3.13, several similar (but faster) helpers are added to -+ * include/linux/dcache.h. Try them (in the future). -+ */ -+ -+static inline int au_d_hashed_positive(struct dentry *d) -+{ -+ int err; -+ struct inode *inode = d_inode(d); -+ -+ err = 0; -+ if (unlikely(d_unhashed(d) -+ || d_is_negative(d) -+ || !inode->i_nlink)) -+ err = -ENOENT; -+ return err; -+} -+ -+static inline int au_d_linkable(struct dentry *d) -+{ -+ int err; -+ struct inode *inode = d_inode(d); -+ -+ err = au_d_hashed_positive(d); -+ if (err -+ && d_is_positive(d) -+ && (inode->i_state & I_LINKABLE)) -+ err = 0; -+ return err; -+} -+ -+static inline int au_d_alive(struct dentry *d) -+{ -+ int err; -+ struct inode *inode; -+ -+ err = 0; -+ if (!IS_ROOT(d)) -+ err = au_d_hashed_positive(d); -+ else { -+ inode = d_inode(d); -+ if (unlikely(d_unlinked(d) -+ || d_is_negative(d) -+ || !inode->i_nlink)) -+ err = -ENOENT; -+ } -+ return err; -+} -+ -+static inline int au_alive_dir(struct dentry *d) -+{ -+ int err; -+ -+ err = au_d_alive(d); -+ if (unlikely(err || IS_DEADDIR(d_inode(d)))) -+ err = -ENOENT; -+ return err; -+} -+ -+static inline int au_qstreq(struct qstr *a, struct qstr *b) -+{ -+ return a->len == b->len -+ && !memcmp(a->name, b->name, a->len); -+} -+ -+/* -+ * by the commit -+ * 360f547 2015-01-25 dcache: let the dentry count go down to zero without -+ * taking d_lock -+ * the type of d_lockref.count became int, but the inlined function d_count() -+ * still returns unsigned int. -+ * I don't know why. Maybe it is for every d_count() users? -+ * Anyway au_dcount() lives on. -+ */ -+static inline int au_dcount(struct dentry *d) -+{ -+ return (int)d_count(d); -+} -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_DCSUB_H__ */ -diff --git a/fs/aufs/debug.c b/fs/aufs/debug.c -new file mode 100644 -index 000000000000..fd0ba9d15742 ---- /dev/null -+++ b/fs/aufs/debug.c -@@ -0,0 +1,428 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * debug print functions -+ */ -+ -+#include -+#include "aufs.h" -+ -+/* Returns 0, or -errno. arg is in kp->arg. */ -+static int param_atomic_t_set(const char *val, const struct kernel_param *kp) -+{ -+ int err, n; -+ -+ err = kstrtoint(val, 0, &n); -+ if (!err) { -+ if (n > 0) -+ au_debug_on(); -+ else -+ au_debug_off(); -+ } -+ return err; -+} -+ -+/* Returns length written or -errno. Buffer is 4k (ie. be short!) */ -+static int param_atomic_t_get(char *buffer, const struct kernel_param *kp) -+{ -+ atomic_t *a; -+ -+ a = kp->arg; -+ return sprintf(buffer, "%d", atomic_read(a)); -+} -+ -+static struct kernel_param_ops param_ops_atomic_t = { -+ .set = param_atomic_t_set, -+ .get = param_atomic_t_get -+ /* void (*free)(void *arg) */ -+}; -+ -+atomic_t aufs_debug = ATOMIC_INIT(0); -+MODULE_PARM_DESC(debug, "debug print"); -+module_param_named(debug, aufs_debug, atomic_t, 0664); -+ -+DEFINE_MUTEX(au_dbg_mtx); /* just to serialize the dbg msgs */ -+char *au_plevel = KERN_DEBUG; -+#define dpri(fmt, ...) do { \ -+ if ((au_plevel \ -+ && strcmp(au_plevel, KERN_DEBUG)) \ -+ || au_debug_test()) \ -+ printk("%s" fmt, au_plevel, ##__VA_ARGS__); \ -+} while (0) -+ -+/* ---------------------------------------------------------------------- */ -+ -+void au_dpri_whlist(struct au_nhash *whlist) -+{ -+ unsigned long ul, n; -+ struct hlist_head *head; -+ struct au_vdir_wh *pos; -+ -+ n = whlist->nh_num; -+ head = whlist->nh_head; -+ for (ul = 0; ul < n; ul++) { -+ hlist_for_each_entry(pos, head, wh_hash) -+ dpri("b%d, %.*s, %d\n", -+ pos->wh_bindex, -+ pos->wh_str.len, pos->wh_str.name, -+ pos->wh_str.len); -+ head++; -+ } -+} -+ -+void au_dpri_vdir(struct au_vdir *vdir) -+{ -+ unsigned long ul; -+ union au_vdir_deblk_p p; -+ unsigned char *o; -+ -+ if (!vdir || IS_ERR(vdir)) { -+ dpri("err %ld\n", PTR_ERR(vdir)); -+ return; -+ } -+ -+ dpri("deblk %u, nblk %lu, deblk %p, last{%lu, %p}, ver %llu\n", -+ vdir->vd_deblk_sz, vdir->vd_nblk, vdir->vd_deblk, -+ vdir->vd_last.ul, vdir->vd_last.p.deblk, vdir->vd_version); -+ for (ul = 0; ul < vdir->vd_nblk; ul++) { -+ p.deblk = vdir->vd_deblk[ul]; -+ o = p.deblk; -+ dpri("[%lu]: %p\n", ul, o); -+ } -+} -+ -+static int do_pri_inode(aufs_bindex_t bindex, struct inode *inode, int hn, -+ struct dentry *wh) -+{ -+ char *n = NULL; -+ int l = 0; -+ -+ if (!inode || IS_ERR(inode)) { -+ dpri("i%d: err %ld\n", bindex, PTR_ERR(inode)); -+ return -1; -+ } -+ -+ /* the type of i_blocks depends upon CONFIG_LBDAF */ -+ BUILD_BUG_ON(sizeof(inode->i_blocks) != sizeof(unsigned long) -+ && sizeof(inode->i_blocks) != sizeof(u64)); -+ if (wh) { -+ n = (void *)wh->d_name.name; -+ l = wh->d_name.len; -+ } -+ -+ dpri("i%d: %p, i%lu, %s, cnt %d, nl %u, 0%o, sz %llu, blk %llu," -+ " hn %d, ct %lld, np %lu, st 0x%lx, f 0x%x, v %llu, g %x%s%.*s\n", -+ bindex, inode, -+ inode->i_ino, inode->i_sb ? au_sbtype(inode->i_sb) : "??", -+ atomic_read(&inode->i_count), inode->i_nlink, inode->i_mode, -+ i_size_read(inode), (unsigned long long)inode->i_blocks, -+ hn, (long long)timespec64_to_ns(&inode->i_ctime) & 0x0ffff, -+ inode->i_mapping ? inode->i_mapping->nrpages : 0, -+ inode->i_state, inode->i_flags, inode_peek_iversion(inode), -+ inode->i_generation, -+ l ? ", wh " : "", l, n); -+ return 0; -+} -+ -+void au_dpri_inode(struct inode *inode) -+{ -+ struct au_iinfo *iinfo; -+ struct au_hinode *hi; -+ aufs_bindex_t bindex; -+ int err, hn; -+ -+ err = do_pri_inode(-1, inode, -1, NULL); -+ if (err || !au_test_aufs(inode->i_sb) || au_is_bad_inode(inode)) -+ return; -+ -+ iinfo = au_ii(inode); -+ dpri("i-1: btop %d, bbot %d, gen %d\n", -+ iinfo->ii_btop, iinfo->ii_bbot, au_iigen(inode, NULL)); -+ if (iinfo->ii_btop < 0) -+ return; -+ hn = 0; -+ for (bindex = iinfo->ii_btop; bindex <= iinfo->ii_bbot; bindex++) { -+ hi = au_hinode(iinfo, bindex); -+ hn = !!au_hn(hi); -+ do_pri_inode(bindex, hi->hi_inode, hn, hi->hi_whdentry); -+ } -+} -+ -+void au_dpri_dalias(struct inode *inode) -+{ -+ struct dentry *d; -+ -+ spin_lock(&inode->i_lock); -+ hlist_for_each_entry(d, &inode->i_dentry, d_u.d_alias) -+ au_dpri_dentry(d); -+ spin_unlock(&inode->i_lock); -+} -+ -+static int do_pri_dentry(aufs_bindex_t bindex, struct dentry *dentry) -+{ -+ struct dentry *wh = NULL; -+ int hn; -+ struct inode *inode; -+ struct au_iinfo *iinfo; -+ struct au_hinode *hi; -+ -+ if (!dentry || IS_ERR(dentry)) { -+ dpri("d%d: err %ld\n", bindex, PTR_ERR(dentry)); -+ return -1; -+ } -+ /* do not call dget_parent() here */ -+ /* note: access d_xxx without d_lock */ -+ dpri("d%d: %p, %pd2?, %s, cnt %d, flags 0x%x, %shashed\n", -+ bindex, dentry, dentry, -+ dentry->d_sb ? au_sbtype(dentry->d_sb) : "??", -+ au_dcount(dentry), dentry->d_flags, -+ d_unhashed(dentry) ? "un" : ""); -+ hn = -1; -+ inode = NULL; -+ if (d_is_positive(dentry)) -+ inode = d_inode(dentry); -+ if (inode -+ && au_test_aufs(dentry->d_sb) -+ && bindex >= 0 -+ && !au_is_bad_inode(inode)) { -+ iinfo = au_ii(inode); -+ hi = au_hinode(iinfo, bindex); -+ hn = !!au_hn(hi); -+ wh = hi->hi_whdentry; -+ } -+ do_pri_inode(bindex, inode, hn, wh); -+ return 0; -+} -+ -+void au_dpri_dentry(struct dentry *dentry) -+{ -+ struct au_dinfo *dinfo; -+ aufs_bindex_t bindex; -+ int err; -+ -+ err = do_pri_dentry(-1, dentry); -+ if (err || !au_test_aufs(dentry->d_sb)) -+ return; -+ -+ dinfo = au_di(dentry); -+ if (!dinfo) -+ return; -+ dpri("d-1: btop %d, bbot %d, bwh %d, bdiropq %d, gen %d, tmp %d\n", -+ dinfo->di_btop, dinfo->di_bbot, -+ dinfo->di_bwh, dinfo->di_bdiropq, au_digen(dentry), -+ dinfo->di_tmpfile); -+ if (dinfo->di_btop < 0) -+ return; -+ for (bindex = dinfo->di_btop; bindex <= dinfo->di_bbot; bindex++) -+ do_pri_dentry(bindex, au_hdentry(dinfo, bindex)->hd_dentry); -+} -+ -+static int do_pri_file(aufs_bindex_t bindex, struct file *file) -+{ -+ char a[32]; -+ -+ if (!file || IS_ERR(file)) { -+ dpri("f%d: err %ld\n", bindex, PTR_ERR(file)); -+ return -1; -+ } -+ a[0] = 0; -+ if (bindex < 0 -+ && !IS_ERR_OR_NULL(file->f_path.dentry) -+ && au_test_aufs(file->f_path.dentry->d_sb) -+ && au_fi(file)) -+ snprintf(a, sizeof(a), ", gen %d, mmapped %d", -+ au_figen(file), atomic_read(&au_fi(file)->fi_mmapped)); -+ dpri("f%d: mode 0x%x, flags 0%o, cnt %ld, v %llu, pos %llu%s\n", -+ bindex, file->f_mode, file->f_flags, (long)file_count(file), -+ file->f_version, file->f_pos, a); -+ if (!IS_ERR_OR_NULL(file->f_path.dentry)) -+ do_pri_dentry(bindex, file->f_path.dentry); -+ return 0; -+} -+ -+void au_dpri_file(struct file *file) -+{ -+ struct au_finfo *finfo; -+ struct au_fidir *fidir; -+ struct au_hfile *hfile; -+ aufs_bindex_t bindex; -+ int err; -+ -+ err = do_pri_file(-1, file); -+ if (err -+ || IS_ERR_OR_NULL(file->f_path.dentry) -+ || !au_test_aufs(file->f_path.dentry->d_sb)) -+ return; -+ -+ finfo = au_fi(file); -+ if (!finfo) -+ return; -+ if (finfo->fi_btop < 0) -+ return; -+ fidir = finfo->fi_hdir; -+ if (!fidir) -+ do_pri_file(finfo->fi_btop, finfo->fi_htop.hf_file); -+ else -+ for (bindex = finfo->fi_btop; -+ bindex >= 0 && bindex <= fidir->fd_bbot; -+ bindex++) { -+ hfile = fidir->fd_hfile + bindex; -+ do_pri_file(bindex, hfile ? hfile->hf_file : NULL); -+ } -+} -+ -+static int do_pri_br(aufs_bindex_t bindex, struct au_branch *br) -+{ -+ struct vfsmount *mnt; -+ struct super_block *sb; -+ -+ if (!br || IS_ERR(br)) -+ goto out; -+ mnt = au_br_mnt(br); -+ if (!mnt || IS_ERR(mnt)) -+ goto out; -+ sb = mnt->mnt_sb; -+ if (!sb || IS_ERR(sb)) -+ goto out; -+ -+ dpri("s%d: {perm 0x%x, id %d, wbr %p}, " -+ "%s, dev 0x%02x%02x, flags 0x%lx, cnt %d, active %d, " -+ "xino %d\n", -+ bindex, br->br_perm, br->br_id, br->br_wbr, -+ au_sbtype(sb), MAJOR(sb->s_dev), MINOR(sb->s_dev), -+ sb->s_flags, sb->s_count, -+ atomic_read(&sb->s_active), -+ !!au_xino_file(br->br_xino, /*idx*/-1)); -+ return 0; -+ -+out: -+ dpri("s%d: err %ld\n", bindex, PTR_ERR(br)); -+ return -1; -+} -+ -+void au_dpri_sb(struct super_block *sb) -+{ -+ struct au_sbinfo *sbinfo; -+ aufs_bindex_t bindex; -+ int err; -+ /* to reduce stack size */ -+ struct { -+ struct vfsmount mnt; -+ struct au_branch fake; -+ } *a; -+ -+ /* this function can be called from magic sysrq */ -+ a = kzalloc(sizeof(*a), GFP_ATOMIC); -+ if (unlikely(!a)) { -+ dpri("no memory\n"); -+ return; -+ } -+ -+ a->mnt.mnt_sb = sb; -+ a->fake.br_path.mnt = &a->mnt; -+ err = do_pri_br(-1, &a->fake); -+ au_kfree_rcu(a); -+ dpri("dev 0x%x\n", sb->s_dev); -+ if (err || !au_test_aufs(sb)) -+ return; -+ -+ sbinfo = au_sbi(sb); -+ if (!sbinfo) -+ return; -+ dpri("nw %d, gen %u, kobj %d\n", -+ atomic_read(&sbinfo->si_nowait.nw_len), sbinfo->si_generation, -+ kref_read(&sbinfo->si_kobj.kref)); -+ for (bindex = 0; bindex <= sbinfo->si_bbot; bindex++) -+ do_pri_br(bindex, sbinfo->si_branch[0 + bindex]); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+void __au_dbg_verify_dinode(struct dentry *dentry, const char *func, int line) -+{ -+ struct inode *h_inode, *inode = d_inode(dentry); -+ struct dentry *h_dentry; -+ aufs_bindex_t bindex, bbot, bi; -+ -+ if (!inode /* || au_di(dentry)->di_lsc == AuLsc_DI_TMP */) -+ return; -+ -+ bbot = au_dbbot(dentry); -+ bi = au_ibbot(inode); -+ if (bi < bbot) -+ bbot = bi; -+ bindex = au_dbtop(dentry); -+ bi = au_ibtop(inode); -+ if (bi > bindex) -+ bindex = bi; -+ -+ for (; bindex <= bbot; bindex++) { -+ h_dentry = au_h_dptr(dentry, bindex); -+ if (!h_dentry) -+ continue; -+ h_inode = au_h_iptr(inode, bindex); -+ if (unlikely(h_inode != d_inode(h_dentry))) { -+ au_debug_on(); -+ AuDbg("b%d, %s:%d\n", bindex, func, line); -+ AuDbgDentry(dentry); -+ AuDbgInode(inode); -+ au_debug_off(); -+ BUG(); -+ } -+ } -+} -+ -+void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen) -+{ -+ int err, i, j; -+ struct au_dcsub_pages dpages; -+ struct au_dpage *dpage; -+ struct dentry **dentries; -+ -+ err = au_dpages_init(&dpages, GFP_NOFS); -+ AuDebugOn(err); -+ err = au_dcsub_pages_rev_aufs(&dpages, parent, /*do_include*/1); -+ AuDebugOn(err); -+ for (i = dpages.ndpage - 1; !err && i >= 0; i--) { -+ dpage = dpages.dpages + i; -+ dentries = dpage->dentries; -+ for (j = dpage->ndentry - 1; !err && j >= 0; j--) -+ AuDebugOn(au_digen_test(dentries[j], sigen)); -+ } -+ au_dpages_free(&dpages); -+} -+ -+void au_dbg_verify_kthread(void) -+{ -+ if (au_wkq_test()) { -+ au_dbg_blocked(); -+ /* -+ * It may be recursive, but udba=notify between two aufs mounts, -+ * where a single ro branch is shared, is not a problem. -+ */ -+ /* WARN_ON(1); */ -+ } -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+int __init au_debug_init(void) -+{ -+ aufs_bindex_t bindex; -+ struct au_vdir_destr destr; -+ -+ bindex = -1; -+ AuDebugOn(bindex >= 0); -+ -+ destr.len = -1; -+ AuDebugOn(destr.len < NAME_MAX); -+ -+#ifdef CONFIG_4KSTACKS -+ pr_warn("CONFIG_4KSTACKS is defined.\n"); -+#endif -+ -+ return 0; -+} -diff --git a/fs/aufs/debug.h b/fs/aufs/debug.h -new file mode 100644 -index 000000000000..5799794de0c2 ---- /dev/null -+++ b/fs/aufs/debug.h -@@ -0,0 +1,213 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * debug print functions -+ */ -+ -+#ifndef __AUFS_DEBUG_H__ -+#define __AUFS_DEBUG_H__ -+ -+#ifdef __KERNEL__ -+ -+#include -+#include -+#include -+#include -+ -+#ifdef CONFIG_AUFS_DEBUG -+#define AuDebugOn(a) BUG_ON(a) -+ -+/* module parameter */ -+extern atomic_t aufs_debug; -+static inline void au_debug_on(void) -+{ -+ atomic_inc(&aufs_debug); -+} -+static inline void au_debug_off(void) -+{ -+ atomic_dec_if_positive(&aufs_debug); -+} -+ -+static inline int au_debug_test(void) -+{ -+ return atomic_read(&aufs_debug) > 0; -+} -+#else -+#define AuDebugOn(a) do {} while (0) -+AuStubVoid(au_debug_on, void) -+AuStubVoid(au_debug_off, void) -+AuStubInt0(au_debug_test, void) -+#endif /* CONFIG_AUFS_DEBUG */ -+ -+#define param_check_atomic_t(name, p) __param_check(name, p, atomic_t) -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* debug print */ -+ -+#define AuDbg(fmt, ...) do { \ -+ if (au_debug_test()) \ -+ pr_debug("DEBUG: " fmt, ##__VA_ARGS__); \ -+} while (0) -+#define AuLabel(l) AuDbg(#l "\n") -+#define AuIOErr(fmt, ...) pr_err("I/O Error, " fmt, ##__VA_ARGS__) -+#define AuWarn1(fmt, ...) do { \ -+ static unsigned char _c; \ -+ if (!_c++) \ -+ pr_warn(fmt, ##__VA_ARGS__); \ -+} while (0) -+ -+#define AuErr1(fmt, ...) do { \ -+ static unsigned char _c; \ -+ if (!_c++) \ -+ pr_err(fmt, ##__VA_ARGS__); \ -+} while (0) -+ -+#define AuIOErr1(fmt, ...) do { \ -+ static unsigned char _c; \ -+ if (!_c++) \ -+ AuIOErr(fmt, ##__VA_ARGS__); \ -+} while (0) -+ -+#define AuUnsupportMsg "This operation is not supported." \ -+ " Please report this application to aufs-users ML." -+#define AuUnsupport(fmt, ...) do { \ -+ pr_err(AuUnsupportMsg "\n" fmt, ##__VA_ARGS__); \ -+ dump_stack(); \ -+} while (0) -+ -+#define AuTraceErr(e) do { \ -+ if (unlikely((e) < 0)) \ -+ AuDbg("err %d\n", (int)(e)); \ -+} while (0) -+ -+#define AuTraceErrPtr(p) do { \ -+ if (IS_ERR(p)) \ -+ AuDbg("err %ld\n", PTR_ERR(p)); \ -+} while (0) -+ -+/* dirty macros for debug print, use with "%.*s" and caution */ -+#define AuLNPair(qstr) (qstr)->len, (qstr)->name -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct dentry; -+#ifdef CONFIG_AUFS_DEBUG -+extern struct mutex au_dbg_mtx; -+extern char *au_plevel; -+struct au_nhash; -+void au_dpri_whlist(struct au_nhash *whlist); -+struct au_vdir; -+void au_dpri_vdir(struct au_vdir *vdir); -+struct inode; -+void au_dpri_inode(struct inode *inode); -+void au_dpri_dalias(struct inode *inode); -+void au_dpri_dentry(struct dentry *dentry); -+struct file; -+void au_dpri_file(struct file *filp); -+struct super_block; -+void au_dpri_sb(struct super_block *sb); -+ -+#define au_dbg_verify_dinode(d) __au_dbg_verify_dinode(d, __func__, __LINE__) -+void __au_dbg_verify_dinode(struct dentry *dentry, const char *func, int line); -+void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen); -+void au_dbg_verify_kthread(void); -+ -+int __init au_debug_init(void); -+ -+#define AuDbgWhlist(w) do { \ -+ mutex_lock(&au_dbg_mtx); \ -+ AuDbg(#w "\n"); \ -+ au_dpri_whlist(w); \ -+ mutex_unlock(&au_dbg_mtx); \ -+} while (0) -+ -+#define AuDbgVdir(v) do { \ -+ mutex_lock(&au_dbg_mtx); \ -+ AuDbg(#v "\n"); \ -+ au_dpri_vdir(v); \ -+ mutex_unlock(&au_dbg_mtx); \ -+} while (0) -+ -+#define AuDbgInode(i) do { \ -+ mutex_lock(&au_dbg_mtx); \ -+ AuDbg(#i "\n"); \ -+ au_dpri_inode(i); \ -+ mutex_unlock(&au_dbg_mtx); \ -+} while (0) -+ -+#define AuDbgDAlias(i) do { \ -+ mutex_lock(&au_dbg_mtx); \ -+ AuDbg(#i "\n"); \ -+ au_dpri_dalias(i); \ -+ mutex_unlock(&au_dbg_mtx); \ -+} while (0) -+ -+#define AuDbgDentry(d) do { \ -+ mutex_lock(&au_dbg_mtx); \ -+ AuDbg(#d "\n"); \ -+ au_dpri_dentry(d); \ -+ mutex_unlock(&au_dbg_mtx); \ -+} while (0) -+ -+#define AuDbgFile(f) do { \ -+ mutex_lock(&au_dbg_mtx); \ -+ AuDbg(#f "\n"); \ -+ au_dpri_file(f); \ -+ mutex_unlock(&au_dbg_mtx); \ -+} while (0) -+ -+#define AuDbgSb(sb) do { \ -+ mutex_lock(&au_dbg_mtx); \ -+ AuDbg(#sb "\n"); \ -+ au_dpri_sb(sb); \ -+ mutex_unlock(&au_dbg_mtx); \ -+} while (0) -+ -+#define AuDbgSym(addr) do { \ -+ char sym[KSYM_SYMBOL_LEN]; \ -+ sprint_symbol(sym, (unsigned long)addr); \ -+ AuDbg("%s\n", sym); \ -+} while (0) -+#else -+AuStubVoid(au_dbg_verify_dinode, struct dentry *dentry) -+AuStubVoid(au_dbg_verify_gen, struct dentry *parent, unsigned int sigen) -+AuStubVoid(au_dbg_verify_kthread, void) -+AuStubInt0(__init au_debug_init, void) -+ -+#define AuDbgWhlist(w) do {} while (0) -+#define AuDbgVdir(v) do {} while (0) -+#define AuDbgInode(i) do {} while (0) -+#define AuDbgDAlias(i) do {} while (0) -+#define AuDbgDentry(d) do {} while (0) -+#define AuDbgFile(f) do {} while (0) -+#define AuDbgSb(sb) do {} while (0) -+#define AuDbgSym(addr) do {} while (0) -+#endif /* CONFIG_AUFS_DEBUG */ -+ -+/* ---------------------------------------------------------------------- */ -+ -+#ifdef CONFIG_AUFS_MAGIC_SYSRQ -+int __init au_sysrq_init(void); -+void au_sysrq_fin(void); -+ -+#ifdef CONFIG_HW_CONSOLE -+#define au_dbg_blocked() do { \ -+ WARN_ON(1); \ -+ handle_sysrq('w'); \ -+} while (0) -+#else -+AuStubVoid(au_dbg_blocked, void) -+#endif -+ -+#else -+AuStubInt0(__init au_sysrq_init, void) -+AuStubVoid(au_sysrq_fin, void) -+AuStubVoid(au_dbg_blocked, void) -+#endif /* CONFIG_AUFS_MAGIC_SYSRQ */ -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_DEBUG_H__ */ -diff --git a/fs/aufs/dentry.c b/fs/aufs/dentry.c -new file mode 100644 -index 000000000000..1a029193315a ---- /dev/null -+++ b/fs/aufs/dentry.c -@@ -0,0 +1,1141 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * lookup and dentry operations -+ */ -+ -+#include -+#include -+#include "aufs.h" -+ -+/* -+ * returns positive/negative dentry, NULL or an error. -+ * NULL means whiteout-ed or not-found. -+ */ -+static struct dentry* -+au_do_lookup(struct dentry *h_parent, struct dentry *dentry, -+ aufs_bindex_t bindex, struct au_do_lookup_args *args) -+{ -+ struct dentry *h_dentry; -+ struct inode *h_inode; -+ struct au_branch *br; -+ int wh_found, opq; -+ unsigned char wh_able; -+ const unsigned char allow_neg = !!au_ftest_lkup(args->flags, ALLOW_NEG); -+ const unsigned char ignore_perm = !!au_ftest_lkup(args->flags, -+ IGNORE_PERM); -+ -+ wh_found = 0; -+ br = au_sbr(dentry->d_sb, bindex); -+ wh_able = !!au_br_whable(br->br_perm); -+ if (wh_able) -+ wh_found = au_wh_test(h_parent, &args->whname, ignore_perm); -+ h_dentry = ERR_PTR(wh_found); -+ if (!wh_found) -+ goto real_lookup; -+ if (unlikely(wh_found < 0)) -+ goto out; -+ -+ /* We found a whiteout */ -+ /* au_set_dbbot(dentry, bindex); */ -+ au_set_dbwh(dentry, bindex); -+ if (!allow_neg) -+ return NULL; /* success */ -+ -+real_lookup: -+ if (!ignore_perm) -+ h_dentry = vfsub_lkup_one(args->name, h_parent); -+ else -+ h_dentry = au_sio_lkup_one(args->name, h_parent); -+ if (IS_ERR(h_dentry)) { -+ if (PTR_ERR(h_dentry) == -ENAMETOOLONG -+ && !allow_neg) -+ h_dentry = NULL; -+ goto out; -+ } -+ -+ h_inode = d_inode(h_dentry); -+ if (d_is_negative(h_dentry)) { -+ if (!allow_neg) -+ goto out_neg; -+ } else if (wh_found -+ || (args->type && args->type != (h_inode->i_mode & S_IFMT))) -+ goto out_neg; -+ else if (au_ftest_lkup(args->flags, DIRREN) -+ /* && h_inode */ -+ && !au_dr_lkup_h_ino(args, bindex, h_inode->i_ino)) { -+ AuDbg("b%d %pd ignored hi%llu\n", bindex, h_dentry, -+ (unsigned long long)h_inode->i_ino); -+ goto out_neg; -+ } -+ -+ if (au_dbbot(dentry) <= bindex) -+ au_set_dbbot(dentry, bindex); -+ if (au_dbtop(dentry) < 0 || bindex < au_dbtop(dentry)) -+ au_set_dbtop(dentry, bindex); -+ au_set_h_dptr(dentry, bindex, h_dentry); -+ -+ if (!d_is_dir(h_dentry) -+ || !wh_able -+ || (d_really_is_positive(dentry) && !d_is_dir(dentry))) -+ goto out; /* success */ -+ -+ inode_lock_shared_nested(h_inode, AuLsc_I_CHILD); -+ opq = au_diropq_test(h_dentry); -+ inode_unlock_shared(h_inode); -+ if (opq > 0) -+ au_set_dbdiropq(dentry, bindex); -+ else if (unlikely(opq < 0)) { -+ au_set_h_dptr(dentry, bindex, NULL); -+ h_dentry = ERR_PTR(opq); -+ } -+ goto out; -+ -+out_neg: -+ dput(h_dentry); -+ h_dentry = NULL; -+out: -+ return h_dentry; -+} -+ -+static int au_test_shwh(struct super_block *sb, const struct qstr *name) -+{ -+ if (unlikely(!au_opt_test(au_mntflags(sb), SHWH) -+ && !strncmp(name->name, AUFS_WH_PFX, AUFS_WH_PFX_LEN))) -+ return -EPERM; -+ return 0; -+} -+ -+/* -+ * returns the number of lower positive dentries, -+ * otherwise an error. -+ * can be called at unlinking with @type is zero. -+ */ -+int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t btop, -+ unsigned int flags) -+{ -+ int npositive, err; -+ aufs_bindex_t bindex, btail, bdiropq; -+ unsigned char isdir, dirperm1, dirren; -+ struct au_do_lookup_args args = { -+ .flags = flags, -+ .name = &dentry->d_name -+ }; -+ struct dentry *parent; -+ struct super_block *sb; -+ -+ sb = dentry->d_sb; -+ err = au_test_shwh(sb, args.name); -+ if (unlikely(err)) -+ goto out; -+ -+ err = au_wh_name_alloc(&args.whname, args.name); -+ if (unlikely(err)) -+ goto out; -+ -+ isdir = !!d_is_dir(dentry); -+ dirperm1 = !!au_opt_test(au_mntflags(sb), DIRPERM1); -+ dirren = !!au_opt_test(au_mntflags(sb), DIRREN); -+ if (dirren) -+ au_fset_lkup(args.flags, DIRREN); -+ -+ npositive = 0; -+ parent = dget_parent(dentry); -+ btail = au_dbtaildir(parent); -+ for (bindex = btop; bindex <= btail; bindex++) { -+ struct dentry *h_parent, *h_dentry; -+ struct inode *h_inode, *h_dir; -+ struct au_branch *br; -+ -+ h_dentry = au_h_dptr(dentry, bindex); -+ if (h_dentry) { -+ if (d_is_positive(h_dentry)) -+ npositive++; -+ break; -+ } -+ h_parent = au_h_dptr(parent, bindex); -+ if (!h_parent || !d_is_dir(h_parent)) -+ continue; -+ -+ if (dirren) { -+ /* if the inum matches, then use the prepared name */ -+ err = au_dr_lkup_name(&args, bindex); -+ if (unlikely(err)) -+ goto out_parent; -+ } -+ -+ h_dir = d_inode(h_parent); -+ inode_lock_shared_nested(h_dir, AuLsc_I_PARENT); -+ h_dentry = au_do_lookup(h_parent, dentry, bindex, &args); -+ inode_unlock_shared(h_dir); -+ err = PTR_ERR(h_dentry); -+ if (IS_ERR(h_dentry)) -+ goto out_parent; -+ if (h_dentry) -+ au_fclr_lkup(args.flags, ALLOW_NEG); -+ if (dirperm1) -+ au_fset_lkup(args.flags, IGNORE_PERM); -+ -+ if (au_dbwh(dentry) == bindex) -+ break; -+ if (!h_dentry) -+ continue; -+ if (d_is_negative(h_dentry)) -+ continue; -+ h_inode = d_inode(h_dentry); -+ npositive++; -+ if (!args.type) -+ args.type = h_inode->i_mode & S_IFMT; -+ if (args.type != S_IFDIR) -+ break; -+ else if (isdir) { -+ /* the type of lower may be different */ -+ bdiropq = au_dbdiropq(dentry); -+ if (bdiropq >= 0 && bdiropq <= bindex) -+ break; -+ } -+ br = au_sbr(sb, bindex); -+ if (dirren -+ && au_dr_hino_test_add(&br->br_dirren, h_inode->i_ino, -+ /*add_ent*/NULL)) { -+ /* prepare next name to lookup */ -+ err = au_dr_lkup(&args, dentry, bindex); -+ if (unlikely(err)) -+ goto out_parent; -+ } -+ } -+ -+ if (npositive) { -+ AuLabel(positive); -+ au_update_dbtop(dentry); -+ } -+ err = npositive; -+ if (unlikely(!au_opt_test(au_mntflags(sb), UDBA_NONE) -+ && au_dbtop(dentry) < 0)) { -+ err = -EIO; -+ AuIOErr("both of real entry and whiteout found, %pd, err %d\n", -+ dentry, err); -+ } -+ -+out_parent: -+ dput(parent); -+ au_kfree_try_rcu(args.whname.name); -+ if (dirren) -+ au_dr_lkup_fin(&args); -+out: -+ return err; -+} -+ -+struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent) -+{ -+ struct dentry *dentry; -+ int wkq_err; -+ -+ if (!au_test_h_perm_sio(d_inode(parent), MAY_EXEC)) -+ dentry = vfsub_lkup_one(name, parent); -+ else { -+ struct vfsub_lkup_one_args args = { -+ .errp = &dentry, -+ .name = name, -+ .parent = parent -+ }; -+ -+ wkq_err = au_wkq_wait(vfsub_call_lkup_one, &args); -+ if (unlikely(wkq_err)) -+ dentry = ERR_PTR(wkq_err); -+ } -+ -+ return dentry; -+} -+ -+/* -+ * lookup @dentry on @bindex which should be negative. -+ */ -+int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex, int wh) -+{ -+ int err; -+ struct dentry *parent, *h_parent, *h_dentry; -+ struct au_branch *br; -+ -+ parent = dget_parent(dentry); -+ h_parent = au_h_dptr(parent, bindex); -+ br = au_sbr(dentry->d_sb, bindex); -+ if (wh) -+ h_dentry = au_whtmp_lkup(h_parent, br, &dentry->d_name); -+ else -+ h_dentry = au_sio_lkup_one(&dentry->d_name, h_parent); -+ err = PTR_ERR(h_dentry); -+ if (IS_ERR(h_dentry)) -+ goto out; -+ if (unlikely(d_is_positive(h_dentry))) { -+ err = -EIO; -+ AuIOErr("%pd should be negative on b%d.\n", h_dentry, bindex); -+ dput(h_dentry); -+ goto out; -+ } -+ -+ err = 0; -+ if (bindex < au_dbtop(dentry)) -+ au_set_dbtop(dentry, bindex); -+ if (au_dbbot(dentry) < bindex) -+ au_set_dbbot(dentry, bindex); -+ au_set_h_dptr(dentry, bindex, h_dentry); -+ -+out: -+ dput(parent); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* subset of struct inode */ -+struct au_iattr { -+ unsigned long i_ino; -+ /* unsigned int i_nlink; */ -+ kuid_t i_uid; -+ kgid_t i_gid; -+ u64 i_version; -+/* -+ loff_t i_size; -+ blkcnt_t i_blocks; -+*/ -+ umode_t i_mode; -+}; -+ -+static void au_iattr_save(struct au_iattr *ia, struct inode *h_inode) -+{ -+ ia->i_ino = h_inode->i_ino; -+ /* ia->i_nlink = h_inode->i_nlink; */ -+ ia->i_uid = h_inode->i_uid; -+ ia->i_gid = h_inode->i_gid; -+ ia->i_version = inode_query_iversion(h_inode); -+/* -+ ia->i_size = h_inode->i_size; -+ ia->i_blocks = h_inode->i_blocks; -+*/ -+ ia->i_mode = (h_inode->i_mode & S_IFMT); -+} -+ -+static int au_iattr_test(struct au_iattr *ia, struct inode *h_inode) -+{ -+ return ia->i_ino != h_inode->i_ino -+ /* || ia->i_nlink != h_inode->i_nlink */ -+ || !uid_eq(ia->i_uid, h_inode->i_uid) -+ || !gid_eq(ia->i_gid, h_inode->i_gid) -+ || !inode_eq_iversion(h_inode, ia->i_version) -+/* -+ || ia->i_size != h_inode->i_size -+ || ia->i_blocks != h_inode->i_blocks -+*/ -+ || ia->i_mode != (h_inode->i_mode & S_IFMT); -+} -+ -+static int au_h_verify_dentry(struct dentry *h_dentry, struct dentry *h_parent, -+ struct au_branch *br) -+{ -+ int err; -+ struct au_iattr ia; -+ struct inode *h_inode; -+ struct dentry *h_d; -+ struct super_block *h_sb; -+ -+ err = 0; -+ memset(&ia, -1, sizeof(ia)); -+ h_sb = h_dentry->d_sb; -+ h_inode = NULL; -+ if (d_is_positive(h_dentry)) { -+ h_inode = d_inode(h_dentry); -+ au_iattr_save(&ia, h_inode); -+ } else if (au_test_nfs(h_sb) || au_test_fuse(h_sb)) -+ /* nfs d_revalidate may return 0 for negative dentry */ -+ /* fuse d_revalidate always return 0 for negative dentry */ -+ goto out; -+ -+ /* main purpose is namei.c:cached_lookup() and d_revalidate */ -+ h_d = vfsub_lkup_one(&h_dentry->d_name, h_parent); -+ err = PTR_ERR(h_d); -+ if (IS_ERR(h_d)) -+ goto out; -+ -+ err = 0; -+ if (unlikely(h_d != h_dentry -+ || d_inode(h_d) != h_inode -+ || (h_inode && au_iattr_test(&ia, h_inode)))) -+ err = au_busy_or_stale(); -+ dput(h_d); -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir, -+ struct dentry *h_parent, struct au_branch *br) -+{ -+ int err; -+ -+ err = 0; -+ if (udba == AuOpt_UDBA_REVAL -+ && !au_test_fs_remote(h_dentry->d_sb)) { -+ IMustLock(h_dir); -+ err = (d_inode(h_dentry->d_parent) != h_dir); -+ } else if (udba != AuOpt_UDBA_NONE) -+ err = au_h_verify_dentry(h_dentry, h_parent, br); -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int au_do_refresh_hdentry(struct dentry *dentry, struct dentry *parent) -+{ -+ int err; -+ aufs_bindex_t new_bindex, bindex, bbot, bwh, bdiropq; -+ struct au_hdentry tmp, *p, *q; -+ struct au_dinfo *dinfo; -+ struct super_block *sb; -+ -+ DiMustWriteLock(dentry); -+ -+ sb = dentry->d_sb; -+ dinfo = au_di(dentry); -+ bbot = dinfo->di_bbot; -+ bwh = dinfo->di_bwh; -+ bdiropq = dinfo->di_bdiropq; -+ bindex = dinfo->di_btop; -+ p = au_hdentry(dinfo, bindex); -+ for (; bindex <= bbot; bindex++, p++) { -+ if (!p->hd_dentry) -+ continue; -+ -+ new_bindex = au_br_index(sb, p->hd_id); -+ if (new_bindex == bindex) -+ continue; -+ -+ if (dinfo->di_bwh == bindex) -+ bwh = new_bindex; -+ if (dinfo->di_bdiropq == bindex) -+ bdiropq = new_bindex; -+ if (new_bindex < 0) { -+ au_hdput(p); -+ p->hd_dentry = NULL; -+ continue; -+ } -+ -+ /* swap two lower dentries, and loop again */ -+ q = au_hdentry(dinfo, new_bindex); -+ tmp = *q; -+ *q = *p; -+ *p = tmp; -+ if (tmp.hd_dentry) { -+ bindex--; -+ p--; -+ } -+ } -+ -+ dinfo->di_bwh = -1; -+ if (bwh >= 0 && bwh <= au_sbbot(sb) && au_sbr_whable(sb, bwh)) -+ dinfo->di_bwh = bwh; -+ -+ dinfo->di_bdiropq = -1; -+ if (bdiropq >= 0 -+ && bdiropq <= au_sbbot(sb) -+ && au_sbr_whable(sb, bdiropq)) -+ dinfo->di_bdiropq = bdiropq; -+ -+ err = -EIO; -+ dinfo->di_btop = -1; -+ dinfo->di_bbot = -1; -+ bbot = au_dbbot(parent); -+ bindex = 0; -+ p = au_hdentry(dinfo, bindex); -+ for (; bindex <= bbot; bindex++, p++) -+ if (p->hd_dentry) { -+ dinfo->di_btop = bindex; -+ break; -+ } -+ -+ if (dinfo->di_btop >= 0) { -+ bindex = bbot; -+ p = au_hdentry(dinfo, bindex); -+ for (; bindex >= 0; bindex--, p--) -+ if (p->hd_dentry) { -+ dinfo->di_bbot = bindex; -+ err = 0; -+ break; -+ } -+ } -+ -+ return err; -+} -+ -+static void au_do_hide(struct dentry *dentry) -+{ -+ struct inode *inode; -+ -+ if (d_really_is_positive(dentry)) { -+ inode = d_inode(dentry); -+ if (!d_is_dir(dentry)) { -+ if (inode->i_nlink && !d_unhashed(dentry)) -+ drop_nlink(inode); -+ } else { -+ clear_nlink(inode); -+ /* stop next lookup */ -+ inode->i_flags |= S_DEAD; -+ } -+ smp_mb(); /* necessary? */ -+ } -+ d_drop(dentry); -+} -+ -+static int au_hide_children(struct dentry *parent) -+{ -+ int err, i, j, ndentry; -+ struct au_dcsub_pages dpages; -+ struct au_dpage *dpage; -+ struct dentry *dentry; -+ -+ err = au_dpages_init(&dpages, GFP_NOFS); -+ if (unlikely(err)) -+ goto out; -+ err = au_dcsub_pages(&dpages, parent, NULL, NULL); -+ if (unlikely(err)) -+ goto out_dpages; -+ -+ /* in reverse order */ -+ for (i = dpages.ndpage - 1; i >= 0; i--) { -+ dpage = dpages.dpages + i; -+ ndentry = dpage->ndentry; -+ for (j = ndentry - 1; j >= 0; j--) { -+ dentry = dpage->dentries[j]; -+ if (dentry != parent) -+ au_do_hide(dentry); -+ } -+ } -+ -+out_dpages: -+ au_dpages_free(&dpages); -+out: -+ return err; -+} -+ -+static void au_hide(struct dentry *dentry) -+{ -+ int err; -+ -+ AuDbgDentry(dentry); -+ if (d_is_dir(dentry)) { -+ /* shrink_dcache_parent(dentry); */ -+ err = au_hide_children(dentry); -+ if (unlikely(err)) -+ AuIOErr("%pd, failed hiding children, ignored %d\n", -+ dentry, err); -+ } -+ au_do_hide(dentry); -+} -+ -+/* -+ * By adding a dirty branch, a cached dentry may be affected in various ways. -+ * -+ * a dirty branch is added -+ * - on the top of layers -+ * - in the middle of layers -+ * - to the bottom of layers -+ * -+ * on the added branch there exists -+ * - a whiteout -+ * - a diropq -+ * - a same named entry -+ * + exist -+ * * negative --> positive -+ * * positive --> positive -+ * - type is unchanged -+ * - type is changed -+ * + doesn't exist -+ * * negative --> negative -+ * * positive --> negative (rejected by au_br_del() for non-dir case) -+ * - none -+ */ -+static int au_refresh_by_dinfo(struct dentry *dentry, struct au_dinfo *dinfo, -+ struct au_dinfo *tmp) -+{ -+ int err; -+ aufs_bindex_t bindex, bbot; -+ struct { -+ struct dentry *dentry; -+ struct inode *inode; -+ mode_t mode; -+ } orig_h, tmp_h = { -+ .dentry = NULL -+ }; -+ struct au_hdentry *hd; -+ struct inode *inode, *h_inode; -+ struct dentry *h_dentry; -+ -+ err = 0; -+ AuDebugOn(dinfo->di_btop < 0); -+ orig_h.mode = 0; -+ orig_h.dentry = au_hdentry(dinfo, dinfo->di_btop)->hd_dentry; -+ orig_h.inode = NULL; -+ if (d_is_positive(orig_h.dentry)) { -+ orig_h.inode = d_inode(orig_h.dentry); -+ orig_h.mode = orig_h.inode->i_mode & S_IFMT; -+ } -+ if (tmp->di_btop >= 0) { -+ tmp_h.dentry = au_hdentry(tmp, tmp->di_btop)->hd_dentry; -+ if (d_is_positive(tmp_h.dentry)) { -+ tmp_h.inode = d_inode(tmp_h.dentry); -+ tmp_h.mode = tmp_h.inode->i_mode & S_IFMT; -+ } -+ } -+ -+ inode = NULL; -+ if (d_really_is_positive(dentry)) -+ inode = d_inode(dentry); -+ if (!orig_h.inode) { -+ AuDbg("negative originally\n"); -+ if (inode) { -+ au_hide(dentry); -+ goto out; -+ } -+ AuDebugOn(inode); -+ AuDebugOn(dinfo->di_btop != dinfo->di_bbot); -+ AuDebugOn(dinfo->di_bdiropq != -1); -+ -+ if (!tmp_h.inode) { -+ AuDbg("negative --> negative\n"); -+ /* should have only one negative lower */ -+ if (tmp->di_btop >= 0 -+ && tmp->di_btop < dinfo->di_btop) { -+ AuDebugOn(tmp->di_btop != tmp->di_bbot); -+ AuDebugOn(dinfo->di_btop != dinfo->di_bbot); -+ au_set_h_dptr(dentry, dinfo->di_btop, NULL); -+ au_di_cp(dinfo, tmp); -+ hd = au_hdentry(tmp, tmp->di_btop); -+ au_set_h_dptr(dentry, tmp->di_btop, -+ dget(hd->hd_dentry)); -+ } -+ au_dbg_verify_dinode(dentry); -+ } else { -+ AuDbg("negative --> positive\n"); -+ /* -+ * similar to the behaviour of creating with bypassing -+ * aufs. -+ * unhash it in order to force an error in the -+ * succeeding create operation. -+ * we should not set S_DEAD here. -+ */ -+ d_drop(dentry); -+ /* au_di_swap(tmp, dinfo); */ -+ au_dbg_verify_dinode(dentry); -+ } -+ } else { -+ AuDbg("positive originally\n"); -+ /* inode may be NULL */ -+ AuDebugOn(inode && (inode->i_mode & S_IFMT) != orig_h.mode); -+ if (!tmp_h.inode) { -+ AuDbg("positive --> negative\n"); -+ /* or bypassing aufs */ -+ au_hide(dentry); -+ if (tmp->di_bwh >= 0 && tmp->di_bwh <= dinfo->di_btop) -+ dinfo->di_bwh = tmp->di_bwh; -+ if (inode) -+ err = au_refresh_hinode_self(inode); -+ au_dbg_verify_dinode(dentry); -+ } else if (orig_h.mode == tmp_h.mode) { -+ AuDbg("positive --> positive, same type\n"); -+ if (!S_ISDIR(orig_h.mode) -+ && dinfo->di_btop > tmp->di_btop) { -+ /* -+ * similar to the behaviour of removing and -+ * creating. -+ */ -+ au_hide(dentry); -+ if (inode) -+ err = au_refresh_hinode_self(inode); -+ au_dbg_verify_dinode(dentry); -+ } else { -+ /* fill empty slots */ -+ if (dinfo->di_btop > tmp->di_btop) -+ dinfo->di_btop = tmp->di_btop; -+ if (dinfo->di_bbot < tmp->di_bbot) -+ dinfo->di_bbot = tmp->di_bbot; -+ dinfo->di_bwh = tmp->di_bwh; -+ dinfo->di_bdiropq = tmp->di_bdiropq; -+ bbot = dinfo->di_bbot; -+ bindex = tmp->di_btop; -+ hd = au_hdentry(tmp, bindex); -+ for (; bindex <= bbot; bindex++, hd++) { -+ if (au_h_dptr(dentry, bindex)) -+ continue; -+ h_dentry = hd->hd_dentry; -+ if (!h_dentry) -+ continue; -+ AuDebugOn(d_is_negative(h_dentry)); -+ h_inode = d_inode(h_dentry); -+ AuDebugOn(orig_h.mode -+ != (h_inode->i_mode -+ & S_IFMT)); -+ au_set_h_dptr(dentry, bindex, -+ dget(h_dentry)); -+ } -+ if (inode) -+ err = au_refresh_hinode(inode, dentry); -+ au_dbg_verify_dinode(dentry); -+ } -+ } else { -+ AuDbg("positive --> positive, different type\n"); -+ /* similar to the behaviour of removing and creating */ -+ au_hide(dentry); -+ if (inode) -+ err = au_refresh_hinode_self(inode); -+ au_dbg_verify_dinode(dentry); -+ } -+ } -+ -+out: -+ return err; -+} -+ -+void au_refresh_dop(struct dentry *dentry, int force_reval) -+{ -+ const struct dentry_operations *dop -+ = force_reval ? &aufs_dop : dentry->d_sb->s_d_op; -+ static const unsigned int mask -+ = DCACHE_OP_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE; -+ -+ BUILD_BUG_ON(sizeof(mask) != sizeof(dentry->d_flags)); -+ -+ if (dentry->d_op == dop) -+ return; -+ -+ AuDbg("%pd\n", dentry); -+ spin_lock(&dentry->d_lock); -+ if (dop == &aufs_dop) -+ dentry->d_flags |= mask; -+ else -+ dentry->d_flags &= ~mask; -+ dentry->d_op = dop; -+ spin_unlock(&dentry->d_lock); -+} -+ -+int au_refresh_dentry(struct dentry *dentry, struct dentry *parent) -+{ -+ int err, ebrange, nbr; -+ unsigned int sigen; -+ struct au_dinfo *dinfo, *tmp; -+ struct super_block *sb; -+ struct inode *inode; -+ -+ DiMustWriteLock(dentry); -+ AuDebugOn(IS_ROOT(dentry)); -+ AuDebugOn(d_really_is_negative(parent)); -+ -+ sb = dentry->d_sb; -+ sigen = au_sigen(sb); -+ err = au_digen_test(parent, sigen); -+ if (unlikely(err)) -+ goto out; -+ -+ nbr = au_sbbot(sb) + 1; -+ dinfo = au_di(dentry); -+ err = au_di_realloc(dinfo, nbr, /*may_shrink*/0); -+ if (unlikely(err)) -+ goto out; -+ ebrange = au_dbrange_test(dentry); -+ if (!ebrange) -+ ebrange = au_do_refresh_hdentry(dentry, parent); -+ -+ if (d_unhashed(dentry) || ebrange /* || dinfo->di_tmpfile */) { -+ AuDebugOn(au_dbtop(dentry) < 0 && au_dbbot(dentry) >= 0); -+ if (d_really_is_positive(dentry)) { -+ inode = d_inode(dentry); -+ err = au_refresh_hinode_self(inode); -+ } -+ au_dbg_verify_dinode(dentry); -+ if (!err) -+ goto out_dgen; /* success */ -+ goto out; -+ } -+ -+ /* temporary dinfo */ -+ AuDbgDentry(dentry); -+ err = -ENOMEM; -+ tmp = au_di_alloc(sb, AuLsc_DI_TMP); -+ if (unlikely(!tmp)) -+ goto out; -+ au_di_swap(tmp, dinfo); -+ /* returns the number of positive dentries */ -+ /* -+ * if current working dir is removed, it returns an error. -+ * but the dentry is legal. -+ */ -+ err = au_lkup_dentry(dentry, /*btop*/0, AuLkup_ALLOW_NEG); -+ AuDbgDentry(dentry); -+ au_di_swap(tmp, dinfo); -+ if (err == -ENOENT) -+ err = 0; -+ if (err >= 0) { -+ /* compare/refresh by dinfo */ -+ AuDbgDentry(dentry); -+ err = au_refresh_by_dinfo(dentry, dinfo, tmp); -+ au_dbg_verify_dinode(dentry); -+ AuTraceErr(err); -+ } -+ au_di_realloc(dinfo, nbr, /*may_shrink*/1); /* harmless if err */ -+ au_rw_write_unlock(&tmp->di_rwsem); -+ au_di_free(tmp); -+ if (unlikely(err)) -+ goto out; -+ -+out_dgen: -+ au_update_digen(dentry); -+out: -+ if (unlikely(err && !(dentry->d_flags & DCACHE_NFSFS_RENAMED))) { -+ AuIOErr("failed refreshing %pd, %d\n", dentry, err); -+ AuDbgDentry(dentry); -+ } -+ AuTraceErr(err); -+ return err; -+} -+ -+static int au_do_h_d_reval(struct dentry *h_dentry, unsigned int flags, -+ struct dentry *dentry, aufs_bindex_t bindex) -+{ -+ int err, valid; -+ -+ err = 0; -+ if (!(h_dentry->d_flags & DCACHE_OP_REVALIDATE)) -+ goto out; -+ -+ AuDbg("b%d\n", bindex); -+ /* -+ * gave up supporting LOOKUP_CREATE/OPEN for lower fs, -+ * due to whiteout and branch permission. -+ */ -+ flags &= ~(/*LOOKUP_PARENT |*/ LOOKUP_OPEN | LOOKUP_CREATE -+ | LOOKUP_FOLLOW | LOOKUP_EXCL); -+ /* it may return tri-state */ -+ valid = h_dentry->d_op->d_revalidate(h_dentry, flags); -+ -+ if (unlikely(valid < 0)) -+ err = valid; -+ else if (!valid) -+ err = -EINVAL; -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+/* todo: remove this */ -+static int h_d_revalidate(struct dentry *dentry, struct inode *inode, -+ unsigned int flags, int do_udba, int dirren) -+{ -+ int err; -+ umode_t mode, h_mode; -+ aufs_bindex_t bindex, btail, btop, ibs, ibe; -+ unsigned char plus, unhashed, is_root, h_plus, h_nfs, tmpfile; -+ struct inode *h_inode, *h_cached_inode; -+ struct dentry *h_dentry; -+ struct qstr *name, *h_name; -+ -+ err = 0; -+ plus = 0; -+ mode = 0; -+ ibs = -1; -+ ibe = -1; -+ unhashed = !!d_unhashed(dentry); -+ is_root = !!IS_ROOT(dentry); -+ name = &dentry->d_name; -+ tmpfile = au_di(dentry)->di_tmpfile; -+ -+ /* -+ * Theoretically, REVAL test should be unnecessary in case of -+ * {FS,I}NOTIFY. -+ * But {fs,i}notify doesn't fire some necessary events, -+ * IN_ATTRIB for atime/nlink/pageio -+ * Let's do REVAL test too. -+ */ -+ if (do_udba && inode) { -+ mode = (inode->i_mode & S_IFMT); -+ plus = (inode->i_nlink > 0); -+ ibs = au_ibtop(inode); -+ ibe = au_ibbot(inode); -+ } -+ -+ btop = au_dbtop(dentry); -+ btail = btop; -+ if (inode && S_ISDIR(inode->i_mode)) -+ btail = au_dbtaildir(dentry); -+ for (bindex = btop; bindex <= btail; bindex++) { -+ h_dentry = au_h_dptr(dentry, bindex); -+ if (!h_dentry) -+ continue; -+ -+ AuDbg("b%d, %pd\n", bindex, h_dentry); -+ h_nfs = !!au_test_nfs(h_dentry->d_sb); -+ spin_lock(&h_dentry->d_lock); -+ h_name = &h_dentry->d_name; -+ if (unlikely(do_udba -+ && !is_root -+ && ((!h_nfs -+ && (unhashed != !!d_unhashed(h_dentry) -+ || (!tmpfile && !dirren -+ && !au_qstreq(name, h_name)) -+ )) -+ || (h_nfs -+ && !(flags & LOOKUP_OPEN) -+ && (h_dentry->d_flags -+ & DCACHE_NFSFS_RENAMED))) -+ )) { -+ int h_unhashed; -+ -+ h_unhashed = d_unhashed(h_dentry); -+ spin_unlock(&h_dentry->d_lock); -+ AuDbg("unhash 0x%x 0x%x, %pd %pd\n", -+ unhashed, h_unhashed, dentry, h_dentry); -+ goto err; -+ } -+ spin_unlock(&h_dentry->d_lock); -+ -+ err = au_do_h_d_reval(h_dentry, flags, dentry, bindex); -+ if (unlikely(err)) -+ /* do not goto err, to keep the errno */ -+ break; -+ -+ /* todo: plink too? */ -+ if (!do_udba) -+ continue; -+ -+ /* UDBA tests */ -+ if (unlikely(!!inode != d_is_positive(h_dentry))) -+ goto err; -+ -+ h_inode = NULL; -+ if (d_is_positive(h_dentry)) -+ h_inode = d_inode(h_dentry); -+ h_plus = plus; -+ h_mode = mode; -+ h_cached_inode = h_inode; -+ if (h_inode) { -+ h_mode = (h_inode->i_mode & S_IFMT); -+ h_plus = (h_inode->i_nlink > 0); -+ } -+ if (inode && ibs <= bindex && bindex <= ibe) -+ h_cached_inode = au_h_iptr(inode, bindex); -+ -+ if (!h_nfs) { -+ if (unlikely(plus != h_plus && !tmpfile)) -+ goto err; -+ } else { -+ if (unlikely(!(h_dentry->d_flags & DCACHE_NFSFS_RENAMED) -+ && !is_root -+ && !IS_ROOT(h_dentry) -+ && unhashed != d_unhashed(h_dentry))) -+ goto err; -+ } -+ if (unlikely(mode != h_mode -+ || h_cached_inode != h_inode)) -+ goto err; -+ continue; -+ -+err: -+ err = -EINVAL; -+ break; -+ } -+ -+ AuTraceErr(err); -+ return err; -+} -+ -+/* todo: consolidate with do_refresh() and au_reval_for_attr() */ -+static int simple_reval_dpath(struct dentry *dentry, unsigned int sigen) -+{ -+ int err; -+ struct dentry *parent; -+ -+ if (!au_digen_test(dentry, sigen)) -+ return 0; -+ -+ parent = dget_parent(dentry); -+ di_read_lock_parent(parent, AuLock_IR); -+ AuDebugOn(au_digen_test(parent, sigen)); -+ au_dbg_verify_gen(parent, sigen); -+ err = au_refresh_dentry(dentry, parent); -+ di_read_unlock(parent, AuLock_IR); -+ dput(parent); -+ AuTraceErr(err); -+ return err; -+} -+ -+int au_reval_dpath(struct dentry *dentry, unsigned int sigen) -+{ -+ int err; -+ struct dentry *d, *parent; -+ -+ if (!au_ftest_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIR)) -+ return simple_reval_dpath(dentry, sigen); -+ -+ /* slow loop, keep it simple and stupid */ -+ /* cf: au_cpup_dirs() */ -+ err = 0; -+ parent = NULL; -+ while (au_digen_test(dentry, sigen)) { -+ d = dentry; -+ while (1) { -+ dput(parent); -+ parent = dget_parent(d); -+ if (!au_digen_test(parent, sigen)) -+ break; -+ d = parent; -+ } -+ -+ if (d != dentry) -+ di_write_lock_child2(d); -+ -+ /* someone might update our dentry while we were sleeping */ -+ if (au_digen_test(d, sigen)) { -+ /* -+ * todo: consolidate with simple_reval_dpath(), -+ * do_refresh() and au_reval_for_attr(). -+ */ -+ di_read_lock_parent(parent, AuLock_IR); -+ err = au_refresh_dentry(d, parent); -+ di_read_unlock(parent, AuLock_IR); -+ } -+ -+ if (d != dentry) -+ di_write_unlock(d); -+ dput(parent); -+ if (unlikely(err)) -+ break; -+ } -+ -+ return err; -+} -+ -+/* -+ * if valid returns 1, otherwise 0. -+ */ -+static int aufs_d_revalidate(struct dentry *dentry, unsigned int flags) -+{ -+ int valid, err; -+ unsigned int sigen; -+ unsigned char do_udba, dirren; -+ struct super_block *sb; -+ struct inode *inode; -+ -+ /* todo: support rcu-walk? */ -+ if (flags & LOOKUP_RCU) -+ return -ECHILD; -+ -+ valid = 0; -+ if (unlikely(!au_di(dentry))) -+ goto out; -+ -+ valid = 1; -+ sb = dentry->d_sb; -+ /* -+ * todo: very ugly -+ * i_mutex of parent dir may be held, -+ * but we should not return 'invalid' due to busy. -+ */ -+ err = aufs_read_lock(dentry, AuLock_FLUSH | AuLock_DW | AuLock_NOPLM); -+ if (unlikely(err)) { -+ valid = err; -+ AuTraceErr(err); -+ goto out; -+ } -+ inode = NULL; -+ if (d_really_is_positive(dentry)) -+ inode = d_inode(dentry); -+ if (unlikely(inode && au_is_bad_inode(inode))) { -+ err = -EINVAL; -+ AuTraceErr(err); -+ goto out_dgrade; -+ } -+ if (unlikely(au_dbrange_test(dentry))) { -+ err = -EINVAL; -+ AuTraceErr(err); -+ goto out_dgrade; -+ } -+ -+ sigen = au_sigen(sb); -+ if (au_digen_test(dentry, sigen)) { -+ AuDebugOn(IS_ROOT(dentry)); -+ err = au_reval_dpath(dentry, sigen); -+ if (unlikely(err)) { -+ AuTraceErr(err); -+ goto out_dgrade; -+ } -+ } -+ di_downgrade_lock(dentry, AuLock_IR); -+ -+ err = -EINVAL; -+ if (!(flags & (LOOKUP_OPEN | LOOKUP_EMPTY)) -+ && inode -+ && !(inode->i_state && I_LINKABLE) -+ && (IS_DEADDIR(inode) || !inode->i_nlink)) { -+ AuTraceErr(err); -+ goto out_inval; -+ } -+ -+ do_udba = !au_opt_test(au_mntflags(sb), UDBA_NONE); -+ if (do_udba && inode) { -+ aufs_bindex_t btop = au_ibtop(inode); -+ struct inode *h_inode; -+ -+ if (btop >= 0) { -+ h_inode = au_h_iptr(inode, btop); -+ if (h_inode && au_test_higen(inode, h_inode)) { -+ AuTraceErr(err); -+ goto out_inval; -+ } -+ } -+ } -+ -+ dirren = !!au_opt_test(au_mntflags(sb), DIRREN); -+ err = h_d_revalidate(dentry, inode, flags, do_udba, dirren); -+ if (unlikely(!err && do_udba && au_dbtop(dentry) < 0)) { -+ err = -EIO; -+ AuDbg("both of real entry and whiteout found, %p, err %d\n", -+ dentry, err); -+ } -+ goto out_inval; -+ -+out_dgrade: -+ di_downgrade_lock(dentry, AuLock_IR); -+out_inval: -+ aufs_read_unlock(dentry, AuLock_IR); -+ AuTraceErr(err); -+ valid = !err; -+out: -+ if (!valid) { -+ AuDbg("%pd invalid, %d\n", dentry, valid); -+ d_drop(dentry); -+ } -+ return valid; -+} -+ -+static void aufs_d_release(struct dentry *dentry) -+{ -+ if (au_di(dentry)) { -+ au_di_fin(dentry); -+ au_hn_di_reinit(dentry); -+ } -+} -+ -+const struct dentry_operations aufs_dop = { -+ .d_revalidate = aufs_d_revalidate, -+ .d_weak_revalidate = aufs_d_revalidate, -+ .d_release = aufs_d_release -+}; -+ -+/* aufs_dop without d_revalidate */ -+const struct dentry_operations aufs_dop_noreval = { -+ .d_release = aufs_d_release -+}; -diff --git a/fs/aufs/dentry.h b/fs/aufs/dentry.h -new file mode 100644 -index 000000000000..086f6ccf4b15 ---- /dev/null -+++ b/fs/aufs/dentry.h -@@ -0,0 +1,255 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * lookup and dentry operations -+ */ -+ -+#ifndef __AUFS_DENTRY_H__ -+#define __AUFS_DENTRY_H__ -+ -+#ifdef __KERNEL__ -+ -+#include -+#include "dirren.h" -+#include "rwsem.h" -+ -+struct au_hdentry { -+ struct dentry *hd_dentry; -+ aufs_bindex_t hd_id; -+}; -+ -+struct au_dinfo { -+ atomic_t di_generation; -+ -+ struct au_rwsem di_rwsem; -+ aufs_bindex_t di_btop, di_bbot, di_bwh, di_bdiropq; -+ unsigned char di_tmpfile; /* to allow the different name */ -+ struct au_hdentry *di_hdentry; -+ struct rcu_head rcu; -+} ____cacheline_aligned_in_smp; -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* flags for au_lkup_dentry() */ -+#define AuLkup_ALLOW_NEG 1 -+#define AuLkup_IGNORE_PERM (1 << 1) -+#define AuLkup_DIRREN (1 << 2) -+#define au_ftest_lkup(flags, name) ((flags) & AuLkup_##name) -+#define au_fset_lkup(flags, name) \ -+ do { (flags) |= AuLkup_##name; } while (0) -+#define au_fclr_lkup(flags, name) \ -+ do { (flags) &= ~AuLkup_##name; } while (0) -+ -+#ifndef CONFIG_AUFS_DIRREN -+#undef AuLkup_DIRREN -+#define AuLkup_DIRREN 0 -+#endif -+ -+struct au_do_lookup_args { -+ unsigned int flags; -+ mode_t type; -+ struct qstr whname, *name; -+ struct au_dr_lookup dirren; -+}; -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* dentry.c */ -+extern const struct dentry_operations aufs_dop, aufs_dop_noreval; -+struct au_branch; -+struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent); -+int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir, -+ struct dentry *h_parent, struct au_branch *br); -+ -+int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t btop, -+ unsigned int flags); -+int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex, int wh); -+int au_refresh_dentry(struct dentry *dentry, struct dentry *parent); -+int au_reval_dpath(struct dentry *dentry, unsigned int sigen); -+void au_refresh_dop(struct dentry *dentry, int force_reval); -+ -+/* dinfo.c */ -+void au_di_init_once(void *_di); -+struct au_dinfo *au_di_alloc(struct super_block *sb, unsigned int lsc); -+void au_di_free(struct au_dinfo *dinfo); -+void au_di_swap(struct au_dinfo *a, struct au_dinfo *b); -+void au_di_cp(struct au_dinfo *dst, struct au_dinfo *src); -+int au_di_init(struct dentry *dentry); -+void au_di_fin(struct dentry *dentry); -+int au_di_realloc(struct au_dinfo *dinfo, int nbr, int may_shrink); -+ -+void di_read_lock(struct dentry *d, int flags, unsigned int lsc); -+void di_read_unlock(struct dentry *d, int flags); -+void di_downgrade_lock(struct dentry *d, int flags); -+void di_write_lock(struct dentry *d, unsigned int lsc); -+void di_write_unlock(struct dentry *d); -+void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir); -+void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir); -+void di_write_unlock2(struct dentry *d1, struct dentry *d2); -+ -+struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex); -+struct dentry *au_h_d_alias(struct dentry *dentry, aufs_bindex_t bindex); -+aufs_bindex_t au_dbtail(struct dentry *dentry); -+aufs_bindex_t au_dbtaildir(struct dentry *dentry); -+ -+void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex, -+ struct dentry *h_dentry); -+int au_digen_test(struct dentry *dentry, unsigned int sigen); -+int au_dbrange_test(struct dentry *dentry); -+void au_update_digen(struct dentry *dentry); -+void au_update_dbrange(struct dentry *dentry, int do_put_zero); -+void au_update_dbtop(struct dentry *dentry); -+void au_update_dbbot(struct dentry *dentry); -+int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry); -+ -+/* ---------------------------------------------------------------------- */ -+ -+static inline struct au_dinfo *au_di(struct dentry *dentry) -+{ -+ return dentry->d_fsdata; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* lock subclass for dinfo */ -+enum { -+ AuLsc_DI_CHILD, /* child first */ -+ AuLsc_DI_CHILD2, /* rename(2), link(2), and cpup at hnotify */ -+ AuLsc_DI_CHILD3, /* copyup dirs */ -+ AuLsc_DI_PARENT, -+ AuLsc_DI_PARENT2, -+ AuLsc_DI_PARENT3, -+ AuLsc_DI_TMP /* temp for replacing dinfo */ -+}; -+ -+/* -+ * di_read_lock_child, di_write_lock_child, -+ * di_read_lock_child2, di_write_lock_child2, -+ * di_read_lock_child3, di_write_lock_child3, -+ * di_read_lock_parent, di_write_lock_parent, -+ * di_read_lock_parent2, di_write_lock_parent2, -+ * di_read_lock_parent3, di_write_lock_parent3, -+ */ -+#define AuReadLockFunc(name, lsc) \ -+static inline void di_read_lock_##name(struct dentry *d, int flags) \ -+{ di_read_lock(d, flags, AuLsc_DI_##lsc); } -+ -+#define AuWriteLockFunc(name, lsc) \ -+static inline void di_write_lock_##name(struct dentry *d) \ -+{ di_write_lock(d, AuLsc_DI_##lsc); } -+ -+#define AuRWLockFuncs(name, lsc) \ -+ AuReadLockFunc(name, lsc) \ -+ AuWriteLockFunc(name, lsc) -+ -+AuRWLockFuncs(child, CHILD); -+AuRWLockFuncs(child2, CHILD2); -+AuRWLockFuncs(child3, CHILD3); -+AuRWLockFuncs(parent, PARENT); -+AuRWLockFuncs(parent2, PARENT2); -+AuRWLockFuncs(parent3, PARENT3); -+ -+#undef AuReadLockFunc -+#undef AuWriteLockFunc -+#undef AuRWLockFuncs -+ -+#define DiMustNoWaiters(d) AuRwMustNoWaiters(&au_di(d)->di_rwsem) -+#define DiMustAnyLock(d) AuRwMustAnyLock(&au_di(d)->di_rwsem) -+#define DiMustWriteLock(d) AuRwMustWriteLock(&au_di(d)->di_rwsem) -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* todo: memory barrier? */ -+static inline unsigned int au_digen(struct dentry *d) -+{ -+ return atomic_read(&au_di(d)->di_generation); -+} -+ -+static inline void au_h_dentry_init(struct au_hdentry *hdentry) -+{ -+ hdentry->hd_dentry = NULL; -+} -+ -+static inline struct au_hdentry *au_hdentry(struct au_dinfo *di, -+ aufs_bindex_t bindex) -+{ -+ return di->di_hdentry + bindex; -+} -+ -+static inline void au_hdput(struct au_hdentry *hd) -+{ -+ if (hd) -+ dput(hd->hd_dentry); -+} -+ -+static inline aufs_bindex_t au_dbtop(struct dentry *dentry) -+{ -+ DiMustAnyLock(dentry); -+ return au_di(dentry)->di_btop; -+} -+ -+static inline aufs_bindex_t au_dbbot(struct dentry *dentry) -+{ -+ DiMustAnyLock(dentry); -+ return au_di(dentry)->di_bbot; -+} -+ -+static inline aufs_bindex_t au_dbwh(struct dentry *dentry) -+{ -+ DiMustAnyLock(dentry); -+ return au_di(dentry)->di_bwh; -+} -+ -+static inline aufs_bindex_t au_dbdiropq(struct dentry *dentry) -+{ -+ DiMustAnyLock(dentry); -+ return au_di(dentry)->di_bdiropq; -+} -+ -+/* todo: hard/soft set? */ -+static inline void au_set_dbtop(struct dentry *dentry, aufs_bindex_t bindex) -+{ -+ DiMustWriteLock(dentry); -+ au_di(dentry)->di_btop = bindex; -+} -+ -+static inline void au_set_dbbot(struct dentry *dentry, aufs_bindex_t bindex) -+{ -+ DiMustWriteLock(dentry); -+ au_di(dentry)->di_bbot = bindex; -+} -+ -+static inline void au_set_dbwh(struct dentry *dentry, aufs_bindex_t bindex) -+{ -+ DiMustWriteLock(dentry); -+ /* dbwh can be outside of btop - bbot range */ -+ au_di(dentry)->di_bwh = bindex; -+} -+ -+static inline void au_set_dbdiropq(struct dentry *dentry, aufs_bindex_t bindex) -+{ -+ DiMustWriteLock(dentry); -+ au_di(dentry)->di_bdiropq = bindex; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+#ifdef CONFIG_AUFS_HNOTIFY -+static inline void au_digen_dec(struct dentry *d) -+{ -+ atomic_dec(&au_di(d)->di_generation); -+} -+ -+static inline void au_hn_di_reinit(struct dentry *dentry) -+{ -+ dentry->d_fsdata = NULL; -+} -+#else -+AuStubVoid(au_hn_di_reinit, struct dentry *dentry __maybe_unused) -+#endif /* CONFIG_AUFS_HNOTIFY */ -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_DENTRY_H__ */ -diff --git a/fs/aufs/dinfo.c b/fs/aufs/dinfo.c -new file mode 100644 -index 000000000000..aed5314e5e24 ---- /dev/null -+++ b/fs/aufs/dinfo.c -@@ -0,0 +1,541 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * dentry private data -+ */ -+ -+#include "aufs.h" -+ -+void au_di_init_once(void *_dinfo) -+{ -+ struct au_dinfo *dinfo = _dinfo; -+ -+ au_rw_init(&dinfo->di_rwsem); -+} -+ -+struct au_dinfo *au_di_alloc(struct super_block *sb, unsigned int lsc) -+{ -+ struct au_dinfo *dinfo; -+ int nbr, i; -+ -+ dinfo = au_cache_alloc_dinfo(); -+ if (unlikely(!dinfo)) -+ goto out; -+ -+ nbr = au_sbbot(sb) + 1; -+ if (nbr <= 0) -+ nbr = 1; -+ dinfo->di_hdentry = kcalloc(nbr, sizeof(*dinfo->di_hdentry), GFP_NOFS); -+ if (dinfo->di_hdentry) { -+ au_rw_write_lock_nested(&dinfo->di_rwsem, lsc); -+ dinfo->di_btop = -1; -+ dinfo->di_bbot = -1; -+ dinfo->di_bwh = -1; -+ dinfo->di_bdiropq = -1; -+ dinfo->di_tmpfile = 0; -+ for (i = 0; i < nbr; i++) -+ dinfo->di_hdentry[i].hd_id = -1; -+ goto out; -+ } -+ -+ au_cache_free_dinfo(dinfo); -+ dinfo = NULL; -+ -+out: -+ return dinfo; -+} -+ -+void au_di_free(struct au_dinfo *dinfo) -+{ -+ struct au_hdentry *p; -+ aufs_bindex_t bbot, bindex; -+ -+ /* dentry may not be revalidated */ -+ bindex = dinfo->di_btop; -+ if (bindex >= 0) { -+ bbot = dinfo->di_bbot; -+ p = au_hdentry(dinfo, bindex); -+ while (bindex++ <= bbot) -+ au_hdput(p++); -+ } -+ au_kfree_try_rcu(dinfo->di_hdentry); -+ au_cache_free_dinfo(dinfo); -+} -+ -+void au_di_swap(struct au_dinfo *a, struct au_dinfo *b) -+{ -+ struct au_hdentry *p; -+ aufs_bindex_t bi; -+ -+ AuRwMustWriteLock(&a->di_rwsem); -+ AuRwMustWriteLock(&b->di_rwsem); -+ -+#define DiSwap(v, name) \ -+ do { \ -+ v = a->di_##name; \ -+ a->di_##name = b->di_##name; \ -+ b->di_##name = v; \ -+ } while (0) -+ -+ DiSwap(p, hdentry); -+ DiSwap(bi, btop); -+ DiSwap(bi, bbot); -+ DiSwap(bi, bwh); -+ DiSwap(bi, bdiropq); -+ /* smp_mb(); */ -+ -+#undef DiSwap -+} -+ -+void au_di_cp(struct au_dinfo *dst, struct au_dinfo *src) -+{ -+ AuRwMustWriteLock(&dst->di_rwsem); -+ AuRwMustWriteLock(&src->di_rwsem); -+ -+ dst->di_btop = src->di_btop; -+ dst->di_bbot = src->di_bbot; -+ dst->di_bwh = src->di_bwh; -+ dst->di_bdiropq = src->di_bdiropq; -+ /* smp_mb(); */ -+} -+ -+int au_di_init(struct dentry *dentry) -+{ -+ int err; -+ struct super_block *sb; -+ struct au_dinfo *dinfo; -+ -+ err = 0; -+ sb = dentry->d_sb; -+ dinfo = au_di_alloc(sb, AuLsc_DI_CHILD); -+ if (dinfo) { -+ atomic_set(&dinfo->di_generation, au_sigen(sb)); -+ /* smp_mb(); */ /* atomic_set */ -+ dentry->d_fsdata = dinfo; -+ } else -+ err = -ENOMEM; -+ -+ return err; -+} -+ -+void au_di_fin(struct dentry *dentry) -+{ -+ struct au_dinfo *dinfo; -+ -+ dinfo = au_di(dentry); -+ AuRwDestroy(&dinfo->di_rwsem); -+ au_di_free(dinfo); -+} -+ -+int au_di_realloc(struct au_dinfo *dinfo, int nbr, int may_shrink) -+{ -+ int err, sz; -+ struct au_hdentry *hdp; -+ -+ AuRwMustWriteLock(&dinfo->di_rwsem); -+ -+ err = -ENOMEM; -+ sz = sizeof(*hdp) * (dinfo->di_bbot + 1); -+ if (!sz) -+ sz = sizeof(*hdp); -+ hdp = au_kzrealloc(dinfo->di_hdentry, sz, sizeof(*hdp) * nbr, GFP_NOFS, -+ may_shrink); -+ if (hdp) { -+ dinfo->di_hdentry = hdp; -+ err = 0; -+ } -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static void do_ii_write_lock(struct inode *inode, unsigned int lsc) -+{ -+ switch (lsc) { -+ case AuLsc_DI_CHILD: -+ ii_write_lock_child(inode); -+ break; -+ case AuLsc_DI_CHILD2: -+ ii_write_lock_child2(inode); -+ break; -+ case AuLsc_DI_CHILD3: -+ ii_write_lock_child3(inode); -+ break; -+ case AuLsc_DI_PARENT: -+ ii_write_lock_parent(inode); -+ break; -+ case AuLsc_DI_PARENT2: -+ ii_write_lock_parent2(inode); -+ break; -+ case AuLsc_DI_PARENT3: -+ ii_write_lock_parent3(inode); -+ break; -+ default: -+ BUG(); -+ } -+} -+ -+static void do_ii_read_lock(struct inode *inode, unsigned int lsc) -+{ -+ switch (lsc) { -+ case AuLsc_DI_CHILD: -+ ii_read_lock_child(inode); -+ break; -+ case AuLsc_DI_CHILD2: -+ ii_read_lock_child2(inode); -+ break; -+ case AuLsc_DI_CHILD3: -+ ii_read_lock_child3(inode); -+ break; -+ case AuLsc_DI_PARENT: -+ ii_read_lock_parent(inode); -+ break; -+ case AuLsc_DI_PARENT2: -+ ii_read_lock_parent2(inode); -+ break; -+ case AuLsc_DI_PARENT3: -+ ii_read_lock_parent3(inode); -+ break; -+ default: -+ BUG(); -+ } -+} -+ -+void di_read_lock(struct dentry *d, int flags, unsigned int lsc) -+{ -+ struct inode *inode; -+ -+ au_rw_read_lock_nested(&au_di(d)->di_rwsem, lsc); -+ if (d_really_is_positive(d)) { -+ inode = d_inode(d); -+ if (au_ftest_lock(flags, IW)) -+ do_ii_write_lock(inode, lsc); -+ else if (au_ftest_lock(flags, IR)) -+ do_ii_read_lock(inode, lsc); -+ } -+} -+ -+void di_read_unlock(struct dentry *d, int flags) -+{ -+ struct inode *inode; -+ -+ if (d_really_is_positive(d)) { -+ inode = d_inode(d); -+ if (au_ftest_lock(flags, IW)) { -+ au_dbg_verify_dinode(d); -+ ii_write_unlock(inode); -+ } else if (au_ftest_lock(flags, IR)) { -+ au_dbg_verify_dinode(d); -+ ii_read_unlock(inode); -+ } -+ } -+ au_rw_read_unlock(&au_di(d)->di_rwsem); -+} -+ -+void di_downgrade_lock(struct dentry *d, int flags) -+{ -+ if (d_really_is_positive(d) && au_ftest_lock(flags, IR)) -+ ii_downgrade_lock(d_inode(d)); -+ au_rw_dgrade_lock(&au_di(d)->di_rwsem); -+} -+ -+void di_write_lock(struct dentry *d, unsigned int lsc) -+{ -+ au_rw_write_lock_nested(&au_di(d)->di_rwsem, lsc); -+ if (d_really_is_positive(d)) -+ do_ii_write_lock(d_inode(d), lsc); -+} -+ -+void di_write_unlock(struct dentry *d) -+{ -+ au_dbg_verify_dinode(d); -+ if (d_really_is_positive(d)) -+ ii_write_unlock(d_inode(d)); -+ au_rw_write_unlock(&au_di(d)->di_rwsem); -+} -+ -+void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir) -+{ -+ AuDebugOn(d1 == d2 -+ || d_inode(d1) == d_inode(d2) -+ || d1->d_sb != d2->d_sb); -+ -+ if ((isdir && au_test_subdir(d1, d2)) -+ || d1 < d2) { -+ di_write_lock_child(d1); -+ di_write_lock_child2(d2); -+ } else { -+ di_write_lock_child(d2); -+ di_write_lock_child2(d1); -+ } -+} -+ -+void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir) -+{ -+ AuDebugOn(d1 == d2 -+ || d_inode(d1) == d_inode(d2) -+ || d1->d_sb != d2->d_sb); -+ -+ if ((isdir && au_test_subdir(d1, d2)) -+ || d1 < d2) { -+ di_write_lock_parent(d1); -+ di_write_lock_parent2(d2); -+ } else { -+ di_write_lock_parent(d2); -+ di_write_lock_parent2(d1); -+ } -+} -+ -+void di_write_unlock2(struct dentry *d1, struct dentry *d2) -+{ -+ di_write_unlock(d1); -+ if (d_inode(d1) == d_inode(d2)) -+ au_rw_write_unlock(&au_di(d2)->di_rwsem); -+ else -+ di_write_unlock(d2); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex) -+{ -+ struct dentry *d; -+ -+ DiMustAnyLock(dentry); -+ -+ if (au_dbtop(dentry) < 0 || bindex < au_dbtop(dentry)) -+ return NULL; -+ AuDebugOn(bindex < 0); -+ d = au_hdentry(au_di(dentry), bindex)->hd_dentry; -+ AuDebugOn(d && au_dcount(d) <= 0); -+ return d; -+} -+ -+/* -+ * extended version of au_h_dptr(). -+ * returns a hashed and positive (or linkable) h_dentry in bindex, NULL, or -+ * error. -+ */ -+struct dentry *au_h_d_alias(struct dentry *dentry, aufs_bindex_t bindex) -+{ -+ struct dentry *h_dentry; -+ struct inode *inode, *h_inode; -+ -+ AuDebugOn(d_really_is_negative(dentry)); -+ -+ h_dentry = NULL; -+ if (au_dbtop(dentry) <= bindex -+ && bindex <= au_dbbot(dentry)) -+ h_dentry = au_h_dptr(dentry, bindex); -+ if (h_dentry && !au_d_linkable(h_dentry)) { -+ dget(h_dentry); -+ goto out; /* success */ -+ } -+ -+ inode = d_inode(dentry); -+ AuDebugOn(bindex < au_ibtop(inode)); -+ AuDebugOn(au_ibbot(inode) < bindex); -+ h_inode = au_h_iptr(inode, bindex); -+ h_dentry = d_find_alias(h_inode); -+ if (h_dentry) { -+ if (!IS_ERR(h_dentry)) { -+ if (!au_d_linkable(h_dentry)) -+ goto out; /* success */ -+ dput(h_dentry); -+ } else -+ goto out; -+ } -+ -+ if (au_opt_test(au_mntflags(dentry->d_sb), PLINK)) { -+ h_dentry = au_plink_lkup(inode, bindex); -+ AuDebugOn(!h_dentry); -+ if (!IS_ERR(h_dentry)) { -+ if (!au_d_hashed_positive(h_dentry)) -+ goto out; /* success */ -+ dput(h_dentry); -+ h_dentry = NULL; -+ } -+ } -+ -+out: -+ AuDbgDentry(h_dentry); -+ return h_dentry; -+} -+ -+aufs_bindex_t au_dbtail(struct dentry *dentry) -+{ -+ aufs_bindex_t bbot, bwh; -+ -+ bbot = au_dbbot(dentry); -+ if (0 <= bbot) { -+ bwh = au_dbwh(dentry); -+ if (!bwh) -+ return bwh; -+ if (0 < bwh && bwh < bbot) -+ return bwh - 1; -+ } -+ return bbot; -+} -+ -+aufs_bindex_t au_dbtaildir(struct dentry *dentry) -+{ -+ aufs_bindex_t bbot, bopq; -+ -+ bbot = au_dbtail(dentry); -+ if (0 <= bbot) { -+ bopq = au_dbdiropq(dentry); -+ if (0 <= bopq && bopq < bbot) -+ bbot = bopq; -+ } -+ return bbot; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex, -+ struct dentry *h_dentry) -+{ -+ struct au_dinfo *dinfo; -+ struct au_hdentry *hd; -+ struct au_branch *br; -+ -+ DiMustWriteLock(dentry); -+ -+ dinfo = au_di(dentry); -+ hd = au_hdentry(dinfo, bindex); -+ au_hdput(hd); -+ hd->hd_dentry = h_dentry; -+ if (h_dentry) { -+ br = au_sbr(dentry->d_sb, bindex); -+ hd->hd_id = br->br_id; -+ } -+} -+ -+int au_dbrange_test(struct dentry *dentry) -+{ -+ int err; -+ aufs_bindex_t btop, bbot; -+ -+ err = 0; -+ btop = au_dbtop(dentry); -+ bbot = au_dbbot(dentry); -+ if (btop >= 0) -+ AuDebugOn(bbot < 0 && btop > bbot); -+ else { -+ err = -EIO; -+ AuDebugOn(bbot >= 0); -+ } -+ -+ return err; -+} -+ -+int au_digen_test(struct dentry *dentry, unsigned int sigen) -+{ -+ int err; -+ -+ err = 0; -+ if (unlikely(au_digen(dentry) != sigen -+ || au_iigen_test(d_inode(dentry), sigen))) -+ err = -EIO; -+ -+ return err; -+} -+ -+void au_update_digen(struct dentry *dentry) -+{ -+ atomic_set(&au_di(dentry)->di_generation, au_sigen(dentry->d_sb)); -+ /* smp_mb(); */ /* atomic_set */ -+} -+ -+void au_update_dbrange(struct dentry *dentry, int do_put_zero) -+{ -+ struct au_dinfo *dinfo; -+ struct dentry *h_d; -+ struct au_hdentry *hdp; -+ aufs_bindex_t bindex, bbot; -+ -+ DiMustWriteLock(dentry); -+ -+ dinfo = au_di(dentry); -+ if (!dinfo || dinfo->di_btop < 0) -+ return; -+ -+ if (do_put_zero) { -+ bbot = dinfo->di_bbot; -+ bindex = dinfo->di_btop; -+ hdp = au_hdentry(dinfo, bindex); -+ for (; bindex <= bbot; bindex++, hdp++) { -+ h_d = hdp->hd_dentry; -+ if (h_d && d_is_negative(h_d)) -+ au_set_h_dptr(dentry, bindex, NULL); -+ } -+ } -+ -+ dinfo->di_btop = 0; -+ hdp = au_hdentry(dinfo, dinfo->di_btop); -+ for (; dinfo->di_btop <= dinfo->di_bbot; dinfo->di_btop++, hdp++) -+ if (hdp->hd_dentry) -+ break; -+ if (dinfo->di_btop > dinfo->di_bbot) { -+ dinfo->di_btop = -1; -+ dinfo->di_bbot = -1; -+ return; -+ } -+ -+ hdp = au_hdentry(dinfo, dinfo->di_bbot); -+ for (; dinfo->di_bbot >= 0; dinfo->di_bbot--, hdp--) -+ if (hdp->hd_dentry) -+ break; -+ AuDebugOn(dinfo->di_btop > dinfo->di_bbot || dinfo->di_bbot < 0); -+} -+ -+void au_update_dbtop(struct dentry *dentry) -+{ -+ aufs_bindex_t bindex, bbot; -+ struct dentry *h_dentry; -+ -+ bbot = au_dbbot(dentry); -+ for (bindex = au_dbtop(dentry); bindex <= bbot; bindex++) { -+ h_dentry = au_h_dptr(dentry, bindex); -+ if (!h_dentry) -+ continue; -+ if (d_is_positive(h_dentry)) { -+ au_set_dbtop(dentry, bindex); -+ return; -+ } -+ au_set_h_dptr(dentry, bindex, NULL); -+ } -+} -+ -+void au_update_dbbot(struct dentry *dentry) -+{ -+ aufs_bindex_t bindex, btop; -+ struct dentry *h_dentry; -+ -+ btop = au_dbtop(dentry); -+ for (bindex = au_dbbot(dentry); bindex >= btop; bindex--) { -+ h_dentry = au_h_dptr(dentry, bindex); -+ if (!h_dentry) -+ continue; -+ if (d_is_positive(h_dentry)) { -+ au_set_dbbot(dentry, bindex); -+ return; -+ } -+ au_set_h_dptr(dentry, bindex, NULL); -+ } -+} -+ -+int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry) -+{ -+ aufs_bindex_t bindex, bbot; -+ -+ bbot = au_dbbot(dentry); -+ for (bindex = au_dbtop(dentry); bindex <= bbot; bindex++) -+ if (au_h_dptr(dentry, bindex) == h_dentry) -+ return bindex; -+ return -1; -+} -diff --git a/fs/aufs/dir.c b/fs/aufs/dir.c -new file mode 100644 -index 000000000000..44adae19efb1 ---- /dev/null -+++ b/fs/aufs/dir.c -@@ -0,0 +1,750 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * directory operations -+ */ -+ -+#include -+#include -+#include "aufs.h" -+ -+void au_add_nlink(struct inode *dir, struct inode *h_dir) -+{ -+ unsigned int nlink; -+ -+ AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode)); -+ -+ nlink = dir->i_nlink; -+ nlink += h_dir->i_nlink - 2; -+ if (h_dir->i_nlink < 2) -+ nlink += 2; -+ smp_mb(); /* for i_nlink */ -+ /* 0 can happen in revaliding */ -+ set_nlink(dir, nlink); -+} -+ -+void au_sub_nlink(struct inode *dir, struct inode *h_dir) -+{ -+ unsigned int nlink; -+ -+ AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode)); -+ -+ nlink = dir->i_nlink; -+ nlink -= h_dir->i_nlink - 2; -+ if (h_dir->i_nlink < 2) -+ nlink -= 2; -+ smp_mb(); /* for i_nlink */ -+ /* nlink == 0 means the branch-fs is broken */ -+ set_nlink(dir, nlink); -+} -+ -+loff_t au_dir_size(struct file *file, struct dentry *dentry) -+{ -+ loff_t sz; -+ aufs_bindex_t bindex, bbot; -+ struct file *h_file; -+ struct dentry *h_dentry; -+ -+ sz = 0; -+ if (file) { -+ AuDebugOn(!d_is_dir(file->f_path.dentry)); -+ -+ bbot = au_fbbot_dir(file); -+ for (bindex = au_fbtop(file); -+ bindex <= bbot && sz < KMALLOC_MAX_SIZE; -+ bindex++) { -+ h_file = au_hf_dir(file, bindex); -+ if (h_file && file_inode(h_file)) -+ sz += vfsub_f_size_read(h_file); -+ } -+ } else { -+ AuDebugOn(!dentry); -+ AuDebugOn(!d_is_dir(dentry)); -+ -+ bbot = au_dbtaildir(dentry); -+ for (bindex = au_dbtop(dentry); -+ bindex <= bbot && sz < KMALLOC_MAX_SIZE; -+ bindex++) { -+ h_dentry = au_h_dptr(dentry, bindex); -+ if (h_dentry && d_is_positive(h_dentry)) -+ sz += i_size_read(d_inode(h_dentry)); -+ } -+ } -+ if (sz < KMALLOC_MAX_SIZE) -+ sz = roundup_pow_of_two(sz); -+ if (sz > KMALLOC_MAX_SIZE) -+ sz = KMALLOC_MAX_SIZE; -+ else if (sz < NAME_MAX) { -+ BUILD_BUG_ON(AUFS_RDBLK_DEF < NAME_MAX); -+ sz = AUFS_RDBLK_DEF; -+ } -+ return sz; -+} -+ -+struct au_dir_ts_arg { -+ struct dentry *dentry; -+ aufs_bindex_t brid; -+}; -+ -+static void au_do_dir_ts(void *arg) -+{ -+ struct au_dir_ts_arg *a = arg; -+ struct au_dtime dt; -+ struct path h_path; -+ struct inode *dir, *h_dir; -+ struct super_block *sb; -+ struct au_branch *br; -+ struct au_hinode *hdir; -+ int err; -+ aufs_bindex_t btop, bindex; -+ -+ sb = a->dentry->d_sb; -+ if (d_really_is_negative(a->dentry)) -+ goto out; -+ /* no dir->i_mutex lock */ -+ aufs_read_lock(a->dentry, AuLock_DW); /* noflush */ -+ -+ dir = d_inode(a->dentry); -+ btop = au_ibtop(dir); -+ bindex = au_br_index(sb, a->brid); -+ if (bindex < btop) -+ goto out_unlock; -+ -+ br = au_sbr(sb, bindex); -+ h_path.dentry = au_h_dptr(a->dentry, bindex); -+ if (!h_path.dentry) -+ goto out_unlock; -+ h_path.mnt = au_br_mnt(br); -+ au_dtime_store(&dt, a->dentry, &h_path); -+ -+ br = au_sbr(sb, btop); -+ if (!au_br_writable(br->br_perm)) -+ goto out_unlock; -+ h_path.dentry = au_h_dptr(a->dentry, btop); -+ h_path.mnt = au_br_mnt(br); -+ err = vfsub_mnt_want_write(h_path.mnt); -+ if (err) -+ goto out_unlock; -+ hdir = au_hi(dir, btop); -+ au_hn_inode_lock_nested(hdir, AuLsc_I_PARENT); -+ h_dir = au_h_iptr(dir, btop); -+ if (h_dir->i_nlink -+ && timespec64_compare(&h_dir->i_mtime, &dt.dt_mtime) < 0) { -+ dt.dt_h_path = h_path; -+ au_dtime_revert(&dt); -+ } -+ au_hn_inode_unlock(hdir); -+ vfsub_mnt_drop_write(h_path.mnt); -+ au_cpup_attr_timesizes(dir); -+ -+out_unlock: -+ aufs_read_unlock(a->dentry, AuLock_DW); -+out: -+ dput(a->dentry); -+ au_nwt_done(&au_sbi(sb)->si_nowait); -+ au_kfree_try_rcu(arg); -+} -+ -+void au_dir_ts(struct inode *dir, aufs_bindex_t bindex) -+{ -+ int perm, wkq_err; -+ aufs_bindex_t btop; -+ struct au_dir_ts_arg *arg; -+ struct dentry *dentry; -+ struct super_block *sb; -+ -+ IMustLock(dir); -+ -+ dentry = d_find_any_alias(dir); -+ AuDebugOn(!dentry); -+ sb = dentry->d_sb; -+ btop = au_ibtop(dir); -+ if (btop == bindex) { -+ au_cpup_attr_timesizes(dir); -+ goto out; -+ } -+ -+ perm = au_sbr_perm(sb, btop); -+ if (!au_br_writable(perm)) -+ goto out; -+ -+ arg = kmalloc(sizeof(*arg), GFP_NOFS); -+ if (!arg) -+ goto out; -+ -+ arg->dentry = dget(dentry); /* will be dput-ted by au_do_dir_ts() */ -+ arg->brid = au_sbr_id(sb, bindex); -+ wkq_err = au_wkq_nowait(au_do_dir_ts, arg, sb, /*flags*/0); -+ if (unlikely(wkq_err)) { -+ pr_err("wkq %d\n", wkq_err); -+ dput(dentry); -+ au_kfree_try_rcu(arg); -+ } -+ -+out: -+ dput(dentry); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int reopen_dir(struct file *file) -+{ -+ int err; -+ unsigned int flags; -+ aufs_bindex_t bindex, btail, btop; -+ struct dentry *dentry, *h_dentry; -+ struct file *h_file; -+ -+ /* open all lower dirs */ -+ dentry = file->f_path.dentry; -+ btop = au_dbtop(dentry); -+ for (bindex = au_fbtop(file); bindex < btop; bindex++) -+ au_set_h_fptr(file, bindex, NULL); -+ au_set_fbtop(file, btop); -+ -+ btail = au_dbtaildir(dentry); -+ for (bindex = au_fbbot_dir(file); btail < bindex; bindex--) -+ au_set_h_fptr(file, bindex, NULL); -+ au_set_fbbot_dir(file, btail); -+ -+ flags = vfsub_file_flags(file); -+ for (bindex = btop; bindex <= btail; bindex++) { -+ h_dentry = au_h_dptr(dentry, bindex); -+ if (!h_dentry) -+ continue; -+ h_file = au_hf_dir(file, bindex); -+ if (h_file) -+ continue; -+ -+ h_file = au_h_open(dentry, bindex, flags, file, /*force_wr*/0); -+ err = PTR_ERR(h_file); -+ if (IS_ERR(h_file)) -+ goto out; /* close all? */ -+ au_set_h_fptr(file, bindex, h_file); -+ } -+ au_update_figen(file); -+ /* todo: necessary? */ -+ /* file->f_ra = h_file->f_ra; */ -+ err = 0; -+ -+out: -+ return err; -+} -+ -+static int do_open_dir(struct file *file, int flags, struct file *h_file) -+{ -+ int err; -+ aufs_bindex_t bindex, btail; -+ struct dentry *dentry, *h_dentry; -+ struct vfsmount *mnt; -+ -+ FiMustWriteLock(file); -+ AuDebugOn(h_file); -+ -+ err = 0; -+ mnt = file->f_path.mnt; -+ dentry = file->f_path.dentry; -+ file->f_version = inode_query_iversion(d_inode(dentry)); -+ bindex = au_dbtop(dentry); -+ au_set_fbtop(file, bindex); -+ btail = au_dbtaildir(dentry); -+ au_set_fbbot_dir(file, btail); -+ for (; !err && bindex <= btail; bindex++) { -+ h_dentry = au_h_dptr(dentry, bindex); -+ if (!h_dentry) -+ continue; -+ -+ err = vfsub_test_mntns(mnt, h_dentry->d_sb); -+ if (unlikely(err)) -+ break; -+ h_file = au_h_open(dentry, bindex, flags, file, /*force_wr*/0); -+ if (IS_ERR(h_file)) { -+ err = PTR_ERR(h_file); -+ break; -+ } -+ au_set_h_fptr(file, bindex, h_file); -+ } -+ au_update_figen(file); -+ /* todo: necessary? */ -+ /* file->f_ra = h_file->f_ra; */ -+ if (!err) -+ return 0; /* success */ -+ -+ /* close all */ -+ for (bindex = au_fbtop(file); bindex <= btail; bindex++) -+ au_set_h_fptr(file, bindex, NULL); -+ au_set_fbtop(file, -1); -+ au_set_fbbot_dir(file, -1); -+ -+ return err; -+} -+ -+static int aufs_open_dir(struct inode *inode __maybe_unused, -+ struct file *file) -+{ -+ int err; -+ struct super_block *sb; -+ struct au_fidir *fidir; -+ -+ err = -ENOMEM; -+ sb = file->f_path.dentry->d_sb; -+ si_read_lock(sb, AuLock_FLUSH); -+ fidir = au_fidir_alloc(sb); -+ if (fidir) { -+ struct au_do_open_args args = { -+ .open = do_open_dir, -+ .fidir = fidir -+ }; -+ err = au_do_open(file, &args); -+ if (unlikely(err)) -+ au_kfree_rcu(fidir); -+ } -+ si_read_unlock(sb); -+ return err; -+} -+ -+static int aufs_release_dir(struct inode *inode __maybe_unused, -+ struct file *file) -+{ -+ struct au_vdir *vdir_cache; -+ struct au_finfo *finfo; -+ struct au_fidir *fidir; -+ struct au_hfile *hf; -+ aufs_bindex_t bindex, bbot; -+ -+ finfo = au_fi(file); -+ fidir = finfo->fi_hdir; -+ if (fidir) { -+ au_hbl_del(&finfo->fi_hlist, -+ &au_sbi(file->f_path.dentry->d_sb)->si_files); -+ vdir_cache = fidir->fd_vdir_cache; /* lock-free */ -+ if (vdir_cache) -+ au_vdir_free(vdir_cache); -+ -+ bindex = finfo->fi_btop; -+ if (bindex >= 0) { -+ hf = fidir->fd_hfile + bindex; -+ /* -+ * calls fput() instead of filp_close(), -+ * since no dnotify or lock for the lower file. -+ */ -+ bbot = fidir->fd_bbot; -+ for (; bindex <= bbot; bindex++, hf++) -+ if (hf->hf_file) -+ au_hfput(hf, /*execed*/0); -+ } -+ au_kfree_rcu(fidir); -+ finfo->fi_hdir = NULL; -+ } -+ au_finfo_fin(file); -+ return 0; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int au_do_flush_dir(struct file *file, fl_owner_t id) -+{ -+ int err; -+ aufs_bindex_t bindex, bbot; -+ struct file *h_file; -+ -+ err = 0; -+ bbot = au_fbbot_dir(file); -+ for (bindex = au_fbtop(file); !err && bindex <= bbot; bindex++) { -+ h_file = au_hf_dir(file, bindex); -+ if (h_file) -+ err = vfsub_flush(h_file, id); -+ } -+ return err; -+} -+ -+static int aufs_flush_dir(struct file *file, fl_owner_t id) -+{ -+ return au_do_flush(file, id, au_do_flush_dir); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int au_do_fsync_dir_no_file(struct dentry *dentry, int datasync) -+{ -+ int err; -+ aufs_bindex_t bbot, bindex; -+ struct inode *inode; -+ struct super_block *sb; -+ -+ err = 0; -+ sb = dentry->d_sb; -+ inode = d_inode(dentry); -+ IMustLock(inode); -+ bbot = au_dbbot(dentry); -+ for (bindex = au_dbtop(dentry); !err && bindex <= bbot; bindex++) { -+ struct path h_path; -+ -+ if (au_test_ro(sb, bindex, inode)) -+ continue; -+ h_path.dentry = au_h_dptr(dentry, bindex); -+ if (!h_path.dentry) -+ continue; -+ -+ h_path.mnt = au_sbr_mnt(sb, bindex); -+ err = vfsub_fsync(NULL, &h_path, datasync); -+ } -+ -+ return err; -+} -+ -+static int au_do_fsync_dir(struct file *file, int datasync) -+{ -+ int err; -+ aufs_bindex_t bbot, bindex; -+ struct file *h_file; -+ struct super_block *sb; -+ struct inode *inode; -+ -+ err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1, /*fi_lsc*/0); -+ if (unlikely(err)) -+ goto out; -+ -+ inode = file_inode(file); -+ sb = inode->i_sb; -+ bbot = au_fbbot_dir(file); -+ for (bindex = au_fbtop(file); !err && bindex <= bbot; bindex++) { -+ h_file = au_hf_dir(file, bindex); -+ if (!h_file || au_test_ro(sb, bindex, inode)) -+ continue; -+ -+ err = vfsub_fsync(h_file, &h_file->f_path, datasync); -+ } -+ -+out: -+ return err; -+} -+ -+/* -+ * @file may be NULL -+ */ -+static int aufs_fsync_dir(struct file *file, loff_t start, loff_t end, -+ int datasync) -+{ -+ int err; -+ struct dentry *dentry; -+ struct inode *inode; -+ struct super_block *sb; -+ -+ err = 0; -+ dentry = file->f_path.dentry; -+ inode = d_inode(dentry); -+ inode_lock(inode); -+ sb = dentry->d_sb; -+ si_noflush_read_lock(sb); -+ if (file) -+ err = au_do_fsync_dir(file, datasync); -+ else { -+ di_write_lock_child(dentry); -+ err = au_do_fsync_dir_no_file(dentry, datasync); -+ } -+ au_cpup_attr_timesizes(inode); -+ di_write_unlock(dentry); -+ if (file) -+ fi_write_unlock(file); -+ -+ si_read_unlock(sb); -+ inode_unlock(inode); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int aufs_iterate_shared(struct file *file, struct dir_context *ctx) -+{ -+ int err; -+ struct dentry *dentry; -+ struct inode *inode, *h_inode; -+ struct super_block *sb; -+ -+ AuDbg("%pD, ctx{%ps, %llu}\n", file, ctx->actor, ctx->pos); -+ -+ dentry = file->f_path.dentry; -+ inode = d_inode(dentry); -+ IMustLock(inode); -+ -+ sb = dentry->d_sb; -+ si_read_lock(sb, AuLock_FLUSH); -+ err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1, /*fi_lsc*/0); -+ if (unlikely(err)) -+ goto out; -+ err = au_alive_dir(dentry); -+ if (!err) -+ err = au_vdir_init(file); -+ di_downgrade_lock(dentry, AuLock_IR); -+ if (unlikely(err)) -+ goto out_unlock; -+ -+ h_inode = au_h_iptr(inode, au_ibtop(inode)); -+ if (!au_test_nfsd()) { -+ err = au_vdir_fill_de(file, ctx); -+ fsstack_copy_attr_atime(inode, h_inode); -+ } else { -+ /* -+ * nfsd filldir may call lookup_one_len(), vfs_getattr(), -+ * encode_fh() and others. -+ */ -+ atomic_inc(&h_inode->i_count); -+ di_read_unlock(dentry, AuLock_IR); -+ si_read_unlock(sb); -+ err = au_vdir_fill_de(file, ctx); -+ fsstack_copy_attr_atime(inode, h_inode); -+ fi_write_unlock(file); -+ iput(h_inode); -+ -+ AuTraceErr(err); -+ return err; -+ } -+ -+out_unlock: -+ di_read_unlock(dentry, AuLock_IR); -+ fi_write_unlock(file); -+out: -+ si_read_unlock(sb); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+#define AuTestEmpty_WHONLY 1 -+#define AuTestEmpty_CALLED (1 << 1) -+#define AuTestEmpty_SHWH (1 << 2) -+#define au_ftest_testempty(flags, name) ((flags) & AuTestEmpty_##name) -+#define au_fset_testempty(flags, name) \ -+ do { (flags) |= AuTestEmpty_##name; } while (0) -+#define au_fclr_testempty(flags, name) \ -+ do { (flags) &= ~AuTestEmpty_##name; } while (0) -+ -+#ifndef CONFIG_AUFS_SHWH -+#undef AuTestEmpty_SHWH -+#define AuTestEmpty_SHWH 0 -+#endif -+ -+struct test_empty_arg { -+ struct dir_context ctx; -+ struct au_nhash *whlist; -+ unsigned int flags; -+ int err; -+ aufs_bindex_t bindex; -+}; -+ -+static int test_empty_cb(struct dir_context *ctx, const char *__name, -+ int namelen, loff_t offset __maybe_unused, u64 ino, -+ unsigned int d_type) -+{ -+ struct test_empty_arg *arg = container_of(ctx, struct test_empty_arg, -+ ctx); -+ char *name = (void *)__name; -+ -+ arg->err = 0; -+ au_fset_testempty(arg->flags, CALLED); -+ /* smp_mb(); */ -+ if (name[0] == '.' -+ && (namelen == 1 || (name[1] == '.' && namelen == 2))) -+ goto out; /* success */ -+ -+ if (namelen <= AUFS_WH_PFX_LEN -+ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) { -+ if (au_ftest_testempty(arg->flags, WHONLY) -+ && !au_nhash_test_known_wh(arg->whlist, name, namelen)) -+ arg->err = -ENOTEMPTY; -+ goto out; -+ } -+ -+ name += AUFS_WH_PFX_LEN; -+ namelen -= AUFS_WH_PFX_LEN; -+ if (!au_nhash_test_known_wh(arg->whlist, name, namelen)) -+ arg->err = au_nhash_append_wh -+ (arg->whlist, name, namelen, ino, d_type, arg->bindex, -+ au_ftest_testempty(arg->flags, SHWH)); -+ -+out: -+ /* smp_mb(); */ -+ AuTraceErr(arg->err); -+ return arg->err; -+} -+ -+static int do_test_empty(struct dentry *dentry, struct test_empty_arg *arg) -+{ -+ int err; -+ struct file *h_file; -+ struct au_branch *br; -+ -+ h_file = au_h_open(dentry, arg->bindex, -+ O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_LARGEFILE, -+ /*file*/NULL, /*force_wr*/0); -+ err = PTR_ERR(h_file); -+ if (IS_ERR(h_file)) -+ goto out; -+ -+ err = 0; -+ if (!au_opt_test(au_mntflags(dentry->d_sb), UDBA_NONE) -+ && !file_inode(h_file)->i_nlink) -+ goto out_put; -+ -+ do { -+ arg->err = 0; -+ au_fclr_testempty(arg->flags, CALLED); -+ /* smp_mb(); */ -+ err = vfsub_iterate_dir(h_file, &arg->ctx); -+ if (err >= 0) -+ err = arg->err; -+ } while (!err && au_ftest_testempty(arg->flags, CALLED)); -+ -+out_put: -+ fput(h_file); -+ br = au_sbr(dentry->d_sb, arg->bindex); -+ au_lcnt_dec(&br->br_nfiles); -+out: -+ return err; -+} -+ -+struct do_test_empty_args { -+ int *errp; -+ struct dentry *dentry; -+ struct test_empty_arg *arg; -+}; -+ -+static void call_do_test_empty(void *args) -+{ -+ struct do_test_empty_args *a = args; -+ *a->errp = do_test_empty(a->dentry, a->arg); -+} -+ -+static int sio_test_empty(struct dentry *dentry, struct test_empty_arg *arg) -+{ -+ int err, wkq_err; -+ struct dentry *h_dentry; -+ struct inode *h_inode; -+ -+ h_dentry = au_h_dptr(dentry, arg->bindex); -+ h_inode = d_inode(h_dentry); -+ /* todo: i_mode changes anytime? */ -+ inode_lock_shared_nested(h_inode, AuLsc_I_CHILD); -+ err = au_test_h_perm_sio(h_inode, MAY_EXEC | MAY_READ); -+ inode_unlock_shared(h_inode); -+ if (!err) -+ err = do_test_empty(dentry, arg); -+ else { -+ struct do_test_empty_args args = { -+ .errp = &err, -+ .dentry = dentry, -+ .arg = arg -+ }; -+ unsigned int flags = arg->flags; -+ -+ wkq_err = au_wkq_wait(call_do_test_empty, &args); -+ if (unlikely(wkq_err)) -+ err = wkq_err; -+ arg->flags = flags; -+ } -+ -+ return err; -+} -+ -+int au_test_empty_lower(struct dentry *dentry) -+{ -+ int err; -+ unsigned int rdhash; -+ aufs_bindex_t bindex, btop, btail; -+ struct au_nhash whlist; -+ struct test_empty_arg arg = { -+ .ctx = { -+ .actor = test_empty_cb -+ } -+ }; -+ int (*test_empty)(struct dentry *dentry, struct test_empty_arg *arg); -+ -+ SiMustAnyLock(dentry->d_sb); -+ -+ rdhash = au_sbi(dentry->d_sb)->si_rdhash; -+ if (!rdhash) -+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, dentry)); -+ err = au_nhash_alloc(&whlist, rdhash, GFP_NOFS); -+ if (unlikely(err)) -+ goto out; -+ -+ arg.flags = 0; -+ arg.whlist = &whlist; -+ btop = au_dbtop(dentry); -+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH)) -+ au_fset_testempty(arg.flags, SHWH); -+ test_empty = do_test_empty; -+ if (au_opt_test(au_mntflags(dentry->d_sb), DIRPERM1)) -+ test_empty = sio_test_empty; -+ arg.bindex = btop; -+ err = test_empty(dentry, &arg); -+ if (unlikely(err)) -+ goto out_whlist; -+ -+ au_fset_testempty(arg.flags, WHONLY); -+ btail = au_dbtaildir(dentry); -+ for (bindex = btop + 1; !err && bindex <= btail; bindex++) { -+ struct dentry *h_dentry; -+ -+ h_dentry = au_h_dptr(dentry, bindex); -+ if (h_dentry && d_is_positive(h_dentry)) { -+ arg.bindex = bindex; -+ err = test_empty(dentry, &arg); -+ } -+ } -+ -+out_whlist: -+ au_nhash_wh_free(&whlist); -+out: -+ return err; -+} -+ -+int au_test_empty(struct dentry *dentry, struct au_nhash *whlist) -+{ -+ int err; -+ struct test_empty_arg arg = { -+ .ctx = { -+ .actor = test_empty_cb -+ } -+ }; -+ aufs_bindex_t bindex, btail; -+ -+ err = 0; -+ arg.whlist = whlist; -+ arg.flags = AuTestEmpty_WHONLY; -+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH)) -+ au_fset_testempty(arg.flags, SHWH); -+ btail = au_dbtaildir(dentry); -+ for (bindex = au_dbtop(dentry); !err && bindex <= btail; bindex++) { -+ struct dentry *h_dentry; -+ -+ h_dentry = au_h_dptr(dentry, bindex); -+ if (h_dentry && d_is_positive(h_dentry)) { -+ arg.bindex = bindex; -+ err = sio_test_empty(dentry, &arg); -+ } -+ } -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+const struct file_operations aufs_dir_fop = { -+ .owner = THIS_MODULE, -+ .llseek = default_llseek, -+ .read = generic_read_dir, -+ .iterate_shared = aufs_iterate_shared, -+ .unlocked_ioctl = aufs_ioctl_dir, -+#ifdef CONFIG_COMPAT -+ .compat_ioctl = aufs_compat_ioctl_dir, -+#endif -+ .open = aufs_open_dir, -+ .release = aufs_release_dir, -+ .flush = aufs_flush_dir, -+ .fsync = aufs_fsync_dir -+}; -diff --git a/fs/aufs/dir.h b/fs/aufs/dir.h -new file mode 100644 -index 000000000000..75fad78d2278 ---- /dev/null -+++ b/fs/aufs/dir.h -@@ -0,0 +1,121 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * directory operations -+ */ -+ -+#ifndef __AUFS_DIR_H__ -+#define __AUFS_DIR_H__ -+ -+#ifdef __KERNEL__ -+ -+#include -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* need to be faster and smaller */ -+ -+struct au_nhash { -+ unsigned int nh_num; -+ struct hlist_head *nh_head; -+}; -+ -+struct au_vdir_destr { -+ unsigned char len; -+ unsigned char name[]; -+} __packed; -+ -+struct au_vdir_dehstr { -+ struct hlist_node hash; -+ struct au_vdir_destr *str; -+ struct rcu_head rcu; -+} ____cacheline_aligned_in_smp; -+ -+struct au_vdir_de { -+ ino_t de_ino; -+ unsigned char de_type; -+ /* caution: packed */ -+ struct au_vdir_destr de_str; -+} __packed; -+ -+struct au_vdir_wh { -+ struct hlist_node wh_hash; -+#ifdef CONFIG_AUFS_SHWH -+ ino_t wh_ino; -+ aufs_bindex_t wh_bindex; -+ unsigned char wh_type; -+#else -+ aufs_bindex_t wh_bindex; -+#endif -+ /* caution: packed */ -+ struct au_vdir_destr wh_str; -+} __packed; -+ -+union au_vdir_deblk_p { -+ unsigned char *deblk; -+ struct au_vdir_de *de; -+}; -+ -+struct au_vdir { -+ unsigned char **vd_deblk; -+ unsigned long vd_nblk; -+ struct { -+ unsigned long ul; -+ union au_vdir_deblk_p p; -+ } vd_last; -+ -+ u64 vd_version; -+ unsigned int vd_deblk_sz; -+ unsigned long vd_jiffy; -+ struct rcu_head rcu; -+} ____cacheline_aligned_in_smp; -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* dir.c */ -+extern const struct file_operations aufs_dir_fop; -+void au_add_nlink(struct inode *dir, struct inode *h_dir); -+void au_sub_nlink(struct inode *dir, struct inode *h_dir); -+loff_t au_dir_size(struct file *file, struct dentry *dentry); -+void au_dir_ts(struct inode *dir, aufs_bindex_t bsrc); -+int au_test_empty_lower(struct dentry *dentry); -+int au_test_empty(struct dentry *dentry, struct au_nhash *whlist); -+ -+/* vdir.c */ -+unsigned int au_rdhash_est(loff_t sz); -+int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp); -+void au_nhash_wh_free(struct au_nhash *whlist); -+int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt, -+ int limit); -+int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen); -+int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino, -+ unsigned int d_type, aufs_bindex_t bindex, -+ unsigned char shwh); -+void au_vdir_free(struct au_vdir *vdir); -+int au_vdir_init(struct file *file); -+int au_vdir_fill_de(struct file *file, struct dir_context *ctx); -+ -+/* ioctl.c */ -+long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg); -+ -+#ifdef CONFIG_AUFS_RDU -+/* rdu.c */ -+long au_rdu_ioctl(struct file *file, unsigned int cmd, unsigned long arg); -+#ifdef CONFIG_COMPAT -+long au_rdu_compat_ioctl(struct file *file, unsigned int cmd, -+ unsigned long arg); -+#endif -+#else -+AuStub(long, au_rdu_ioctl, return -EINVAL, struct file *file, -+ unsigned int cmd, unsigned long arg) -+#ifdef CONFIG_COMPAT -+AuStub(long, au_rdu_compat_ioctl, return -EINVAL, struct file *file, -+ unsigned int cmd, unsigned long arg) -+#endif -+#endif -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_DIR_H__ */ -diff --git a/fs/aufs/dirren.c b/fs/aufs/dirren.c -new file mode 100644 -index 000000000000..12b56c47f2dd ---- /dev/null -+++ b/fs/aufs/dirren.c -@@ -0,0 +1,1303 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2017-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * special handling in renaming a directory -+ * in order to support looking-up the before-renamed name on the lower readonly -+ * branches -+ */ -+ -+#include -+#include "aufs.h" -+ -+static void au_dr_hino_del(struct au_dr_br *dr, struct au_dr_hino *ent) -+{ -+ int idx; -+ -+ idx = au_dr_ihash(ent->dr_h_ino); -+ au_hbl_del(&ent->dr_hnode, dr->dr_h_ino + idx); -+} -+ -+static int au_dr_hino_test_empty(struct au_dr_br *dr) -+{ -+ int ret, i; -+ struct hlist_bl_head *hbl; -+ -+ ret = 1; -+ for (i = 0; ret && i < AuDirren_NHASH; i++) { -+ hbl = dr->dr_h_ino + i; -+ hlist_bl_lock(hbl); -+ ret &= hlist_bl_empty(hbl); -+ hlist_bl_unlock(hbl); -+ } -+ -+ return ret; -+} -+ -+static struct au_dr_hino *au_dr_hino_find(struct au_dr_br *dr, ino_t ino) -+{ -+ struct au_dr_hino *found, *ent; -+ struct hlist_bl_head *hbl; -+ struct hlist_bl_node *pos; -+ int idx; -+ -+ found = NULL; -+ idx = au_dr_ihash(ino); -+ hbl = dr->dr_h_ino + idx; -+ hlist_bl_lock(hbl); -+ hlist_bl_for_each_entry(ent, pos, hbl, dr_hnode) -+ if (ent->dr_h_ino == ino) { -+ found = ent; -+ break; -+ } -+ hlist_bl_unlock(hbl); -+ -+ return found; -+} -+ -+int au_dr_hino_test_add(struct au_dr_br *dr, ino_t ino, -+ struct au_dr_hino *add_ent) -+{ -+ int found, idx; -+ struct hlist_bl_head *hbl; -+ struct hlist_bl_node *pos; -+ struct au_dr_hino *ent; -+ -+ found = 0; -+ idx = au_dr_ihash(ino); -+ hbl = dr->dr_h_ino + idx; -+#if 0 /* debug print */ -+ { -+ struct hlist_bl_node *tmp; -+ -+ hlist_bl_for_each_entry_safe(ent, pos, tmp, hbl, dr_hnode) -+ AuDbg("hi%llu\n", (unsigned long long)ent->dr_h_ino); -+ } -+#endif -+ hlist_bl_lock(hbl); -+ hlist_bl_for_each_entry(ent, pos, hbl, dr_hnode) -+ if (ent->dr_h_ino == ino) { -+ found = 1; -+ break; -+ } -+ if (!found && add_ent) -+ hlist_bl_add_head(&add_ent->dr_hnode, hbl); -+ hlist_bl_unlock(hbl); -+ -+ if (!found && add_ent) -+ AuDbg("i%llu added\n", (unsigned long long)add_ent->dr_h_ino); -+ -+ return found; -+} -+ -+void au_dr_hino_free(struct au_dr_br *dr) -+{ -+ int i; -+ struct hlist_bl_head *hbl; -+ struct hlist_bl_node *pos, *tmp; -+ struct au_dr_hino *ent; -+ -+ /* SiMustWriteLock(sb); */ -+ -+ for (i = 0; i < AuDirren_NHASH; i++) { -+ hbl = dr->dr_h_ino + i; -+ /* no spinlock since sbinfo must be write-locked */ -+ hlist_bl_for_each_entry_safe(ent, pos, tmp, hbl, dr_hnode) -+ au_kfree_rcu(ent); -+ INIT_HLIST_BL_HEAD(hbl); -+ } -+} -+ -+/* returns the number of inodes or an error */ -+static int au_dr_hino_store(struct super_block *sb, struct au_branch *br, -+ struct file *hinofile) -+{ -+ int err, i; -+ ssize_t ssz; -+ loff_t pos, oldsize; -+ __be64 u64; -+ struct inode *hinoinode; -+ struct hlist_bl_head *hbl; -+ struct hlist_bl_node *n1, *n2; -+ struct au_dr_hino *ent; -+ -+ SiMustWriteLock(sb); -+ AuDebugOn(!au_br_writable(br->br_perm)); -+ -+ hinoinode = file_inode(hinofile); -+ oldsize = i_size_read(hinoinode); -+ -+ err = 0; -+ pos = 0; -+ hbl = br->br_dirren.dr_h_ino; -+ for (i = 0; !err && i < AuDirren_NHASH; i++, hbl++) { -+ /* no bit-lock since sbinfo must be write-locked */ -+ hlist_bl_for_each_entry_safe(ent, n1, n2, hbl, dr_hnode) { -+ AuDbg("hi%llu, %pD2\n", -+ (unsigned long long)ent->dr_h_ino, hinofile); -+ u64 = cpu_to_be64(ent->dr_h_ino); -+ ssz = vfsub_write_k(hinofile, &u64, sizeof(u64), &pos); -+ if (ssz == sizeof(u64)) -+ continue; -+ -+ /* write error */ -+ pr_err("ssz %zd, %pD2\n", ssz, hinofile); -+ err = -ENOSPC; -+ if (ssz < 0) -+ err = ssz; -+ break; -+ } -+ } -+ /* regardless the error */ -+ if (pos < oldsize) { -+ err = vfsub_trunc(&hinofile->f_path, pos, /*attr*/0, hinofile); -+ AuTraceErr(err); -+ } -+ -+ AuTraceErr(err); -+ return err; -+} -+ -+static int au_dr_hino_load(struct au_dr_br *dr, struct file *hinofile) -+{ -+ int err, hidx; -+ ssize_t ssz; -+ size_t sz, n; -+ loff_t pos; -+ uint64_t u64; -+ struct au_dr_hino *ent; -+ struct inode *hinoinode; -+ struct hlist_bl_head *hbl; -+ -+ err = 0; -+ pos = 0; -+ hbl = dr->dr_h_ino; -+ hinoinode = file_inode(hinofile); -+ sz = i_size_read(hinoinode); -+ AuDebugOn(sz % sizeof(u64)); -+ n = sz / sizeof(u64); -+ while (n--) { -+ ssz = vfsub_read_k(hinofile, &u64, sizeof(u64), &pos); -+ if (unlikely(ssz != sizeof(u64))) { -+ pr_err("ssz %zd, %pD2\n", ssz, hinofile); -+ err = -EINVAL; -+ if (ssz < 0) -+ err = ssz; -+ goto out_free; -+ } -+ -+ ent = kmalloc(sizeof(*ent), GFP_NOFS); -+ if (!ent) { -+ err = -ENOMEM; -+ AuTraceErr(err); -+ goto out_free; -+ } -+ ent->dr_h_ino = be64_to_cpu((__force __be64)u64); -+ AuDbg("hi%llu, %pD2\n", -+ (unsigned long long)ent->dr_h_ino, hinofile); -+ hidx = au_dr_ihash(ent->dr_h_ino); -+ au_hbl_add(&ent->dr_hnode, hbl + hidx); -+ } -+ goto out; /* success */ -+ -+out_free: -+ au_dr_hino_free(dr); -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+/* -+ * @bindex/@br is a switch to distinguish whether suspending hnotify or not. -+ * @path is a switch to distinguish load and store. -+ */ -+static int au_dr_hino(struct super_block *sb, aufs_bindex_t bindex, -+ struct au_branch *br, const struct path *path) -+{ -+ int err, flags; -+ unsigned char load, suspend; -+ struct file *hinofile; -+ struct au_hinode *hdir; -+ struct inode *dir, *delegated; -+ struct path hinopath; -+ struct qstr hinoname = QSTR_INIT(AUFS_WH_DR_BRHINO, -+ sizeof(AUFS_WH_DR_BRHINO) - 1); -+ -+ AuDebugOn(bindex < 0 && !br); -+ AuDebugOn(bindex >= 0 && br); -+ -+ err = -EINVAL; -+ suspend = !br; -+ if (suspend) -+ br = au_sbr(sb, bindex); -+ load = !!path; -+ if (!load) { -+ path = &br->br_path; -+ AuDebugOn(!au_br_writable(br->br_perm)); -+ if (unlikely(!au_br_writable(br->br_perm))) -+ goto out; -+ } -+ -+ hdir = NULL; -+ if (suspend) { -+ dir = d_inode(sb->s_root); -+ hdir = au_hinode(au_ii(dir), bindex); -+ dir = hdir->hi_inode; -+ au_hn_inode_lock_nested(hdir, AuLsc_I_CHILD); -+ } else { -+ dir = d_inode(path->dentry); -+ inode_lock_nested(dir, AuLsc_I_CHILD); -+ } -+ hinopath.dentry = vfsub_lkup_one(&hinoname, path->dentry); -+ err = PTR_ERR(hinopath.dentry); -+ if (IS_ERR(hinopath.dentry)) -+ goto out_unlock; -+ -+ err = 0; -+ flags = O_RDONLY; -+ if (load) { -+ if (d_is_negative(hinopath.dentry)) -+ goto out_dput; /* success */ -+ } else { -+ if (au_dr_hino_test_empty(&br->br_dirren)) { -+ if (d_is_positive(hinopath.dentry)) { -+ delegated = NULL; -+ err = vfsub_unlink(dir, &hinopath, &delegated, -+ /*force*/0); -+ AuTraceErr(err); -+ if (unlikely(err)) -+ pr_err("ignored err %d, %pd2\n", -+ err, hinopath.dentry); -+ if (unlikely(err == -EWOULDBLOCK)) -+ iput(delegated); -+ err = 0; -+ } -+ goto out_dput; -+ } else if (!d_is_positive(hinopath.dentry)) { -+ err = vfsub_create(dir, &hinopath, 0600, -+ /*want_excl*/false); -+ AuTraceErr(err); -+ if (unlikely(err)) -+ goto out_dput; -+ } -+ flags = O_WRONLY; -+ } -+ hinopath.mnt = path->mnt; -+ hinofile = vfsub_dentry_open(&hinopath, flags); -+ if (suspend) -+ au_hn_inode_unlock(hdir); -+ else -+ inode_unlock(dir); -+ dput(hinopath.dentry); -+ AuTraceErrPtr(hinofile); -+ if (IS_ERR(hinofile)) { -+ err = PTR_ERR(hinofile); -+ goto out; -+ } -+ -+ if (load) -+ err = au_dr_hino_load(&br->br_dirren, hinofile); -+ else -+ err = au_dr_hino_store(sb, br, hinofile); -+ fput(hinofile); -+ goto out; -+ -+out_dput: -+ dput(hinopath.dentry); -+out_unlock: -+ if (suspend) -+ au_hn_inode_unlock(hdir); -+ else -+ inode_unlock(dir); -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int au_dr_brid_init(struct au_dr_brid *brid, const struct path *path) -+{ -+ int err; -+ struct kstatfs kstfs; -+ dev_t dev; -+ struct dentry *dentry; -+ struct super_block *sb; -+ -+ err = vfs_statfs((void *)path, &kstfs); -+ AuTraceErr(err); -+ if (unlikely(err)) -+ goto out; -+ -+ /* todo: support for UUID */ -+ -+ if (kstfs.f_fsid.val[0] || kstfs.f_fsid.val[1]) { -+ brid->type = AuBrid_FSID; -+ brid->fsid = kstfs.f_fsid; -+ } else { -+ dentry = path->dentry; -+ sb = dentry->d_sb; -+ dev = sb->s_dev; -+ if (dev) { -+ brid->type = AuBrid_DEV; -+ brid->dev = dev; -+ } -+ } -+ -+out: -+ return err; -+} -+ -+int au_dr_br_init(struct super_block *sb, struct au_branch *br, -+ const struct path *path) -+{ -+ int err, i; -+ struct au_dr_br *dr; -+ struct hlist_bl_head *hbl; -+ -+ dr = &br->br_dirren; -+ hbl = dr->dr_h_ino; -+ for (i = 0; i < AuDirren_NHASH; i++, hbl++) -+ INIT_HLIST_BL_HEAD(hbl); -+ -+ err = au_dr_brid_init(&dr->dr_brid, path); -+ if (unlikely(err)) -+ goto out; -+ -+ if (au_opt_test(au_mntflags(sb), DIRREN)) -+ err = au_dr_hino(sb, /*bindex*/-1, br, path); -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+int au_dr_br_fin(struct super_block *sb, struct au_branch *br) -+{ -+ int err; -+ -+ err = 0; -+ if (au_br_writable(br->br_perm)) -+ err = au_dr_hino(sb, /*bindex*/-1, br, /*path*/NULL); -+ if (!err) -+ au_dr_hino_free(&br->br_dirren); -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int au_brid_str(struct au_dr_brid *brid, struct inode *h_inode, -+ char *buf, size_t sz) -+{ -+ int err; -+ unsigned int major, minor; -+ char *p; -+ -+ p = buf; -+ err = snprintf(p, sz, "%d_", brid->type); -+ AuDebugOn(err > sz); -+ p += err; -+ sz -= err; -+ switch (brid->type) { -+ case AuBrid_Unset: -+ return -EINVAL; -+ case AuBrid_UUID: -+ err = snprintf(p, sz, "%pU", brid->uuid.b); -+ break; -+ case AuBrid_FSID: -+ err = snprintf(p, sz, "%08x-%08x", -+ brid->fsid.val[0], brid->fsid.val[1]); -+ break; -+ case AuBrid_DEV: -+ major = MAJOR(brid->dev); -+ minor = MINOR(brid->dev); -+ if (major <= 0xff && minor <= 0xff) -+ err = snprintf(p, sz, "%02x%02x", major, minor); -+ else -+ err = snprintf(p, sz, "%03x:%05x", major, minor); -+ break; -+ } -+ AuDebugOn(err > sz); -+ p += err; -+ sz -= err; -+ err = snprintf(p, sz, "_%llu", (unsigned long long)h_inode->i_ino); -+ AuDebugOn(err > sz); -+ p += err; -+ sz -= err; -+ -+ return p - buf; -+} -+ -+static int au_drinfo_name(struct au_branch *br, char *name, int len) -+{ -+ int rlen; -+ struct dentry *br_dentry; -+ struct inode *br_inode; -+ -+ br_dentry = au_br_dentry(br); -+ br_inode = d_inode(br_dentry); -+ rlen = au_brid_str(&br->br_dirren.dr_brid, br_inode, name, len); -+ AuDebugOn(rlen >= AUFS_DIRREN_ENV_VAL_SZ); -+ AuDebugOn(rlen > len); -+ -+ return rlen; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * from the given @h_dentry, construct drinfo at @*fdata. -+ * when the size of @*fdata is not enough, reallocate and return new @fdata and -+ * @allocated. -+ */ -+static int au_drinfo_construct(struct au_drinfo_fdata **fdata, -+ struct dentry *h_dentry, -+ unsigned char *allocated) -+{ -+ int err, v; -+ struct au_drinfo_fdata *f, *p; -+ struct au_drinfo *drinfo; -+ struct inode *h_inode; -+ struct qstr *qname; -+ -+ err = 0; -+ f = *fdata; -+ h_inode = d_inode(h_dentry); -+ qname = &h_dentry->d_name; -+ drinfo = &f->drinfo; -+ drinfo->ino = (__force uint64_t)cpu_to_be64(h_inode->i_ino); -+ drinfo->oldnamelen = qname->len; -+ if (*allocated < sizeof(*f) + qname->len) { -+ v = roundup_pow_of_two(*allocated + qname->len); -+ p = au_krealloc(f, v, GFP_NOFS, /*may_shrink*/0); -+ if (unlikely(!p)) { -+ err = -ENOMEM; -+ AuTraceErr(err); -+ goto out; -+ } -+ f = p; -+ *fdata = f; -+ *allocated = v; -+ drinfo = &f->drinfo; -+ } -+ memcpy(drinfo->oldname, qname->name, qname->len); -+ AuDbg("i%llu, %.*s\n", -+ be64_to_cpu((__force __be64)drinfo->ino), drinfo->oldnamelen, -+ drinfo->oldname); -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+/* callers have to free the return value */ -+static struct au_drinfo *au_drinfo_read_k(struct file *file, ino_t h_ino) -+{ -+ struct au_drinfo *ret, *drinfo; -+ struct au_drinfo_fdata fdata; -+ int len; -+ loff_t pos; -+ ssize_t ssz; -+ -+ ret = ERR_PTR(-EIO); -+ pos = 0; -+ ssz = vfsub_read_k(file, &fdata, sizeof(fdata), &pos); -+ if (unlikely(ssz != sizeof(fdata))) { -+ AuIOErr("ssz %zd, %u, %pD2\n", -+ ssz, (unsigned int)sizeof(fdata), file); -+ goto out; -+ } -+ -+ fdata.magic = ntohl((__force __be32)fdata.magic); -+ switch (fdata.magic) { -+ case AUFS_DRINFO_MAGIC_V1: -+ break; -+ default: -+ AuIOErr("magic-num 0x%x, 0x%x, %pD2\n", -+ fdata.magic, AUFS_DRINFO_MAGIC_V1, file); -+ goto out; -+ } -+ -+ drinfo = &fdata.drinfo; -+ len = drinfo->oldnamelen; -+ if (!len) { -+ AuIOErr("broken drinfo %pD2\n", file); -+ goto out; -+ } -+ -+ ret = NULL; -+ drinfo->ino = be64_to_cpu((__force __be64)drinfo->ino); -+ if (unlikely(h_ino && drinfo->ino != h_ino)) { -+ AuDbg("ignored i%llu, i%llu, %pD2\n", -+ (unsigned long long)drinfo->ino, -+ (unsigned long long)h_ino, file); -+ goto out; /* success */ -+ } -+ -+ ret = kmalloc(sizeof(*ret) + len, GFP_NOFS); -+ if (unlikely(!ret)) { -+ ret = ERR_PTR(-ENOMEM); -+ AuTraceErrPtr(ret); -+ goto out; -+ } -+ -+ *ret = *drinfo; -+ ssz = vfsub_read_k(file, (void *)ret->oldname, len, &pos); -+ if (unlikely(ssz != len)) { -+ au_kfree_rcu(ret); -+ ret = ERR_PTR(-EIO); -+ AuIOErr("ssz %zd, %u, %pD2\n", ssz, len, file); -+ goto out; -+ } -+ -+ AuDbg("oldname %.*s\n", ret->oldnamelen, ret->oldname); -+ -+out: -+ return ret; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* in order to be revertible */ -+struct au_drinfo_rev_elm { -+ int created; -+ struct dentry *info_dentry; -+ struct au_drinfo *info_last; -+}; -+ -+struct au_drinfo_rev { -+ unsigned char already; -+ aufs_bindex_t nelm; -+ struct au_drinfo_rev_elm elm[]; -+}; -+ -+/* todo: isn't it too large? */ -+struct au_drinfo_store { -+ struct path h_ppath; -+ struct dentry *h_dentry; -+ struct au_drinfo_fdata *fdata; -+ char *infoname; /* inside of whname, just after PFX */ -+ char whname[sizeof(AUFS_WH_DR_INFO_PFX) + AUFS_DIRREN_ENV_VAL_SZ]; -+ aufs_bindex_t btgt, btail; -+ unsigned char no_sio, -+ allocated, /* current size of *fdata */ -+ infonamelen, /* room size for p */ -+ whnamelen, /* length of the generated name */ -+ renameback; /* renamed back */ -+}; -+ -+/* on rename(2) error, the caller should revert it using @elm */ -+static int au_drinfo_do_store(struct au_drinfo_store *w, -+ struct au_drinfo_rev_elm *elm) -+{ -+ int err, len; -+ ssize_t ssz; -+ loff_t pos; -+ struct path infopath = { -+ .mnt = w->h_ppath.mnt -+ }; -+ struct inode *h_dir, *h_inode, *delegated; -+ struct file *infofile; -+ struct qstr *qname; -+ -+ AuDebugOn(elm -+ && memcmp(elm, page_address(ZERO_PAGE(0)), sizeof(*elm))); -+ -+ infopath.dentry = vfsub_lookup_one_len(w->whname, w->h_ppath.dentry, -+ w->whnamelen); -+ AuTraceErrPtr(infopath.dentry); -+ if (IS_ERR(infopath.dentry)) { -+ err = PTR_ERR(infopath.dentry); -+ goto out; -+ } -+ -+ err = 0; -+ h_dir = d_inode(w->h_ppath.dentry); -+ if (elm && d_is_negative(infopath.dentry)) { -+ err = vfsub_create(h_dir, &infopath, 0600, /*want_excl*/true); -+ AuTraceErr(err); -+ if (unlikely(err)) -+ goto out_dput; -+ elm->created = 1; -+ elm->info_dentry = dget(infopath.dentry); -+ } -+ -+ infofile = vfsub_dentry_open(&infopath, O_RDWR); -+ AuTraceErrPtr(infofile); -+ if (IS_ERR(infofile)) { -+ err = PTR_ERR(infofile); -+ goto out_dput; -+ } -+ -+ h_inode = d_inode(infopath.dentry); -+ if (elm && i_size_read(h_inode)) { -+ h_inode = d_inode(w->h_dentry); -+ elm->info_last = au_drinfo_read_k(infofile, h_inode->i_ino); -+ AuTraceErrPtr(elm->info_last); -+ if (IS_ERR(elm->info_last)) { -+ err = PTR_ERR(elm->info_last); -+ elm->info_last = NULL; -+ AuDebugOn(elm->info_dentry); -+ goto out_fput; -+ } -+ } -+ -+ if (elm && w->renameback) { -+ delegated = NULL; -+ err = vfsub_unlink(h_dir, &infopath, &delegated, /*force*/0); -+ AuTraceErr(err); -+ if (unlikely(err == -EWOULDBLOCK)) -+ iput(delegated); -+ goto out_fput; -+ } -+ -+ pos = 0; -+ qname = &w->h_dentry->d_name; -+ len = sizeof(*w->fdata) + qname->len; -+ if (!elm) -+ len = sizeof(*w->fdata) + w->fdata->drinfo.oldnamelen; -+ ssz = vfsub_write_k(infofile, w->fdata, len, &pos); -+ if (ssz == len) { -+ AuDbg("hi%llu, %.*s\n", w->fdata->drinfo.ino, -+ w->fdata->drinfo.oldnamelen, w->fdata->drinfo.oldname); -+ goto out_fput; /* success */ -+ } else { -+ err = -EIO; -+ if (ssz < 0) -+ err = ssz; -+ /* the caller should revert it using @elm */ -+ } -+ -+out_fput: -+ fput(infofile); -+out_dput: -+ dput(infopath.dentry); -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+struct au_call_drinfo_do_store_args { -+ int *errp; -+ struct au_drinfo_store *w; -+ struct au_drinfo_rev_elm *elm; -+}; -+ -+static void au_call_drinfo_do_store(void *args) -+{ -+ struct au_call_drinfo_do_store_args *a = args; -+ -+ *a->errp = au_drinfo_do_store(a->w, a->elm); -+} -+ -+static int au_drinfo_store_sio(struct au_drinfo_store *w, -+ struct au_drinfo_rev_elm *elm) -+{ -+ int err, wkq_err; -+ -+ if (w->no_sio) -+ err = au_drinfo_do_store(w, elm); -+ else { -+ struct au_call_drinfo_do_store_args a = { -+ .errp = &err, -+ .w = w, -+ .elm = elm -+ }; -+ wkq_err = au_wkq_wait(au_call_drinfo_do_store, &a); -+ if (unlikely(wkq_err)) -+ err = wkq_err; -+ } -+ AuTraceErr(err); -+ -+ return err; -+} -+ -+static int au_drinfo_store_work_init(struct au_drinfo_store *w, -+ aufs_bindex_t btgt) -+{ -+ int err; -+ -+ memset(w, 0, sizeof(*w)); -+ w->allocated = roundup_pow_of_two(sizeof(*w->fdata) + 40); -+ strcpy(w->whname, AUFS_WH_DR_INFO_PFX); -+ w->infoname = w->whname + sizeof(AUFS_WH_DR_INFO_PFX) - 1; -+ w->infonamelen = sizeof(w->whname) - sizeof(AUFS_WH_DR_INFO_PFX); -+ w->btgt = btgt; -+ w->no_sio = !!uid_eq(current_fsuid(), GLOBAL_ROOT_UID); -+ -+ err = -ENOMEM; -+ w->fdata = kcalloc(1, w->allocated, GFP_NOFS); -+ if (unlikely(!w->fdata)) { -+ AuTraceErr(err); -+ goto out; -+ } -+ w->fdata->magic = (__force uint32_t)htonl(AUFS_DRINFO_MAGIC_V1); -+ err = 0; -+ -+out: -+ return err; -+} -+ -+static void au_drinfo_store_work_fin(struct au_drinfo_store *w) -+{ -+ au_kfree_rcu(w->fdata); -+} -+ -+static void au_drinfo_store_rev(struct au_drinfo_rev *rev, -+ struct au_drinfo_store *w) -+{ -+ struct au_drinfo_rev_elm *elm; -+ struct inode *h_dir, *delegated; -+ int err, nelm; -+ struct path infopath = { -+ .mnt = w->h_ppath.mnt -+ }; -+ -+ h_dir = d_inode(w->h_ppath.dentry); -+ IMustLock(h_dir); -+ -+ err = 0; -+ elm = rev->elm; -+ for (nelm = rev->nelm; nelm > 0; nelm--, elm++) { -+ AuDebugOn(elm->created && elm->info_last); -+ if (elm->created) { -+ AuDbg("here\n"); -+ delegated = NULL; -+ infopath.dentry = elm->info_dentry; -+ err = vfsub_unlink(h_dir, &infopath, &delegated, -+ !w->no_sio); -+ AuTraceErr(err); -+ if (unlikely(err == -EWOULDBLOCK)) -+ iput(delegated); -+ dput(elm->info_dentry); -+ } else if (elm->info_last) { -+ AuDbg("here\n"); -+ w->fdata->drinfo = *elm->info_last; -+ memcpy(w->fdata->drinfo.oldname, -+ elm->info_last->oldname, -+ elm->info_last->oldnamelen); -+ err = au_drinfo_store_sio(w, /*elm*/NULL); -+ au_kfree_rcu(elm->info_last); -+ } -+ if (unlikely(err)) -+ AuIOErr("%d, %s\n", err, w->whname); -+ /* go on even if err */ -+ } -+} -+ -+/* caller has to call au_dr_rename_fin() later */ -+static int au_drinfo_store(struct dentry *dentry, aufs_bindex_t btgt, -+ struct qstr *dst_name, void *_rev) -+{ -+ int err, sz, nelm; -+ aufs_bindex_t bindex, btail; -+ struct au_drinfo_store work; -+ struct au_drinfo_rev *rev, **p; -+ struct au_drinfo_rev_elm *elm; -+ struct super_block *sb; -+ struct au_branch *br; -+ struct au_hinode *hdir; -+ -+ err = au_drinfo_store_work_init(&work, btgt); -+ AuTraceErr(err); -+ if (unlikely(err)) -+ goto out; -+ -+ err = -ENOMEM; -+ btail = au_dbtaildir(dentry); -+ nelm = btail - btgt; -+ sz = sizeof(*rev) + sizeof(*elm) * nelm; -+ rev = kcalloc(1, sz, GFP_NOFS); -+ if (unlikely(!rev)) { -+ AuTraceErr(err); -+ goto out_args; -+ } -+ rev->nelm = nelm; -+ elm = rev->elm; -+ p = _rev; -+ *p = rev; -+ -+ err = 0; -+ sb = dentry->d_sb; -+ work.h_ppath.dentry = au_h_dptr(dentry, btgt); -+ work.h_ppath.mnt = au_sbr_mnt(sb, btgt); -+ hdir = au_hi(d_inode(dentry), btgt); -+ au_hn_inode_lock_nested(hdir, AuLsc_I_CHILD); -+ for (bindex = btgt + 1; bindex <= btail; bindex++, elm++) { -+ work.h_dentry = au_h_dptr(dentry, bindex); -+ if (!work.h_dentry) -+ continue; -+ -+ err = au_drinfo_construct(&work.fdata, work.h_dentry, -+ &work.allocated); -+ AuTraceErr(err); -+ if (unlikely(err)) -+ break; -+ -+ work.renameback = au_qstreq(&work.h_dentry->d_name, dst_name); -+ br = au_sbr(sb, bindex); -+ work.whnamelen = sizeof(AUFS_WH_DR_INFO_PFX) - 1; -+ work.whnamelen += au_drinfo_name(br, work.infoname, -+ work.infonamelen); -+ AuDbg("whname %.*s, i%llu, %.*s\n", -+ work.whnamelen, work.whname, -+ be64_to_cpu((__force __be64)work.fdata->drinfo.ino), -+ work.fdata->drinfo.oldnamelen, -+ work.fdata->drinfo.oldname); -+ -+ err = au_drinfo_store_sio(&work, elm); -+ AuTraceErr(err); -+ if (unlikely(err)) -+ break; -+ } -+ if (unlikely(err)) { -+ /* revert all drinfo */ -+ au_drinfo_store_rev(rev, &work); -+ au_kfree_try_rcu(rev); -+ *p = NULL; -+ } -+ au_hn_inode_unlock(hdir); -+ -+out_args: -+ au_drinfo_store_work_fin(&work); -+out: -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+int au_dr_rename(struct dentry *src, aufs_bindex_t bindex, -+ struct qstr *dst_name, void *_rev) -+{ -+ int err, already; -+ ino_t ino; -+ struct super_block *sb; -+ struct au_branch *br; -+ struct au_dr_br *dr; -+ struct dentry *h_dentry; -+ struct inode *h_inode; -+ struct au_dr_hino *ent; -+ struct au_drinfo_rev *rev, **p; -+ -+ AuDbg("bindex %d\n", bindex); -+ -+ err = -ENOMEM; -+ ent = kmalloc(sizeof(*ent), GFP_NOFS); -+ if (unlikely(!ent)) -+ goto out; -+ -+ sb = src->d_sb; -+ br = au_sbr(sb, bindex); -+ dr = &br->br_dirren; -+ h_dentry = au_h_dptr(src, bindex); -+ h_inode = d_inode(h_dentry); -+ ino = h_inode->i_ino; -+ ent->dr_h_ino = ino; -+ already = au_dr_hino_test_add(dr, ino, ent); -+ AuDbg("b%d, hi%llu, already %d\n", -+ bindex, (unsigned long long)ino, already); -+ -+ err = au_drinfo_store(src, bindex, dst_name, _rev); -+ AuTraceErr(err); -+ if (!err) { -+ p = _rev; -+ rev = *p; -+ rev->already = already; -+ goto out; /* success */ -+ } -+ -+ /* revert */ -+ if (!already) -+ au_dr_hino_del(dr, ent); -+ au_kfree_rcu(ent); -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+void au_dr_rename_fin(struct dentry *src, aufs_bindex_t btgt, void *_rev) -+{ -+ struct au_drinfo_rev *rev; -+ struct au_drinfo_rev_elm *elm; -+ int nelm; -+ -+ rev = _rev; -+ elm = rev->elm; -+ for (nelm = rev->nelm; nelm > 0; nelm--, elm++) { -+ dput(elm->info_dentry); -+ au_kfree_rcu(elm->info_last); -+ } -+ au_kfree_try_rcu(rev); -+} -+ -+void au_dr_rename_rev(struct dentry *src, aufs_bindex_t btgt, void *_rev) -+{ -+ int err; -+ struct au_drinfo_store work; -+ struct au_drinfo_rev *rev = _rev; -+ struct super_block *sb; -+ struct au_branch *br; -+ struct inode *h_inode; -+ struct au_dr_br *dr; -+ struct au_dr_hino *ent; -+ -+ err = au_drinfo_store_work_init(&work, btgt); -+ if (unlikely(err)) -+ goto out; -+ -+ sb = src->d_sb; -+ br = au_sbr(sb, btgt); -+ work.h_ppath.dentry = au_h_dptr(src, btgt); -+ work.h_ppath.mnt = au_br_mnt(br); -+ au_drinfo_store_rev(rev, &work); -+ au_drinfo_store_work_fin(&work); -+ if (rev->already) -+ goto out; -+ -+ dr = &br->br_dirren; -+ h_inode = d_inode(work.h_ppath.dentry); -+ ent = au_dr_hino_find(dr, h_inode->i_ino); -+ BUG_ON(!ent); -+ au_dr_hino_del(dr, ent); -+ au_kfree_rcu(ent); -+ -+out: -+ au_kfree_try_rcu(rev); -+ if (unlikely(err)) -+ pr_err("failed to remove dirren info\n"); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static struct au_drinfo *au_drinfo_do_load(struct path *h_ppath, -+ char *whname, int whnamelen, -+ struct dentry **info_dentry) -+{ -+ struct au_drinfo *drinfo; -+ struct file *f; -+ struct inode *h_dir; -+ struct path infopath; -+ int unlocked; -+ -+ AuDbg("%pd/%.*s\n", h_ppath->dentry, whnamelen, whname); -+ -+ *info_dentry = NULL; -+ drinfo = NULL; -+ unlocked = 0; -+ h_dir = d_inode(h_ppath->dentry); -+ inode_lock_shared_nested(h_dir, AuLsc_I_PARENT); -+ infopath.dentry = vfsub_lookup_one_len(whname, h_ppath->dentry, -+ whnamelen); -+ if (IS_ERR(infopath.dentry)) { -+ drinfo = (void *)infopath.dentry; -+ goto out; -+ } -+ -+ if (d_is_negative(infopath.dentry)) -+ goto out_dput; /* success */ -+ -+ infopath.mnt = h_ppath->mnt; -+ f = vfsub_dentry_open(&infopath, O_RDONLY); -+ inode_unlock_shared(h_dir); -+ unlocked = 1; -+ if (IS_ERR(f)) { -+ drinfo = (void *)f; -+ goto out_dput; -+ } -+ -+ drinfo = au_drinfo_read_k(f, /*h_ino*/0); -+ if (IS_ERR_OR_NULL(drinfo)) -+ goto out_fput; -+ -+ AuDbg("oldname %.*s\n", drinfo->oldnamelen, drinfo->oldname); -+ *info_dentry = dget(infopath.dentry); /* keep it alive */ -+ -+out_fput: -+ fput(f); -+out_dput: -+ dput(infopath.dentry); -+out: -+ if (!unlocked) -+ inode_unlock_shared(h_dir); -+ AuTraceErrPtr(drinfo); -+ return drinfo; -+} -+ -+struct au_drinfo_do_load_args { -+ struct au_drinfo **drinfop; -+ struct path *h_ppath; -+ char *whname; -+ int whnamelen; -+ struct dentry **info_dentry; -+}; -+ -+static void au_call_drinfo_do_load(void *args) -+{ -+ struct au_drinfo_do_load_args *a = args; -+ -+ *a->drinfop = au_drinfo_do_load(a->h_ppath, a->whname, a->whnamelen, -+ a->info_dentry); -+} -+ -+struct au_drinfo_load { -+ struct path h_ppath; -+ struct qstr *qname; -+ unsigned char no_sio; -+ -+ aufs_bindex_t ninfo; -+ struct au_drinfo **drinfo; -+}; -+ -+static int au_drinfo_load(struct au_drinfo_load *w, aufs_bindex_t bindex, -+ struct au_branch *br) -+{ -+ int err, wkq_err, whnamelen, e; -+ char whname[sizeof(AUFS_WH_DR_INFO_PFX) + AUFS_DIRREN_ENV_VAL_SZ] -+ = AUFS_WH_DR_INFO_PFX; -+ struct au_drinfo *drinfo; -+ struct qstr oldname; -+ struct inode *h_dir, *delegated; -+ struct dentry *info_dentry; -+ struct path infopath; -+ -+ whnamelen = sizeof(AUFS_WH_DR_INFO_PFX) - 1; -+ whnamelen += au_drinfo_name(br, whname + whnamelen, -+ sizeof(whname) - whnamelen); -+ if (w->no_sio) -+ drinfo = au_drinfo_do_load(&w->h_ppath, whname, whnamelen, -+ &info_dentry); -+ else { -+ struct au_drinfo_do_load_args args = { -+ .drinfop = &drinfo, -+ .h_ppath = &w->h_ppath, -+ .whname = whname, -+ .whnamelen = whnamelen, -+ .info_dentry = &info_dentry -+ }; -+ wkq_err = au_wkq_wait(au_call_drinfo_do_load, &args); -+ if (unlikely(wkq_err)) -+ drinfo = ERR_PTR(wkq_err); -+ } -+ err = PTR_ERR(drinfo); -+ if (IS_ERR_OR_NULL(drinfo)) -+ goto out; -+ -+ err = 0; -+ oldname.len = drinfo->oldnamelen; -+ oldname.name = drinfo->oldname; -+ if (au_qstreq(w->qname, &oldname)) { -+ /* the name is renamed back */ -+ au_kfree_rcu(drinfo); -+ drinfo = NULL; -+ -+ infopath.dentry = info_dentry; -+ infopath.mnt = w->h_ppath.mnt; -+ h_dir = d_inode(w->h_ppath.dentry); -+ delegated = NULL; -+ inode_lock_nested(h_dir, AuLsc_I_PARENT); -+ e = vfsub_unlink(h_dir, &infopath, &delegated, !w->no_sio); -+ inode_unlock(h_dir); -+ if (unlikely(e)) -+ AuIOErr("ignored %d, %pd2\n", e, &infopath.dentry); -+ if (unlikely(e == -EWOULDBLOCK)) -+ iput(delegated); -+ } -+ au_kfree_rcu(w->drinfo[bindex]); -+ w->drinfo[bindex] = drinfo; -+ dput(info_dentry); -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static void au_dr_lkup_free(struct au_drinfo **drinfo, int n) -+{ -+ struct au_drinfo **p = drinfo; -+ -+ while (n-- > 0) -+ au_kfree_rcu(*drinfo++); -+ au_kfree_try_rcu(p); -+} -+ -+int au_dr_lkup(struct au_do_lookup_args *lkup, struct dentry *dentry, -+ aufs_bindex_t btgt) -+{ -+ int err, ninfo; -+ struct au_drinfo_load w; -+ aufs_bindex_t bindex, bbot; -+ struct au_branch *br; -+ struct inode *h_dir; -+ struct au_dr_hino *ent; -+ struct super_block *sb; -+ -+ AuDbg("%.*s, name %.*s, whname %.*s, b%d\n", -+ AuLNPair(&dentry->d_name), AuLNPair(&lkup->dirren.dr_name), -+ AuLNPair(&lkup->whname), btgt); -+ -+ sb = dentry->d_sb; -+ bbot = au_sbbot(sb); -+ w.ninfo = bbot + 1; -+ if (!lkup->dirren.drinfo) { -+ lkup->dirren.drinfo = kcalloc(w.ninfo, -+ sizeof(*lkup->dirren.drinfo), -+ GFP_NOFS); -+ if (unlikely(!lkup->dirren.drinfo)) { -+ err = -ENOMEM; -+ goto out; -+ } -+ lkup->dirren.ninfo = w.ninfo; -+ } -+ w.drinfo = lkup->dirren.drinfo; -+ w.no_sio = !!uid_eq(current_fsuid(), GLOBAL_ROOT_UID); -+ w.h_ppath.dentry = au_h_dptr(dentry, btgt); -+ AuDebugOn(!w.h_ppath.dentry); -+ w.h_ppath.mnt = au_sbr_mnt(sb, btgt); -+ w.qname = &dentry->d_name; -+ -+ ninfo = 0; -+ for (bindex = btgt + 1; bindex <= bbot; bindex++) { -+ br = au_sbr(sb, bindex); -+ err = au_drinfo_load(&w, bindex, br); -+ if (unlikely(err)) -+ goto out_free; -+ if (w.drinfo[bindex]) -+ ninfo++; -+ } -+ if (!ninfo) { -+ br = au_sbr(sb, btgt); -+ h_dir = d_inode(w.h_ppath.dentry); -+ ent = au_dr_hino_find(&br->br_dirren, h_dir->i_ino); -+ AuDebugOn(!ent); -+ au_dr_hino_del(&br->br_dirren, ent); -+ au_kfree_rcu(ent); -+ } -+ goto out; /* success */ -+ -+out_free: -+ au_dr_lkup_free(lkup->dirren.drinfo, lkup->dirren.ninfo); -+ lkup->dirren.ninfo = 0; -+ lkup->dirren.drinfo = NULL; -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+void au_dr_lkup_fin(struct au_do_lookup_args *lkup) -+{ -+ au_dr_lkup_free(lkup->dirren.drinfo, lkup->dirren.ninfo); -+} -+ -+int au_dr_lkup_name(struct au_do_lookup_args *lkup, aufs_bindex_t btgt) -+{ -+ int err; -+ struct au_drinfo *drinfo; -+ -+ err = 0; -+ if (!lkup->dirren.drinfo) -+ goto out; -+ AuDebugOn(lkup->dirren.ninfo <= btgt); -+ drinfo = lkup->dirren.drinfo[btgt]; -+ if (!drinfo) -+ goto out; -+ -+ au_kfree_try_rcu(lkup->whname.name); -+ lkup->whname.name = NULL; -+ lkup->dirren.dr_name.len = drinfo->oldnamelen; -+ lkup->dirren.dr_name.name = drinfo->oldname; -+ lkup->name = &lkup->dirren.dr_name; -+ err = au_wh_name_alloc(&lkup->whname, lkup->name); -+ if (!err) -+ AuDbg("name %.*s, whname %.*s, b%d\n", -+ AuLNPair(lkup->name), AuLNPair(&lkup->whname), -+ btgt); -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+int au_dr_lkup_h_ino(struct au_do_lookup_args *lkup, aufs_bindex_t bindex, -+ ino_t h_ino) -+{ -+ int match; -+ struct au_drinfo *drinfo; -+ -+ match = 1; -+ if (!lkup->dirren.drinfo) -+ goto out; -+ AuDebugOn(lkup->dirren.ninfo <= bindex); -+ drinfo = lkup->dirren.drinfo[bindex]; -+ if (!drinfo) -+ goto out; -+ -+ match = (drinfo->ino == h_ino); -+ AuDbg("match %d\n", match); -+ -+out: -+ return match; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+int au_dr_opt_set(struct super_block *sb) -+{ -+ int err; -+ aufs_bindex_t bindex, bbot; -+ struct au_branch *br; -+ -+ err = 0; -+ bbot = au_sbbot(sb); -+ for (bindex = 0; !err && bindex <= bbot; bindex++) { -+ br = au_sbr(sb, bindex); -+ err = au_dr_hino(sb, bindex, /*br*/NULL, &br->br_path); -+ } -+ -+ return err; -+} -+ -+int au_dr_opt_flush(struct super_block *sb) -+{ -+ int err; -+ aufs_bindex_t bindex, bbot; -+ struct au_branch *br; -+ -+ err = 0; -+ bbot = au_sbbot(sb); -+ for (bindex = 0; !err && bindex <= bbot; bindex++) { -+ br = au_sbr(sb, bindex); -+ if (au_br_writable(br->br_perm)) -+ err = au_dr_hino(sb, bindex, /*br*/NULL, /*path*/NULL); -+ } -+ -+ return err; -+} -+ -+int au_dr_opt_clr(struct super_block *sb, int no_flush) -+{ -+ int err; -+ aufs_bindex_t bindex, bbot; -+ struct au_branch *br; -+ -+ err = 0; -+ if (!no_flush) { -+ err = au_dr_opt_flush(sb); -+ if (unlikely(err)) -+ goto out; -+ } -+ -+ bbot = au_sbbot(sb); -+ for (bindex = 0; bindex <= bbot; bindex++) { -+ br = au_sbr(sb, bindex); -+ au_dr_hino_free(&br->br_dirren); -+ } -+ -+out: -+ return err; -+} -diff --git a/fs/aufs/dirren.h b/fs/aufs/dirren.h -new file mode 100644 -index 000000000000..ade589d2e75c ---- /dev/null -+++ b/fs/aufs/dirren.h -@@ -0,0 +1,127 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2017-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * renamed dir info -+ */ -+ -+#ifndef __AUFS_DIRREN_H__ -+#define __AUFS_DIRREN_H__ -+ -+#ifdef __KERNEL__ -+ -+#include -+#include -+#include -+#include "hbl.h" -+ -+#define AuDirren_NHASH 100 -+ -+#ifdef CONFIG_AUFS_DIRREN -+enum au_brid_type { -+ AuBrid_Unset, -+ AuBrid_UUID, -+ AuBrid_FSID, -+ AuBrid_DEV -+}; -+ -+struct au_dr_brid { -+ enum au_brid_type type; -+ union { -+ uuid_t uuid; /* unimplemented yet */ -+ fsid_t fsid; -+ dev_t dev; -+ }; -+}; -+ -+/* 20 is the max digits length of ulong 64 */ -+/* brid-type "_" uuid "_" inum */ -+#define AUFS_DIRREN_FNAME_SZ (1 + 1 + UUID_STRING_LEN + 20) -+#define AUFS_DIRREN_ENV_VAL_SZ (AUFS_DIRREN_FNAME_SZ + 1 + 20) -+ -+struct au_dr_hino { -+ struct hlist_bl_node dr_hnode; -+ ino_t dr_h_ino; -+}; -+ -+struct au_dr_br { -+ struct hlist_bl_head dr_h_ino[AuDirren_NHASH]; -+ struct au_dr_brid dr_brid; -+}; -+ -+struct au_dr_lookup { -+ /* dr_name is pointed by struct au_do_lookup_args.name */ -+ struct qstr dr_name; /* subset of dr_info */ -+ aufs_bindex_t ninfo; -+ struct au_drinfo **drinfo; -+}; -+#else -+struct au_dr_hino; -+/* empty */ -+struct au_dr_br { }; -+struct au_dr_lookup { }; -+#endif -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct au_branch; -+struct au_do_lookup_args; -+struct au_hinode; -+#ifdef CONFIG_AUFS_DIRREN -+int au_dr_hino_test_add(struct au_dr_br *dr, ino_t h_ino, -+ struct au_dr_hino *add_ent); -+void au_dr_hino_free(struct au_dr_br *dr); -+int au_dr_br_init(struct super_block *sb, struct au_branch *br, -+ const struct path *path); -+int au_dr_br_fin(struct super_block *sb, struct au_branch *br); -+int au_dr_rename(struct dentry *src, aufs_bindex_t bindex, -+ struct qstr *dst_name, void *_rev); -+void au_dr_rename_fin(struct dentry *src, aufs_bindex_t btgt, void *rev); -+void au_dr_rename_rev(struct dentry *src, aufs_bindex_t bindex, void *rev); -+int au_dr_lkup(struct au_do_lookup_args *lkup, struct dentry *dentry, -+ aufs_bindex_t bindex); -+int au_dr_lkup_name(struct au_do_lookup_args *lkup, aufs_bindex_t btgt); -+int au_dr_lkup_h_ino(struct au_do_lookup_args *lkup, aufs_bindex_t bindex, -+ ino_t h_ino); -+void au_dr_lkup_fin(struct au_do_lookup_args *lkup); -+int au_dr_opt_set(struct super_block *sb); -+int au_dr_opt_flush(struct super_block *sb); -+int au_dr_opt_clr(struct super_block *sb, int no_flush); -+#else -+AuStubInt0(au_dr_hino_test_add, struct au_dr_br *dr, ino_t h_ino, -+ struct au_dr_hino *add_ent); -+AuStubVoid(au_dr_hino_free, struct au_dr_br *dr); -+AuStubInt0(au_dr_br_init, struct super_block *sb, struct au_branch *br, -+ const struct path *path); -+AuStubInt0(au_dr_br_fin, struct super_block *sb, struct au_branch *br); -+AuStubInt0(au_dr_rename, struct dentry *src, aufs_bindex_t bindex, -+ struct qstr *dst_name, void *_rev); -+AuStubVoid(au_dr_rename_fin, struct dentry *src, aufs_bindex_t btgt, void *rev); -+AuStubVoid(au_dr_rename_rev, struct dentry *src, aufs_bindex_t bindex, -+ void *rev); -+AuStubInt0(au_dr_lkup, struct au_do_lookup_args *lkup, struct dentry *dentry, -+ aufs_bindex_t bindex); -+AuStubInt0(au_dr_lkup_name, struct au_do_lookup_args *lkup, aufs_bindex_t btgt); -+AuStubInt0(au_dr_lkup_h_ino, struct au_do_lookup_args *lkup, -+ aufs_bindex_t bindex, ino_t h_ino); -+AuStubVoid(au_dr_lkup_fin, struct au_do_lookup_args *lkup); -+AuStubInt0(au_dr_opt_set, struct super_block *sb); -+AuStubInt0(au_dr_opt_flush, struct super_block *sb); -+AuStubInt0(au_dr_opt_clr, struct super_block *sb, int no_flush); -+#endif -+ -+/* ---------------------------------------------------------------------- */ -+ -+#ifdef CONFIG_AUFS_DIRREN -+static inline int au_dr_ihash(ino_t h_ino) -+{ -+ return h_ino % AuDirren_NHASH; -+} -+#else -+AuStubInt0(au_dr_ihash, ino_t h_ino); -+#endif -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_DIRREN_H__ */ -diff --git a/fs/aufs/dynop.c b/fs/aufs/dynop.c -new file mode 100644 -index 000000000000..3c3e7812a021 ---- /dev/null -+++ b/fs/aufs/dynop.c -@@ -0,0 +1,354 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2010-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * dynamically customizable operations for regular files -+ */ -+ -+#include "aufs.h" -+ -+#define DyPrSym(key) AuDbgSym(key->dk_op.dy_hop) -+ -+/* -+ * How large will these lists be? -+ * Usually just a few elements, 20-30 at most for each, I guess. -+ */ -+static struct hlist_bl_head dynop[AuDyLast]; -+ -+static struct au_dykey *dy_gfind_get(struct hlist_bl_head *hbl, -+ const void *h_op) -+{ -+ struct au_dykey *key, *tmp; -+ struct hlist_bl_node *pos; -+ -+ key = NULL; -+ hlist_bl_lock(hbl); -+ hlist_bl_for_each_entry(tmp, pos, hbl, dk_hnode) -+ if (tmp->dk_op.dy_hop == h_op) { -+ if (kref_get_unless_zero(&tmp->dk_kref)) -+ key = tmp; -+ break; -+ } -+ hlist_bl_unlock(hbl); -+ -+ return key; -+} -+ -+static struct au_dykey *dy_bradd(struct au_branch *br, struct au_dykey *key) -+{ -+ struct au_dykey **k, *found; -+ const void *h_op = key->dk_op.dy_hop; -+ int i; -+ -+ found = NULL; -+ k = br->br_dykey; -+ for (i = 0; i < AuBrDynOp; i++) -+ if (k[i]) { -+ if (k[i]->dk_op.dy_hop == h_op) { -+ found = k[i]; -+ break; -+ } -+ } else -+ break; -+ if (!found) { -+ spin_lock(&br->br_dykey_lock); -+ for (; i < AuBrDynOp; i++) -+ if (k[i]) { -+ if (k[i]->dk_op.dy_hop == h_op) { -+ found = k[i]; -+ break; -+ } -+ } else { -+ k[i] = key; -+ break; -+ } -+ spin_unlock(&br->br_dykey_lock); -+ BUG_ON(i == AuBrDynOp); /* expand the array */ -+ } -+ -+ return found; -+} -+ -+/* kref_get() if @key is already added */ -+static struct au_dykey *dy_gadd(struct hlist_bl_head *hbl, struct au_dykey *key) -+{ -+ struct au_dykey *tmp, *found; -+ struct hlist_bl_node *pos; -+ const void *h_op = key->dk_op.dy_hop; -+ -+ found = NULL; -+ hlist_bl_lock(hbl); -+ hlist_bl_for_each_entry(tmp, pos, hbl, dk_hnode) -+ if (tmp->dk_op.dy_hop == h_op) { -+ if (kref_get_unless_zero(&tmp->dk_kref)) -+ found = tmp; -+ break; -+ } -+ if (!found) -+ hlist_bl_add_head(&key->dk_hnode, hbl); -+ hlist_bl_unlock(hbl); -+ -+ if (!found) -+ DyPrSym(key); -+ return found; -+} -+ -+static void dy_free_rcu(struct rcu_head *rcu) -+{ -+ struct au_dykey *key; -+ -+ key = container_of(rcu, struct au_dykey, dk_rcu); -+ DyPrSym(key); -+ kfree(key); -+} -+ -+static void dy_free(struct kref *kref) -+{ -+ struct au_dykey *key; -+ struct hlist_bl_head *hbl; -+ -+ key = container_of(kref, struct au_dykey, dk_kref); -+ hbl = dynop + key->dk_op.dy_type; -+ au_hbl_del(&key->dk_hnode, hbl); -+ call_rcu(&key->dk_rcu, dy_free_rcu); -+} -+ -+void au_dy_put(struct au_dykey *key) -+{ -+ kref_put(&key->dk_kref, dy_free); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+#define DyDbgSize(cnt, op) AuDebugOn(cnt != sizeof(op)/sizeof(void *)) -+ -+#ifdef CONFIG_AUFS_DEBUG -+#define DyDbgDeclare(cnt) unsigned int cnt = 0 -+#define DyDbgInc(cnt) do { cnt++; } while (0) -+#else -+#define DyDbgDeclare(cnt) do {} while (0) -+#define DyDbgInc(cnt) do {} while (0) -+#endif -+ -+#define DySet(func, dst, src, h_op, h_sb) do { \ -+ DyDbgInc(cnt); \ -+ if (h_op->func) { \ -+ if (src.func) \ -+ dst.func = src.func; \ -+ else \ -+ AuDbg("%s %s\n", au_sbtype(h_sb), #func); \ -+ } \ -+} while (0) -+ -+#define DySetForce(func, dst, src) do { \ -+ AuDebugOn(!src.func); \ -+ DyDbgInc(cnt); \ -+ dst.func = src.func; \ -+} while (0) -+ -+#define DySetAop(func) \ -+ DySet(func, dyaop->da_op, aufs_aop, h_aop, h_sb) -+#define DySetAopForce(func) \ -+ DySetForce(func, dyaop->da_op, aufs_aop) -+ -+static void dy_aop(struct au_dykey *key, const void *h_op, -+ struct super_block *h_sb __maybe_unused) -+{ -+ struct au_dyaop *dyaop = (void *)key; -+ const struct address_space_operations *h_aop = h_op; -+ DyDbgDeclare(cnt); -+ -+ AuDbg("%s\n", au_sbtype(h_sb)); -+ -+ DySetAop(writepage); -+ DySetAopForce(readpage); /* force */ -+ DySetAop(writepages); -+ DySetAop(set_page_dirty); -+ DySetAop(readpages); -+ DySetAop(write_begin); -+ DySetAop(write_end); -+ DySetAop(bmap); -+ DySetAop(invalidatepage); -+ DySetAop(releasepage); -+ DySetAop(freepage); -+ /* this one will be changed according to an aufs mount option */ -+ DySetAop(direct_IO); -+ DySetAop(migratepage); -+ DySetAop(isolate_page); -+ DySetAop(putback_page); -+ DySetAop(launder_page); -+ DySetAop(is_partially_uptodate); -+ DySetAop(is_dirty_writeback); -+ DySetAop(error_remove_page); -+ DySetAop(swap_activate); -+ DySetAop(swap_deactivate); -+ -+ DyDbgSize(cnt, *h_aop); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static void dy_bug(struct kref *kref) -+{ -+ BUG(); -+} -+ -+static struct au_dykey *dy_get(struct au_dynop *op, struct au_branch *br) -+{ -+ struct au_dykey *key, *old; -+ struct hlist_bl_head *hbl; -+ struct op { -+ unsigned int sz; -+ void (*set)(struct au_dykey *key, const void *h_op, -+ struct super_block *h_sb __maybe_unused); -+ }; -+ static const struct op a[] = { -+ [AuDy_AOP] = { -+ .sz = sizeof(struct au_dyaop), -+ .set = dy_aop -+ } -+ }; -+ const struct op *p; -+ -+ hbl = dynop + op->dy_type; -+ key = dy_gfind_get(hbl, op->dy_hop); -+ if (key) -+ goto out_add; /* success */ -+ -+ p = a + op->dy_type; -+ key = kzalloc(p->sz, GFP_NOFS); -+ if (unlikely(!key)) { -+ key = ERR_PTR(-ENOMEM); -+ goto out; -+ } -+ -+ key->dk_op.dy_hop = op->dy_hop; -+ kref_init(&key->dk_kref); -+ p->set(key, op->dy_hop, au_br_sb(br)); -+ old = dy_gadd(hbl, key); -+ if (old) { -+ au_kfree_rcu(key); -+ key = old; -+ } -+ -+out_add: -+ old = dy_bradd(br, key); -+ if (old) -+ /* its ref-count should never be zero here */ -+ kref_put(&key->dk_kref, dy_bug); -+out: -+ return key; -+} -+ -+/* ---------------------------------------------------------------------- */ -+/* -+ * Aufs prohibits O_DIRECT by default even if the branch supports it. -+ * This behaviour is necessary to return an error from open(O_DIRECT) instead -+ * of the succeeding I/O. The dio mount option enables O_DIRECT and makes -+ * open(O_DIRECT) always succeed, but the succeeding I/O may return an error. -+ * See the aufs manual in detail. -+ */ -+static void dy_adx(struct au_dyaop *dyaop, int do_dx) -+{ -+ if (!do_dx) -+ dyaop->da_op.direct_IO = NULL; -+ else -+ dyaop->da_op.direct_IO = aufs_aop.direct_IO; -+} -+ -+static struct au_dyaop *dy_aget(struct au_branch *br, -+ const struct address_space_operations *h_aop, -+ int do_dx) -+{ -+ struct au_dyaop *dyaop; -+ struct au_dynop op; -+ -+ op.dy_type = AuDy_AOP; -+ op.dy_haop = h_aop; -+ dyaop = (void *)dy_get(&op, br); -+ if (IS_ERR(dyaop)) -+ goto out; -+ dy_adx(dyaop, do_dx); -+ -+out: -+ return dyaop; -+} -+ -+int au_dy_iaop(struct inode *inode, aufs_bindex_t bindex, -+ struct inode *h_inode) -+{ -+ int err, do_dx; -+ struct super_block *sb; -+ struct au_branch *br; -+ struct au_dyaop *dyaop; -+ -+ AuDebugOn(!S_ISREG(h_inode->i_mode)); -+ IiMustWriteLock(inode); -+ -+ sb = inode->i_sb; -+ br = au_sbr(sb, bindex); -+ do_dx = !!au_opt_test(au_mntflags(sb), DIO); -+ dyaop = dy_aget(br, h_inode->i_mapping->a_ops, do_dx); -+ err = PTR_ERR(dyaop); -+ if (IS_ERR(dyaop)) -+ /* unnecessary to call dy_fput() */ -+ goto out; -+ -+ err = 0; -+ inode->i_mapping->a_ops = &dyaop->da_op; -+ -+out: -+ return err; -+} -+ -+/* -+ * Is it safe to replace a_ops during the inode/file is in operation? -+ * Yes, I hope so. -+ */ -+int au_dy_irefresh(struct inode *inode) -+{ -+ int err; -+ aufs_bindex_t btop; -+ struct inode *h_inode; -+ -+ err = 0; -+ if (S_ISREG(inode->i_mode)) { -+ btop = au_ibtop(inode); -+ h_inode = au_h_iptr(inode, btop); -+ err = au_dy_iaop(inode, btop, h_inode); -+ } -+ return err; -+} -+ -+void au_dy_arefresh(int do_dx) -+{ -+ struct hlist_bl_head *hbl; -+ struct hlist_bl_node *pos; -+ struct au_dykey *key; -+ -+ hbl = dynop + AuDy_AOP; -+ hlist_bl_lock(hbl); -+ hlist_bl_for_each_entry(key, pos, hbl, dk_hnode) -+ dy_adx((void *)key, do_dx); -+ hlist_bl_unlock(hbl); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+void __init au_dy_init(void) -+{ -+ int i; -+ -+ for (i = 0; i < AuDyLast; i++) -+ INIT_HLIST_BL_HEAD(dynop + i); -+} -+ -+void au_dy_fin(void) -+{ -+ int i; -+ -+ for (i = 0; i < AuDyLast; i++) -+ WARN_ON(!hlist_bl_empty(dynop + i)); -+} -diff --git a/fs/aufs/dynop.h b/fs/aufs/dynop.h -new file mode 100644 -index 000000000000..66ac96bbf2ff ---- /dev/null -+++ b/fs/aufs/dynop.h -@@ -0,0 +1,64 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2010-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * dynamically customizable operations (for regular files only) -+ */ -+ -+#ifndef __AUFS_DYNOP_H__ -+#define __AUFS_DYNOP_H__ -+ -+#ifdef __KERNEL__ -+ -+#include -+#include -+ -+enum {AuDy_AOP, AuDyLast}; -+ -+struct au_dynop { -+ int dy_type; -+ union { -+ const void *dy_hop; -+ const struct address_space_operations *dy_haop; -+ }; -+}; -+ -+struct au_dykey { -+ union { -+ struct hlist_bl_node dk_hnode; -+ struct rcu_head dk_rcu; -+ }; -+ struct au_dynop dk_op; -+ -+ /* -+ * during I am in the branch local array, kref is gotten. when the -+ * branch is removed, kref is put. -+ */ -+ struct kref dk_kref; -+}; -+ -+/* stop unioning since their sizes are very different from each other */ -+struct au_dyaop { -+ struct au_dykey da_key; -+ struct address_space_operations da_op; /* not const */ -+}; -+/* make sure that 'struct au_dykey *' can be any type */ -+static_assert(!offsetof(struct au_dyaop, da_key)); -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* dynop.c */ -+struct au_branch; -+void au_dy_put(struct au_dykey *key); -+int au_dy_iaop(struct inode *inode, aufs_bindex_t bindex, -+ struct inode *h_inode); -+int au_dy_irefresh(struct inode *inode); -+void au_dy_arefresh(int do_dio); -+ -+void __init au_dy_init(void); -+void au_dy_fin(void); -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_DYNOP_H__ */ -diff --git a/fs/aufs/export.c b/fs/aufs/export.c -new file mode 100644 -index 000000000000..33ae8ac42c5c ---- /dev/null -+++ b/fs/aufs/export.c -@@ -0,0 +1,825 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * export via nfs -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include "aufs.h" -+ -+union conv { -+#ifdef CONFIG_AUFS_INO_T_64 -+ __u32 a[2]; -+#else -+ __u32 a[1]; -+#endif -+ ino_t ino; -+}; -+ -+static ino_t decode_ino(__u32 *a) -+{ -+ union conv u; -+ -+ BUILD_BUG_ON(sizeof(u.ino) != sizeof(u.a)); -+ u.a[0] = a[0]; -+#ifdef CONFIG_AUFS_INO_T_64 -+ u.a[1] = a[1]; -+#endif -+ return u.ino; -+} -+ -+static void encode_ino(__u32 *a, ino_t ino) -+{ -+ union conv u; -+ -+ u.ino = ino; -+ a[0] = u.a[0]; -+#ifdef CONFIG_AUFS_INO_T_64 -+ a[1] = u.a[1]; -+#endif -+} -+ -+/* NFS file handle */ -+enum { -+ Fh_br_id, -+ Fh_sigen, -+#ifdef CONFIG_AUFS_INO_T_64 -+ /* support 64bit inode number */ -+ Fh_ino1, -+ Fh_ino2, -+ Fh_dir_ino1, -+ Fh_dir_ino2, -+#else -+ Fh_ino1, -+ Fh_dir_ino1, -+#endif -+ Fh_igen, -+ Fh_h_type, -+ Fh_tail, -+ -+ Fh_ino = Fh_ino1, -+ Fh_dir_ino = Fh_dir_ino1 -+}; -+ -+static int au_test_anon(struct dentry *dentry) -+{ -+ /* note: read d_flags without d_lock */ -+ return !!(dentry->d_flags & DCACHE_DISCONNECTED); -+} -+ -+int au_test_nfsd(void) -+{ -+ int ret; -+ struct task_struct *tsk = current; -+ char comm[sizeof(tsk->comm)]; -+ -+ ret = 0; -+ if (tsk->flags & PF_KTHREAD) { -+ get_task_comm(comm, tsk); -+ ret = !strcmp(comm, "nfsd"); -+ } -+ -+ return ret; -+} -+ -+/* ---------------------------------------------------------------------- */ -+/* inode generation external table */ -+ -+void au_xigen_inc(struct inode *inode) -+{ -+ loff_t pos; -+ ssize_t sz; -+ __u32 igen; -+ struct super_block *sb; -+ struct au_sbinfo *sbinfo; -+ -+ sb = inode->i_sb; -+ AuDebugOn(!au_opt_test(au_mntflags(sb), XINO)); -+ -+ sbinfo = au_sbi(sb); -+ pos = inode->i_ino; -+ pos *= sizeof(igen); -+ igen = inode->i_generation + 1; -+ sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xigen, &igen, -+ sizeof(igen), &pos); -+ if (sz == sizeof(igen)) -+ return; /* success */ -+ -+ if (unlikely(sz >= 0)) -+ AuIOErr("xigen error (%zd)\n", sz); -+} -+ -+int au_xigen_new(struct inode *inode) -+{ -+ int err; -+ loff_t pos; -+ ssize_t sz; -+ struct super_block *sb; -+ struct au_sbinfo *sbinfo; -+ struct file *file; -+ -+ err = 0; -+ /* todo: dirty, at mount time */ -+ if (inode->i_ino == AUFS_ROOT_INO) -+ goto out; -+ sb = inode->i_sb; -+ SiMustAnyLock(sb); -+ if (unlikely(!au_opt_test(au_mntflags(sb), XINO))) -+ goto out; -+ -+ err = -EFBIG; -+ pos = inode->i_ino; -+ if (unlikely(au_loff_max / sizeof(inode->i_generation) - 1 < pos)) { -+ AuIOErr1("too large i%lld\n", pos); -+ goto out; -+ } -+ pos *= sizeof(inode->i_generation); -+ -+ err = 0; -+ sbinfo = au_sbi(sb); -+ file = sbinfo->si_xigen; -+ BUG_ON(!file); -+ -+ if (vfsub_f_size_read(file) -+ < pos + sizeof(inode->i_generation)) { -+ inode->i_generation = atomic_inc_return(&sbinfo->si_xigen_next); -+ sz = xino_fwrite(sbinfo->si_xwrite, file, &inode->i_generation, -+ sizeof(inode->i_generation), &pos); -+ } else -+ sz = xino_fread(sbinfo->si_xread, file, &inode->i_generation, -+ sizeof(inode->i_generation), &pos); -+ if (sz == sizeof(inode->i_generation)) -+ goto out; /* success */ -+ -+ err = sz; -+ if (unlikely(sz >= 0)) { -+ err = -EIO; -+ AuIOErr("xigen error (%zd)\n", sz); -+ } -+ -+out: -+ return err; -+} -+ -+int au_xigen_set(struct super_block *sb, struct path *path) -+{ -+ int err; -+ struct au_sbinfo *sbinfo; -+ struct file *file; -+ -+ SiMustWriteLock(sb); -+ -+ sbinfo = au_sbi(sb); -+ file = au_xino_create2(sb, path, sbinfo->si_xigen); -+ err = PTR_ERR(file); -+ if (IS_ERR(file)) -+ goto out; -+ err = 0; -+ if (sbinfo->si_xigen) -+ fput(sbinfo->si_xigen); -+ sbinfo->si_xigen = file; -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+void au_xigen_clr(struct super_block *sb) -+{ -+ struct au_sbinfo *sbinfo; -+ -+ SiMustWriteLock(sb); -+ -+ sbinfo = au_sbi(sb); -+ if (sbinfo->si_xigen) { -+ fput(sbinfo->si_xigen); -+ sbinfo->si_xigen = NULL; -+ } -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static struct dentry *decode_by_ino(struct super_block *sb, ino_t ino, -+ ino_t dir_ino) -+{ -+ struct dentry *dentry, *d; -+ struct inode *inode; -+ unsigned int sigen; -+ -+ dentry = NULL; -+ inode = ilookup(sb, ino); -+ if (!inode) -+ goto out; -+ -+ dentry = ERR_PTR(-ESTALE); -+ sigen = au_sigen(sb); -+ if (unlikely(au_is_bad_inode(inode) -+ || IS_DEADDIR(inode) -+ || sigen != au_iigen(inode, NULL))) -+ goto out_iput; -+ -+ dentry = NULL; -+ if (!dir_ino || S_ISDIR(inode->i_mode)) -+ dentry = d_find_alias(inode); -+ else { -+ spin_lock(&inode->i_lock); -+ hlist_for_each_entry(d, &inode->i_dentry, d_u.d_alias) { -+ spin_lock(&d->d_lock); -+ if (!au_test_anon(d) -+ && d_inode(d->d_parent)->i_ino == dir_ino) { -+ dentry = dget_dlock(d); -+ spin_unlock(&d->d_lock); -+ break; -+ } -+ spin_unlock(&d->d_lock); -+ } -+ spin_unlock(&inode->i_lock); -+ } -+ if (unlikely(dentry && au_digen_test(dentry, sigen))) { -+ /* need to refresh */ -+ dput(dentry); -+ dentry = NULL; -+ } -+ -+out_iput: -+ iput(inode); -+out: -+ AuTraceErrPtr(dentry); -+ return dentry; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* todo: dirty? */ -+/* if exportfs_decode_fh() passed vfsmount*, we could be happy */ -+ -+struct au_compare_mnt_args { -+ /* input */ -+ struct super_block *sb; -+ -+ /* output */ -+ struct vfsmount *mnt; -+}; -+ -+static int au_compare_mnt(struct vfsmount *mnt, void *arg) -+{ -+ struct au_compare_mnt_args *a = arg; -+ -+ if (mnt->mnt_sb != a->sb) -+ return 0; -+ a->mnt = mntget(mnt); -+ return 1; -+} -+ -+static struct vfsmount *au_mnt_get(struct super_block *sb) -+{ -+ int err; -+ struct path root; -+ struct au_compare_mnt_args args = { -+ .sb = sb -+ }; -+ -+ get_fs_root(current->fs, &root); -+ rcu_read_lock(); -+ err = iterate_mounts(au_compare_mnt, &args, root.mnt); -+ rcu_read_unlock(); -+ path_put(&root); -+ AuDebugOn(!err); -+ AuDebugOn(!args.mnt); -+ return args.mnt; -+} -+ -+struct au_nfsd_si_lock { -+ unsigned int sigen; -+ aufs_bindex_t bindex, br_id; -+ unsigned char force_lock; -+}; -+ -+static int si_nfsd_read_lock(struct super_block *sb, -+ struct au_nfsd_si_lock *nsi_lock) -+{ -+ int err; -+ aufs_bindex_t bindex; -+ -+ si_read_lock(sb, AuLock_FLUSH); -+ -+ /* branch id may be wrapped around */ -+ err = 0; -+ bindex = au_br_index(sb, nsi_lock->br_id); -+ if (bindex >= 0 && nsi_lock->sigen + AUFS_BRANCH_MAX > au_sigen(sb)) -+ goto out; /* success */ -+ -+ err = -ESTALE; -+ bindex = -1; -+ if (!nsi_lock->force_lock) -+ si_read_unlock(sb); -+ -+out: -+ nsi_lock->bindex = bindex; -+ return err; -+} -+ -+struct find_name_by_ino { -+ struct dir_context ctx; -+ int called, found; -+ ino_t ino; -+ char *name; -+ int namelen; -+}; -+ -+static int -+find_name_by_ino(struct dir_context *ctx, const char *name, int namelen, -+ loff_t offset, u64 ino, unsigned int d_type) -+{ -+ struct find_name_by_ino *a = container_of(ctx, struct find_name_by_ino, -+ ctx); -+ -+ a->called++; -+ if (a->ino != ino) -+ return 0; -+ -+ memcpy(a->name, name, namelen); -+ a->namelen = namelen; -+ a->found = 1; -+ return 1; -+} -+ -+static struct dentry *au_lkup_by_ino(struct path *path, ino_t ino, -+ struct au_nfsd_si_lock *nsi_lock) -+{ -+ struct dentry *dentry, *parent; -+ struct file *file; -+ struct inode *dir; -+ struct find_name_by_ino arg = { -+ .ctx = { -+ .actor = find_name_by_ino -+ } -+ }; -+ int err; -+ -+ parent = path->dentry; -+ if (nsi_lock) -+ si_read_unlock(parent->d_sb); -+ file = vfsub_dentry_open(path, au_dir_roflags); -+ dentry = (void *)file; -+ if (IS_ERR(file)) -+ goto out; -+ -+ dentry = ERR_PTR(-ENOMEM); -+ arg.name = (void *)__get_free_page(GFP_NOFS); -+ if (unlikely(!arg.name)) -+ goto out_file; -+ arg.ino = ino; -+ arg.found = 0; -+ do { -+ arg.called = 0; -+ /* smp_mb(); */ -+ err = vfsub_iterate_dir(file, &arg.ctx); -+ } while (!err && !arg.found && arg.called); -+ dentry = ERR_PTR(err); -+ if (unlikely(err)) -+ goto out_name; -+ /* instead of ENOENT */ -+ dentry = ERR_PTR(-ESTALE); -+ if (!arg.found) -+ goto out_name; -+ -+ /* do not call vfsub_lkup_one() */ -+ dir = d_inode(parent); -+ dentry = vfsub_lookup_one_len_unlocked(arg.name, parent, arg.namelen); -+ AuTraceErrPtr(dentry); -+ if (IS_ERR(dentry)) -+ goto out_name; -+ AuDebugOn(au_test_anon(dentry)); -+ if (unlikely(d_really_is_negative(dentry))) { -+ dput(dentry); -+ dentry = ERR_PTR(-ENOENT); -+ } -+ -+out_name: -+ free_page((unsigned long)arg.name); -+out_file: -+ fput(file); -+out: -+ if (unlikely(nsi_lock -+ && si_nfsd_read_lock(parent->d_sb, nsi_lock) < 0)) -+ if (!IS_ERR(dentry)) { -+ dput(dentry); -+ dentry = ERR_PTR(-ESTALE); -+ } -+ AuTraceErrPtr(dentry); -+ return dentry; -+} -+ -+static struct dentry *decode_by_dir_ino(struct super_block *sb, ino_t ino, -+ ino_t dir_ino, -+ struct au_nfsd_si_lock *nsi_lock) -+{ -+ struct dentry *dentry; -+ struct path path; -+ -+ if (dir_ino != AUFS_ROOT_INO) { -+ path.dentry = decode_by_ino(sb, dir_ino, 0); -+ dentry = path.dentry; -+ if (!path.dentry || IS_ERR(path.dentry)) -+ goto out; -+ AuDebugOn(au_test_anon(path.dentry)); -+ } else -+ path.dentry = dget(sb->s_root); -+ -+ path.mnt = au_mnt_get(sb); -+ dentry = au_lkup_by_ino(&path, ino, nsi_lock); -+ path_put(&path); -+ -+out: -+ AuTraceErrPtr(dentry); -+ return dentry; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int h_acceptable(void *expv, struct dentry *dentry) -+{ -+ return 1; -+} -+ -+static char *au_build_path(struct dentry *h_parent, struct path *h_rootpath, -+ char *buf, int len, struct super_block *sb) -+{ -+ char *p; -+ int n; -+ struct path path; -+ -+ p = d_path(h_rootpath, buf, len); -+ if (IS_ERR(p)) -+ goto out; -+ n = strlen(p); -+ -+ path.mnt = h_rootpath->mnt; -+ path.dentry = h_parent; -+ p = d_path(&path, buf, len); -+ if (IS_ERR(p)) -+ goto out; -+ if (n != 1) -+ p += n; -+ -+ path.mnt = au_mnt_get(sb); -+ path.dentry = sb->s_root; -+ p = d_path(&path, buf, len - strlen(p)); -+ mntput(path.mnt); -+ if (IS_ERR(p)) -+ goto out; -+ if (n != 1) -+ p[strlen(p)] = '/'; -+ -+out: -+ AuTraceErrPtr(p); -+ return p; -+} -+ -+static -+struct dentry *decode_by_path(struct super_block *sb, ino_t ino, __u32 *fh, -+ int fh_len, struct au_nfsd_si_lock *nsi_lock) -+{ -+ struct dentry *dentry, *h_parent, *root; -+ struct super_block *h_sb; -+ char *pathname, *p; -+ struct vfsmount *h_mnt; -+ struct au_branch *br; -+ int err; -+ struct path path; -+ -+ br = au_sbr(sb, nsi_lock->bindex); -+ h_mnt = au_br_mnt(br); -+ h_sb = h_mnt->mnt_sb; -+ /* todo: call lower fh_to_dentry()? fh_to_parent()? */ -+ lockdep_off(); -+ h_parent = exportfs_decode_fh(h_mnt, (void *)(fh + Fh_tail), -+ fh_len - Fh_tail, fh[Fh_h_type], -+ h_acceptable, /*context*/NULL); -+ lockdep_on(); -+ dentry = h_parent; -+ if (unlikely(!h_parent || IS_ERR(h_parent))) { -+ AuWarn1("%s decode_fh failed, %ld\n", -+ au_sbtype(h_sb), PTR_ERR(h_parent)); -+ goto out; -+ } -+ dentry = NULL; -+ if (unlikely(au_test_anon(h_parent))) { -+ AuWarn1("%s decode_fh returned a disconnected dentry\n", -+ au_sbtype(h_sb)); -+ goto out_h_parent; -+ } -+ -+ dentry = ERR_PTR(-ENOMEM); -+ pathname = (void *)__get_free_page(GFP_NOFS); -+ if (unlikely(!pathname)) -+ goto out_h_parent; -+ -+ root = sb->s_root; -+ path.mnt = h_mnt; -+ di_read_lock_parent(root, !AuLock_IR); -+ path.dentry = au_h_dptr(root, nsi_lock->bindex); -+ di_read_unlock(root, !AuLock_IR); -+ p = au_build_path(h_parent, &path, pathname, PAGE_SIZE, sb); -+ dentry = (void *)p; -+ if (IS_ERR(p)) -+ goto out_pathname; -+ -+ si_read_unlock(sb); -+ err = vfsub_kern_path(p, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path); -+ dentry = ERR_PTR(err); -+ if (unlikely(err)) -+ goto out_relock; -+ -+ dentry = ERR_PTR(-ENOENT); -+ AuDebugOn(au_test_anon(path.dentry)); -+ if (unlikely(d_really_is_negative(path.dentry))) -+ goto out_path; -+ -+ if (ino != d_inode(path.dentry)->i_ino) -+ dentry = au_lkup_by_ino(&path, ino, /*nsi_lock*/NULL); -+ else -+ dentry = dget(path.dentry); -+ -+out_path: -+ path_put(&path); -+out_relock: -+ if (unlikely(si_nfsd_read_lock(sb, nsi_lock) < 0)) -+ if (!IS_ERR(dentry)) { -+ dput(dentry); -+ dentry = ERR_PTR(-ESTALE); -+ } -+out_pathname: -+ free_page((unsigned long)pathname); -+out_h_parent: -+ dput(h_parent); -+out: -+ AuTraceErrPtr(dentry); -+ return dentry; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static struct dentry * -+aufs_fh_to_dentry(struct super_block *sb, struct fid *fid, int fh_len, -+ int fh_type) -+{ -+ struct dentry *dentry; -+ __u32 *fh = fid->raw; -+ struct au_branch *br; -+ ino_t ino, dir_ino; -+ struct au_nfsd_si_lock nsi_lock = { -+ .force_lock = 0 -+ }; -+ -+ dentry = ERR_PTR(-ESTALE); -+ /* it should never happen, but the file handle is unreliable */ -+ if (unlikely(fh_len < Fh_tail)) -+ goto out; -+ nsi_lock.sigen = fh[Fh_sigen]; -+ nsi_lock.br_id = fh[Fh_br_id]; -+ -+ /* branch id may be wrapped around */ -+ br = NULL; -+ if (unlikely(si_nfsd_read_lock(sb, &nsi_lock))) -+ goto out; -+ nsi_lock.force_lock = 1; -+ -+ /* is this inode still cached? */ -+ ino = decode_ino(fh + Fh_ino); -+ /* it should never happen */ -+ if (unlikely(ino == AUFS_ROOT_INO)) -+ goto out_unlock; -+ -+ dir_ino = decode_ino(fh + Fh_dir_ino); -+ dentry = decode_by_ino(sb, ino, dir_ino); -+ if (IS_ERR(dentry)) -+ goto out_unlock; -+ if (dentry) -+ goto accept; -+ -+ /* is the parent dir cached? */ -+ br = au_sbr(sb, nsi_lock.bindex); -+ au_lcnt_inc(&br->br_nfiles); -+ dentry = decode_by_dir_ino(sb, ino, dir_ino, &nsi_lock); -+ if (IS_ERR(dentry)) -+ goto out_unlock; -+ if (dentry) -+ goto accept; -+ -+ /* lookup path */ -+ dentry = decode_by_path(sb, ino, fh, fh_len, &nsi_lock); -+ if (IS_ERR(dentry)) -+ goto out_unlock; -+ if (unlikely(!dentry)) -+ /* todo?: make it ESTALE */ -+ goto out_unlock; -+ -+accept: -+ if (!au_digen_test(dentry, au_sigen(sb)) -+ && d_inode(dentry)->i_generation == fh[Fh_igen]) -+ goto out_unlock; /* success */ -+ -+ dput(dentry); -+ dentry = ERR_PTR(-ESTALE); -+out_unlock: -+ if (br) -+ au_lcnt_dec(&br->br_nfiles); -+ si_read_unlock(sb); -+out: -+ AuTraceErrPtr(dentry); -+ return dentry; -+} -+ -+#if 0 /* reserved for future use */ -+/* support subtreecheck option */ -+static struct dentry *aufs_fh_to_parent(struct super_block *sb, struct fid *fid, -+ int fh_len, int fh_type) -+{ -+ struct dentry *parent; -+ __u32 *fh = fid->raw; -+ ino_t dir_ino; -+ -+ dir_ino = decode_ino(fh + Fh_dir_ino); -+ parent = decode_by_ino(sb, dir_ino, 0); -+ if (IS_ERR(parent)) -+ goto out; -+ if (!parent) -+ parent = decode_by_path(sb, au_br_index(sb, fh[Fh_br_id]), -+ dir_ino, fh, fh_len); -+ -+out: -+ AuTraceErrPtr(parent); -+ return parent; -+} -+#endif -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int aufs_encode_fh(struct inode *inode, __u32 *fh, int *max_len, -+ struct inode *dir) -+{ -+ int err; -+ aufs_bindex_t bindex; -+ struct super_block *sb, *h_sb; -+ struct dentry *dentry, *parent, *h_parent; -+ struct inode *h_dir; -+ struct au_branch *br; -+ -+ err = -ENOSPC; -+ if (unlikely(*max_len <= Fh_tail)) { -+ AuWarn1("NFSv2 client (max_len %d)?\n", *max_len); -+ goto out; -+ } -+ -+ err = FILEID_ROOT; -+ if (inode->i_ino == AUFS_ROOT_INO) { -+ AuDebugOn(inode->i_ino != AUFS_ROOT_INO); -+ goto out; -+ } -+ -+ h_parent = NULL; -+ sb = inode->i_sb; -+ err = si_read_lock(sb, AuLock_FLUSH); -+ if (unlikely(err)) -+ goto out; -+ -+#ifdef CONFIG_AUFS_DEBUG -+ if (unlikely(!au_opt_test(au_mntflags(sb), XINO))) -+ AuWarn1("NFS-exporting requires xino\n"); -+#endif -+ err = -EIO; -+ parent = NULL; -+ ii_read_lock_child(inode); -+ bindex = au_ibtop(inode); -+ if (!dir) { -+ dentry = d_find_any_alias(inode); -+ if (unlikely(!dentry)) -+ goto out_unlock; -+ AuDebugOn(au_test_anon(dentry)); -+ parent = dget_parent(dentry); -+ dput(dentry); -+ if (unlikely(!parent)) -+ goto out_unlock; -+ if (d_really_is_positive(parent)) -+ dir = d_inode(parent); -+ } -+ -+ ii_read_lock_parent(dir); -+ h_dir = au_h_iptr(dir, bindex); -+ ii_read_unlock(dir); -+ if (unlikely(!h_dir)) -+ goto out_parent; -+ h_parent = d_find_any_alias(h_dir); -+ if (unlikely(!h_parent)) -+ goto out_hparent; -+ -+ err = -EPERM; -+ br = au_sbr(sb, bindex); -+ h_sb = au_br_sb(br); -+ if (unlikely(!h_sb->s_export_op)) { -+ AuErr1("%s branch is not exportable\n", au_sbtype(h_sb)); -+ goto out_hparent; -+ } -+ -+ fh[Fh_br_id] = br->br_id; -+ fh[Fh_sigen] = au_sigen(sb); -+ encode_ino(fh + Fh_ino, inode->i_ino); -+ encode_ino(fh + Fh_dir_ino, dir->i_ino); -+ fh[Fh_igen] = inode->i_generation; -+ -+ *max_len -= Fh_tail; -+ fh[Fh_h_type] = exportfs_encode_fh(h_parent, (void *)(fh + Fh_tail), -+ max_len, -+ /*connectable or subtreecheck*/0); -+ err = fh[Fh_h_type]; -+ *max_len += Fh_tail; -+ /* todo: macros? */ -+ if (err != FILEID_INVALID) -+ err = 99; -+ else -+ AuWarn1("%s encode_fh failed\n", au_sbtype(h_sb)); -+ -+out_hparent: -+ dput(h_parent); -+out_parent: -+ dput(parent); -+out_unlock: -+ ii_read_unlock(inode); -+ si_read_unlock(sb); -+out: -+ if (unlikely(err < 0)) -+ err = FILEID_INVALID; -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int aufs_commit_metadata(struct inode *inode) -+{ -+ int err; -+ aufs_bindex_t bindex; -+ struct super_block *sb; -+ struct inode *h_inode; -+ int (*f)(struct inode *inode); -+ -+ sb = inode->i_sb; -+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW); -+ ii_write_lock_child(inode); -+ bindex = au_ibtop(inode); -+ AuDebugOn(bindex < 0); -+ h_inode = au_h_iptr(inode, bindex); -+ -+ f = h_inode->i_sb->s_export_op->commit_metadata; -+ if (f) -+ err = f(h_inode); -+ else { -+ struct writeback_control wbc = { -+ .sync_mode = WB_SYNC_ALL, -+ .nr_to_write = 0 /* metadata only */ -+ }; -+ -+ err = sync_inode(h_inode, &wbc); -+ } -+ -+ au_cpup_attr_timesizes(inode); -+ ii_write_unlock(inode); -+ si_read_unlock(sb); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static struct export_operations aufs_export_op = { -+ .fh_to_dentry = aufs_fh_to_dentry, -+ /* .fh_to_parent = aufs_fh_to_parent, */ -+ .encode_fh = aufs_encode_fh, -+ .commit_metadata = aufs_commit_metadata -+}; -+ -+void au_export_init(struct super_block *sb) -+{ -+ struct au_sbinfo *sbinfo; -+ __u32 u; -+ -+ BUILD_BUG_ON_MSG(IS_BUILTIN(CONFIG_AUFS_FS) -+ && IS_MODULE(CONFIG_EXPORTFS), -+ AUFS_NAME ": unsupported configuration " -+ "CONFIG_EXPORTFS=m and CONFIG_AUFS_FS=y"); -+ -+ sb->s_export_op = &aufs_export_op; -+ sbinfo = au_sbi(sb); -+ sbinfo->si_xigen = NULL; -+ get_random_bytes(&u, sizeof(u)); -+ BUILD_BUG_ON(sizeof(u) != sizeof(int)); -+ atomic_set(&sbinfo->si_xigen_next, u); -+} -diff --git a/fs/aufs/f_op.c b/fs/aufs/f_op.c -new file mode 100644 -index 000000000000..c359b1441e96 ---- /dev/null -+++ b/fs/aufs/f_op.c -@@ -0,0 +1,806 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * file and vm operations -+ */ -+ -+#include -+#include -+#include -+#include -+#include "aufs.h" -+ -+int au_do_open_nondir(struct file *file, int flags, struct file *h_file) -+{ -+ int err; -+ aufs_bindex_t bindex; -+ struct dentry *dentry, *h_dentry; -+ struct au_finfo *finfo; -+ struct inode *h_inode; -+ -+ FiMustWriteLock(file); -+ -+ err = 0; -+ dentry = file->f_path.dentry; -+ AuDebugOn(IS_ERR_OR_NULL(dentry)); -+ finfo = au_fi(file); -+ memset(&finfo->fi_htop, 0, sizeof(finfo->fi_htop)); -+ atomic_set(&finfo->fi_mmapped, 0); -+ bindex = au_dbtop(dentry); -+ if (!h_file) { -+ h_dentry = au_h_dptr(dentry, bindex); -+ err = vfsub_test_mntns(file->f_path.mnt, h_dentry->d_sb); -+ if (unlikely(err)) -+ goto out; -+ h_file = au_h_open(dentry, bindex, flags, file, /*force_wr*/0); -+ if (IS_ERR(h_file)) { -+ err = PTR_ERR(h_file); -+ goto out; -+ } -+ } else { -+ h_dentry = h_file->f_path.dentry; -+ err = vfsub_test_mntns(file->f_path.mnt, h_dentry->d_sb); -+ if (unlikely(err)) -+ goto out; -+ /* br ref is already inc-ed */ -+ } -+ -+ if ((flags & __O_TMPFILE) -+ && !(flags & O_EXCL)) { -+ h_inode = file_inode(h_file); -+ spin_lock(&h_inode->i_lock); -+ h_inode->i_state |= I_LINKABLE; -+ spin_unlock(&h_inode->i_lock); -+ } -+ au_set_fbtop(file, bindex); -+ au_set_h_fptr(file, bindex, h_file); -+ au_update_figen(file); -+ /* todo: necessary? */ -+ /* file->f_ra = h_file->f_ra; */ -+ -+out: -+ return err; -+} -+ -+static int aufs_open_nondir(struct inode *inode __maybe_unused, -+ struct file *file) -+{ -+ int err; -+ struct super_block *sb; -+ struct au_do_open_args args = { -+ .open = au_do_open_nondir -+ }; -+ -+ AuDbg("%pD, f_flags 0x%x, f_mode 0x%x\n", -+ file, vfsub_file_flags(file), file->f_mode); -+ -+ sb = file->f_path.dentry->d_sb; -+ si_read_lock(sb, AuLock_FLUSH); -+ err = au_do_open(file, &args); -+ si_read_unlock(sb); -+ return err; -+} -+ -+int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file) -+{ -+ struct au_finfo *finfo; -+ aufs_bindex_t bindex; -+ -+ finfo = au_fi(file); -+ au_hbl_del(&finfo->fi_hlist, -+ &au_sbi(file->f_path.dentry->d_sb)->si_files); -+ bindex = finfo->fi_btop; -+ if (bindex >= 0) -+ au_set_h_fptr(file, bindex, NULL); -+ -+ au_finfo_fin(file); -+ return 0; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int au_do_flush_nondir(struct file *file, fl_owner_t id) -+{ -+ int err; -+ struct file *h_file; -+ -+ err = 0; -+ h_file = au_hf_top(file); -+ if (h_file) -+ err = vfsub_flush(h_file, id); -+ return err; -+} -+ -+static int aufs_flush_nondir(struct file *file, fl_owner_t id) -+{ -+ return au_do_flush(file, id, au_do_flush_nondir); -+} -+ -+/* ---------------------------------------------------------------------- */ -+/* -+ * read and write functions acquire [fdi]_rwsem once, but release before -+ * mmap_sem. This is because to stop a race condition between mmap(2). -+ * Releasing these aufs-rwsem should be safe, no branch-management (by keeping -+ * si_rwsem), no harmful copy-up should happen. Actually copy-up may happen in -+ * read functions after [fdi]_rwsem are released, but it should be harmless. -+ */ -+ -+/* Callers should call au_read_post() or fput() in the end */ -+struct file *au_read_pre(struct file *file, int keep_fi, unsigned int lsc) -+{ -+ struct file *h_file; -+ int err; -+ -+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0, lsc); -+ if (!err) { -+ di_read_unlock(file->f_path.dentry, AuLock_IR); -+ h_file = au_hf_top(file); -+ get_file(h_file); -+ if (!keep_fi) -+ fi_read_unlock(file); -+ } else -+ h_file = ERR_PTR(err); -+ -+ return h_file; -+} -+ -+static void au_read_post(struct inode *inode, struct file *h_file) -+{ -+ /* update without lock, I don't think it a problem */ -+ fsstack_copy_attr_atime(inode, file_inode(h_file)); -+ fput(h_file); -+} -+ -+struct au_write_pre { -+ /* input */ -+ unsigned int lsc; -+ -+ /* output */ -+ blkcnt_t blks; -+ aufs_bindex_t btop; -+}; -+ -+/* -+ * return with iinfo is write-locked -+ * callers should call au_write_post() or iinfo_write_unlock() + fput() in the -+ * end -+ */ -+static struct file *au_write_pre(struct file *file, int do_ready, -+ struct au_write_pre *wpre) -+{ -+ struct file *h_file; -+ struct dentry *dentry; -+ int err; -+ unsigned int lsc; -+ struct au_pin pin; -+ -+ lsc = 0; -+ if (wpre) -+ lsc = wpre->lsc; -+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1, lsc); -+ h_file = ERR_PTR(err); -+ if (unlikely(err)) -+ goto out; -+ -+ dentry = file->f_path.dentry; -+ if (do_ready) { -+ err = au_ready_to_write(file, -1, &pin); -+ if (unlikely(err)) { -+ h_file = ERR_PTR(err); -+ di_write_unlock(dentry); -+ goto out_fi; -+ } -+ } -+ -+ di_downgrade_lock(dentry, /*flags*/0); -+ if (wpre) -+ wpre->btop = au_fbtop(file); -+ h_file = au_hf_top(file); -+ get_file(h_file); -+ if (wpre) -+ wpre->blks = file_inode(h_file)->i_blocks; -+ if (do_ready) -+ au_unpin(&pin); -+ di_read_unlock(dentry, /*flags*/0); -+ -+out_fi: -+ fi_write_unlock(file); -+out: -+ return h_file; -+} -+ -+static void au_write_post(struct inode *inode, struct file *h_file, -+ struct au_write_pre *wpre, ssize_t written) -+{ -+ struct inode *h_inode; -+ -+ au_cpup_attr_timesizes(inode); -+ AuDebugOn(au_ibtop(inode) != wpre->btop); -+ h_inode = file_inode(h_file); -+ inode->i_mode = h_inode->i_mode; -+ ii_write_unlock(inode); -+ /* AuDbg("blks %llu, %llu\n", (u64)blks, (u64)h_inode->i_blocks); */ -+ if (written > 0) -+ au_fhsm_wrote(inode->i_sb, wpre->btop, -+ /*force*/h_inode->i_blocks > wpre->blks); -+ fput(h_file); -+} -+ -+static ssize_t aufs_read(struct file *file, char __user *buf, size_t count, -+ loff_t *ppos) -+{ -+ ssize_t err; -+ struct inode *inode; -+ struct file *h_file; -+ struct super_block *sb; -+ -+ inode = file_inode(file); -+ sb = inode->i_sb; -+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW); -+ -+ h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0); -+ err = PTR_ERR(h_file); -+ if (IS_ERR(h_file)) -+ goto out; -+ -+ /* filedata may be obsoleted by concurrent copyup, but no problem */ -+ err = vfsub_read_u(h_file, buf, count, ppos); -+ /* todo: necessary? */ -+ /* file->f_ra = h_file->f_ra; */ -+ au_read_post(inode, h_file); -+ -+out: -+ si_read_unlock(sb); -+ return err; -+} -+ -+/* -+ * todo: very ugly -+ * it locks both of i_mutex and si_rwsem for read in safe. -+ * if the plink maintenance mode continues forever (that is the problem), -+ * may loop forever. -+ */ -+static void au_mtx_and_read_lock(struct inode *inode) -+{ -+ int err; -+ struct super_block *sb = inode->i_sb; -+ -+ while (1) { -+ inode_lock(inode); -+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM); -+ if (!err) -+ break; -+ inode_unlock(inode); -+ si_read_lock(sb, AuLock_NOPLMW); -+ si_read_unlock(sb); -+ } -+} -+ -+static ssize_t aufs_write(struct file *file, const char __user *ubuf, -+ size_t count, loff_t *ppos) -+{ -+ ssize_t err; -+ struct au_write_pre wpre; -+ struct inode *inode; -+ struct file *h_file; -+ char __user *buf = (char __user *)ubuf; -+ -+ inode = file_inode(file); -+ au_mtx_and_read_lock(inode); -+ -+ wpre.lsc = 0; -+ h_file = au_write_pre(file, /*do_ready*/1, &wpre); -+ err = PTR_ERR(h_file); -+ if (IS_ERR(h_file)) -+ goto out; -+ -+ err = vfsub_write_u(h_file, buf, count, ppos); -+ au_write_post(inode, h_file, &wpre, err); -+ -+out: -+ si_read_unlock(inode->i_sb); -+ inode_unlock(inode); -+ return err; -+} -+ -+static ssize_t au_do_iter(struct file *h_file, int rw, struct kiocb *kio, -+ struct iov_iter *iov_iter) -+{ -+ ssize_t err; -+ struct file *file; -+ ssize_t (*iter)(struct kiocb *, struct iov_iter *); -+ -+ err = security_file_permission(h_file, rw); -+ if (unlikely(err)) -+ goto out; -+ -+ err = -ENOSYS; /* the branch doesn't have its ->(read|write)_iter() */ -+ iter = NULL; -+ if (rw == MAY_READ) -+ iter = h_file->f_op->read_iter; -+ else if (rw == MAY_WRITE) -+ iter = h_file->f_op->write_iter; -+ -+ file = kio->ki_filp; -+ kio->ki_filp = h_file; -+ if (iter) { -+ lockdep_off(); -+ err = iter(kio, iov_iter); -+ lockdep_on(); -+ } else -+ /* currently there is no such fs */ -+ WARN_ON_ONCE(1); -+ kio->ki_filp = file; -+ -+out: -+ return err; -+} -+ -+static ssize_t aufs_read_iter(struct kiocb *kio, struct iov_iter *iov_iter) -+{ -+ ssize_t err; -+ struct file *file, *h_file; -+ struct inode *inode; -+ struct super_block *sb; -+ -+ file = kio->ki_filp; -+ inode = file_inode(file); -+ sb = inode->i_sb; -+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW); -+ -+ h_file = au_read_pre(file, /*keep_fi*/1, /*lsc*/0); -+ err = PTR_ERR(h_file); -+ if (IS_ERR(h_file)) -+ goto out; -+ -+ if (au_test_loopback_kthread()) { -+ au_warn_loopback(h_file->f_path.dentry->d_sb); -+ if (file->f_mapping != h_file->f_mapping) { -+ file->f_mapping = h_file->f_mapping; -+ smp_mb(); /* unnecessary? */ -+ } -+ } -+ fi_read_unlock(file); -+ -+ err = au_do_iter(h_file, MAY_READ, kio, iov_iter); -+ /* todo: necessary? */ -+ /* file->f_ra = h_file->f_ra; */ -+ au_read_post(inode, h_file); -+ -+out: -+ si_read_unlock(sb); -+ return err; -+} -+ -+static ssize_t aufs_write_iter(struct kiocb *kio, struct iov_iter *iov_iter) -+{ -+ ssize_t err; -+ struct au_write_pre wpre; -+ struct inode *inode; -+ struct file *file, *h_file; -+ -+ file = kio->ki_filp; -+ inode = file_inode(file); -+ au_mtx_and_read_lock(inode); -+ -+ wpre.lsc = 0; -+ h_file = au_write_pre(file, /*do_ready*/1, &wpre); -+ err = PTR_ERR(h_file); -+ if (IS_ERR(h_file)) -+ goto out; -+ -+ err = au_do_iter(h_file, MAY_WRITE, kio, iov_iter); -+ au_write_post(inode, h_file, &wpre, err); -+ -+out: -+ si_read_unlock(inode->i_sb); -+ inode_unlock(inode); -+ return err; -+} -+ -+static ssize_t aufs_splice_read(struct file *file, loff_t *ppos, -+ struct pipe_inode_info *pipe, size_t len, -+ unsigned int flags) -+{ -+ ssize_t err; -+ struct file *h_file; -+ struct inode *inode; -+ struct super_block *sb; -+ -+ inode = file_inode(file); -+ sb = inode->i_sb; -+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW); -+ -+ h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0); -+ err = PTR_ERR(h_file); -+ if (IS_ERR(h_file)) -+ goto out; -+ -+ err = vfsub_splice_to(h_file, ppos, pipe, len, flags); -+ /* todo: necessary? */ -+ /* file->f_ra = h_file->f_ra; */ -+ au_read_post(inode, h_file); -+ -+out: -+ si_read_unlock(sb); -+ return err; -+} -+ -+static ssize_t -+aufs_splice_write(struct pipe_inode_info *pipe, struct file *file, loff_t *ppos, -+ size_t len, unsigned int flags) -+{ -+ ssize_t err; -+ struct au_write_pre wpre; -+ struct inode *inode; -+ struct file *h_file; -+ -+ inode = file_inode(file); -+ au_mtx_and_read_lock(inode); -+ -+ wpre.lsc = 0; -+ h_file = au_write_pre(file, /*do_ready*/1, &wpre); -+ err = PTR_ERR(h_file); -+ if (IS_ERR(h_file)) -+ goto out; -+ -+ err = vfsub_splice_from(pipe, h_file, ppos, len, flags); -+ au_write_post(inode, h_file, &wpre, err); -+ -+out: -+ si_read_unlock(inode->i_sb); -+ inode_unlock(inode); -+ return err; -+} -+ -+static long aufs_fallocate(struct file *file, int mode, loff_t offset, -+ loff_t len) -+{ -+ long err; -+ struct au_write_pre wpre; -+ struct inode *inode; -+ struct file *h_file; -+ -+ inode = file_inode(file); -+ au_mtx_and_read_lock(inode); -+ -+ wpre.lsc = 0; -+ h_file = au_write_pre(file, /*do_ready*/1, &wpre); -+ err = PTR_ERR(h_file); -+ if (IS_ERR(h_file)) -+ goto out; -+ -+ lockdep_off(); -+ err = vfs_fallocate(h_file, mode, offset, len); -+ lockdep_on(); -+ au_write_post(inode, h_file, &wpre, /*written*/1); -+ -+out: -+ si_read_unlock(inode->i_sb); -+ inode_unlock(inode); -+ return err; -+} -+ -+static ssize_t aufs_copy_file_range(struct file *src, loff_t src_pos, -+ struct file *dst, loff_t dst_pos, -+ size_t len, unsigned int flags) -+{ -+ ssize_t err; -+ struct au_write_pre wpre; -+ enum { SRC, DST }; -+ struct { -+ struct inode *inode; -+ struct file *h_file; -+ struct super_block *h_sb; -+ } a[2]; -+#define a_src a[SRC] -+#define a_dst a[DST] -+ -+ err = -EINVAL; -+ a_src.inode = file_inode(src); -+ if (unlikely(!S_ISREG(a_src.inode->i_mode))) -+ goto out; -+ a_dst.inode = file_inode(dst); -+ if (unlikely(!S_ISREG(a_dst.inode->i_mode))) -+ goto out; -+ -+ au_mtx_and_read_lock(a_dst.inode); -+ /* -+ * in order to match the order in di_write_lock2_{child,parent}(), -+ * use f_path.dentry for this comparison. -+ */ -+ if (src->f_path.dentry < dst->f_path.dentry) { -+ a_src.h_file = au_read_pre(src, /*keep_fi*/1, AuLsc_FI_1); -+ err = PTR_ERR(a_src.h_file); -+ if (IS_ERR(a_src.h_file)) -+ goto out_si; -+ -+ wpre.lsc = AuLsc_FI_2; -+ a_dst.h_file = au_write_pre(dst, /*do_ready*/1, &wpre); -+ err = PTR_ERR(a_dst.h_file); -+ if (IS_ERR(a_dst.h_file)) { -+ au_read_post(a_src.inode, a_src.h_file); -+ goto out_si; -+ } -+ } else { -+ wpre.lsc = AuLsc_FI_1; -+ a_dst.h_file = au_write_pre(dst, /*do_ready*/1, &wpre); -+ err = PTR_ERR(a_dst.h_file); -+ if (IS_ERR(a_dst.h_file)) -+ goto out_si; -+ -+ a_src.h_file = au_read_pre(src, /*keep_fi*/1, AuLsc_FI_2); -+ err = PTR_ERR(a_src.h_file); -+ if (IS_ERR(a_src.h_file)) { -+ au_write_post(a_dst.inode, a_dst.h_file, &wpre, -+ /*written*/0); -+ goto out_si; -+ } -+ } -+ -+ err = -EXDEV; -+ a_src.h_sb = file_inode(a_src.h_file)->i_sb; -+ a_dst.h_sb = file_inode(a_dst.h_file)->i_sb; -+ if (unlikely(a_src.h_sb != a_dst.h_sb)) { -+ AuDbgFile(src); -+ AuDbgFile(dst); -+ goto out_file; -+ } -+ -+ err = vfsub_copy_file_range(a_src.h_file, src_pos, a_dst.h_file, -+ dst_pos, len, flags); -+ -+out_file: -+ au_write_post(a_dst.inode, a_dst.h_file, &wpre, err); -+ fi_read_unlock(src); -+ au_read_post(a_src.inode, a_src.h_file); -+out_si: -+ si_read_unlock(a_dst.inode->i_sb); -+ inode_unlock(a_dst.inode); -+out: -+ return err; -+#undef a_src -+#undef a_dst -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * The locking order around current->mmap_sem. -+ * - in most and regular cases -+ * file I/O syscall -- aufs_read() or something -+ * -- si_rwsem for read -- mmap_sem -+ * (Note that [fdi]i_rwsem are released before mmap_sem). -+ * - in mmap case -+ * mmap(2) -- mmap_sem -- aufs_mmap() -- si_rwsem for read -- [fdi]i_rwsem -+ * This AB-BA order is definitely bad, but is not a problem since "si_rwsem for -+ * read" allows multiple processes to acquire it and [fdi]i_rwsem are not held -+ * in file I/O. Aufs needs to stop lockdep in aufs_mmap() though. -+ * It means that when aufs acquires si_rwsem for write, the process should never -+ * acquire mmap_sem. -+ * -+ * Actually aufs_iterate() holds [fdi]i_rwsem before mmap_sem, but this is not a -+ * problem either since any directory is not able to be mmap-ed. -+ * The similar scenario is applied to aufs_readlink() too. -+ */ -+ -+#if 0 /* stop calling security_file_mmap() */ -+/* cf. linux/include/linux/mman.h: calc_vm_prot_bits() */ -+#define AuConv_VM_PROT(f, b) _calc_vm_trans(f, VM_##b, PROT_##b) -+ -+static unsigned long au_arch_prot_conv(unsigned long flags) -+{ -+ /* currently ppc64 only */ -+#ifdef CONFIG_PPC64 -+ /* cf. linux/arch/powerpc/include/asm/mman.h */ -+ AuDebugOn(arch_calc_vm_prot_bits(-1) != VM_SAO); -+ return AuConv_VM_PROT(flags, SAO); -+#else -+ AuDebugOn(arch_calc_vm_prot_bits(-1)); -+ return 0; -+#endif -+} -+ -+static unsigned long au_prot_conv(unsigned long flags) -+{ -+ return AuConv_VM_PROT(flags, READ) -+ | AuConv_VM_PROT(flags, WRITE) -+ | AuConv_VM_PROT(flags, EXEC) -+ | au_arch_prot_conv(flags); -+} -+ -+/* cf. linux/include/linux/mman.h: calc_vm_flag_bits() */ -+#define AuConv_VM_MAP(f, b) _calc_vm_trans(f, VM_##b, MAP_##b) -+ -+static unsigned long au_flag_conv(unsigned long flags) -+{ -+ return AuConv_VM_MAP(flags, GROWSDOWN) -+ | AuConv_VM_MAP(flags, DENYWRITE) -+ | AuConv_VM_MAP(flags, LOCKED); -+} -+#endif -+ -+static int aufs_mmap(struct file *file, struct vm_area_struct *vma) -+{ -+ int err; -+ const unsigned char wlock -+ = (file->f_mode & FMODE_WRITE) && (vma->vm_flags & VM_SHARED); -+ struct super_block *sb; -+ struct file *h_file; -+ struct inode *inode; -+ -+ AuDbgVmRegion(file, vma); -+ -+ inode = file_inode(file); -+ sb = inode->i_sb; -+ lockdep_off(); -+ si_read_lock(sb, AuLock_NOPLMW); -+ -+ h_file = au_write_pre(file, wlock, /*wpre*/NULL); -+ lockdep_on(); -+ err = PTR_ERR(h_file); -+ if (IS_ERR(h_file)) -+ goto out; -+ -+ err = 0; -+ au_set_mmapped(file); -+ au_vm_file_reset(vma, h_file); -+ /* -+ * we cannot call security_mmap_file() here since it may acquire -+ * mmap_sem or i_mutex. -+ * -+ * err = security_mmap_file(h_file, au_prot_conv(vma->vm_flags), -+ * au_flag_conv(vma->vm_flags)); -+ */ -+ if (!err) -+ err = call_mmap(h_file, vma); -+ if (!err) { -+ au_vm_prfile_set(vma, file); -+ fsstack_copy_attr_atime(inode, file_inode(h_file)); -+ goto out_fput; /* success */ -+ } -+ au_unset_mmapped(file); -+ au_vm_file_reset(vma, file); -+ -+out_fput: -+ lockdep_off(); -+ ii_write_unlock(inode); -+ lockdep_on(); -+ fput(h_file); -+out: -+ lockdep_off(); -+ si_read_unlock(sb); -+ lockdep_on(); -+ AuTraceErr(err); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int aufs_fsync_nondir(struct file *file, loff_t start, loff_t end, -+ int datasync) -+{ -+ int err; -+ struct au_write_pre wpre; -+ struct inode *inode; -+ struct file *h_file; -+ -+ err = 0; /* -EBADF; */ /* posix? */ -+ if (unlikely(!(file->f_mode & FMODE_WRITE))) -+ goto out; -+ -+ inode = file_inode(file); -+ au_mtx_and_read_lock(inode); -+ -+ wpre.lsc = 0; -+ h_file = au_write_pre(file, /*do_ready*/1, &wpre); -+ err = PTR_ERR(h_file); -+ if (IS_ERR(h_file)) -+ goto out_unlock; -+ -+ err = vfsub_fsync(h_file, &h_file->f_path, datasync); -+ au_write_post(inode, h_file, &wpre, /*written*/0); -+ -+out_unlock: -+ si_read_unlock(inode->i_sb); -+ inode_unlock(inode); -+out: -+ return err; -+} -+ -+static int aufs_fasync(int fd, struct file *file, int flag) -+{ -+ int err; -+ struct file *h_file; -+ struct super_block *sb; -+ -+ sb = file->f_path.dentry->d_sb; -+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW); -+ -+ h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0); -+ err = PTR_ERR(h_file); -+ if (IS_ERR(h_file)) -+ goto out; -+ -+ if (h_file->f_op->fasync) -+ err = h_file->f_op->fasync(fd, h_file, flag); -+ fput(h_file); /* instead of au_read_post() */ -+ -+out: -+ si_read_unlock(sb); -+ return err; -+} -+ -+static int aufs_setfl(struct file *file, unsigned long arg) -+{ -+ int err; -+ struct file *h_file; -+ struct super_block *sb; -+ -+ sb = file->f_path.dentry->d_sb; -+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW); -+ -+ h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0); -+ err = PTR_ERR(h_file); -+ if (IS_ERR(h_file)) -+ goto out; -+ -+ /* stop calling h_file->fasync */ -+ arg |= vfsub_file_flags(file) & FASYNC; -+ err = setfl(/*unused fd*/-1, h_file, arg); -+ fput(h_file); /* instead of au_read_post() */ -+ -+out: -+ si_read_unlock(sb); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* no one supports this operation, currently */ -+#if 0 /* reserved for future use */ -+static ssize_t aufs_sendpage(struct file *file, struct page *page, int offset, -+ size_t len, loff_t *pos, int more) -+{ -+} -+#endif -+ -+/* ---------------------------------------------------------------------- */ -+ -+const struct file_operations aufs_file_fop = { -+ .owner = THIS_MODULE, -+ -+ .llseek = default_llseek, -+ -+ .read = aufs_read, -+ .write = aufs_write, -+ .read_iter = aufs_read_iter, -+ .write_iter = aufs_write_iter, -+ -+#ifdef CONFIG_AUFS_POLL -+ .poll = aufs_poll, -+#endif -+ .unlocked_ioctl = aufs_ioctl_nondir, -+#ifdef CONFIG_COMPAT -+ .compat_ioctl = aufs_compat_ioctl_nondir, -+#endif -+ .mmap = aufs_mmap, -+ .open = aufs_open_nondir, -+ .flush = aufs_flush_nondir, -+ .release = aufs_release_nondir, -+ .fsync = aufs_fsync_nondir, -+ .fasync = aufs_fasync, -+ /* .sendpage = aufs_sendpage, */ -+ .setfl = aufs_setfl, -+ .splice_write = aufs_splice_write, -+ .splice_read = aufs_splice_read, -+#if 0 /* reserved for future use */ -+ .aio_splice_write = aufs_aio_splice_write, -+ .aio_splice_read = aufs_aio_splice_read, -+#endif -+ .fallocate = aufs_fallocate, -+ .copy_file_range = aufs_copy_file_range -+}; -diff --git a/fs/aufs/fhsm.c b/fs/aufs/fhsm.c -new file mode 100644 -index 000000000000..cb054052cf9a ---- /dev/null -+++ b/fs/aufs/fhsm.c -@@ -0,0 +1,413 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2011-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * File-based Hierarchy Storage Management -+ */ -+ -+#include -+#include -+#include -+#include -+#include "aufs.h" -+ -+static aufs_bindex_t au_fhsm_bottom(struct super_block *sb) -+{ -+ struct au_sbinfo *sbinfo; -+ struct au_fhsm *fhsm; -+ -+ SiMustAnyLock(sb); -+ -+ sbinfo = au_sbi(sb); -+ fhsm = &sbinfo->si_fhsm; -+ AuDebugOn(!fhsm); -+ return fhsm->fhsm_bottom; -+} -+ -+void au_fhsm_set_bottom(struct super_block *sb, aufs_bindex_t bindex) -+{ -+ struct au_sbinfo *sbinfo; -+ struct au_fhsm *fhsm; -+ -+ SiMustWriteLock(sb); -+ -+ sbinfo = au_sbi(sb); -+ fhsm = &sbinfo->si_fhsm; -+ AuDebugOn(!fhsm); -+ fhsm->fhsm_bottom = bindex; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int au_fhsm_test_jiffy(struct au_sbinfo *sbinfo, struct au_branch *br) -+{ -+ struct au_br_fhsm *bf; -+ -+ bf = br->br_fhsm; -+ MtxMustLock(&bf->bf_lock); -+ -+ return !bf->bf_readable -+ || time_after(jiffies, -+ bf->bf_jiffy + sbinfo->si_fhsm.fhsm_expire); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static void au_fhsm_notify(struct super_block *sb, int val) -+{ -+ struct au_sbinfo *sbinfo; -+ struct au_fhsm *fhsm; -+ -+ SiMustAnyLock(sb); -+ -+ sbinfo = au_sbi(sb); -+ fhsm = &sbinfo->si_fhsm; -+ if (au_fhsm_pid(fhsm) -+ && atomic_read(&fhsm->fhsm_readable) != -1) { -+ atomic_set(&fhsm->fhsm_readable, val); -+ if (val) -+ wake_up(&fhsm->fhsm_wqh); -+ } -+} -+ -+static int au_fhsm_stfs(struct super_block *sb, aufs_bindex_t bindex, -+ struct aufs_stfs *rstfs, int do_lock, int do_notify) -+{ -+ int err; -+ struct au_branch *br; -+ struct au_br_fhsm *bf; -+ -+ br = au_sbr(sb, bindex); -+ AuDebugOn(au_br_rdonly(br)); -+ bf = br->br_fhsm; -+ AuDebugOn(!bf); -+ -+ if (do_lock) -+ mutex_lock(&bf->bf_lock); -+ else -+ MtxMustLock(&bf->bf_lock); -+ -+ /* sb->s_root for NFS is unreliable */ -+ err = au_br_stfs(br, &bf->bf_stfs); -+ if (unlikely(err)) { -+ AuErr1("FHSM failed (%d), b%d, ignored.\n", bindex, err); -+ goto out; -+ } -+ -+ bf->bf_jiffy = jiffies; -+ bf->bf_readable = 1; -+ if (do_notify) -+ au_fhsm_notify(sb, /*val*/1); -+ if (rstfs) -+ *rstfs = bf->bf_stfs; -+ -+out: -+ if (do_lock) -+ mutex_unlock(&bf->bf_lock); -+ au_fhsm_notify(sb, /*val*/1); -+ -+ return err; -+} -+ -+void au_fhsm_wrote(struct super_block *sb, aufs_bindex_t bindex, int force) -+{ -+ int err; -+ struct au_sbinfo *sbinfo; -+ struct au_fhsm *fhsm; -+ struct au_branch *br; -+ struct au_br_fhsm *bf; -+ -+ AuDbg("b%d, force %d\n", bindex, force); -+ SiMustAnyLock(sb); -+ -+ sbinfo = au_sbi(sb); -+ fhsm = &sbinfo->si_fhsm; -+ if (!au_ftest_si(sbinfo, FHSM) -+ || fhsm->fhsm_bottom == bindex) -+ return; -+ -+ br = au_sbr(sb, bindex); -+ bf = br->br_fhsm; -+ AuDebugOn(!bf); -+ mutex_lock(&bf->bf_lock); -+ if (force -+ || au_fhsm_pid(fhsm) -+ || au_fhsm_test_jiffy(sbinfo, br)) -+ err = au_fhsm_stfs(sb, bindex, /*rstfs*/NULL, /*do_lock*/0, -+ /*do_notify*/1); -+ mutex_unlock(&bf->bf_lock); -+} -+ -+void au_fhsm_wrote_all(struct super_block *sb, int force) -+{ -+ aufs_bindex_t bindex, bbot; -+ struct au_branch *br; -+ -+ /* exclude the bottom */ -+ bbot = au_fhsm_bottom(sb); -+ for (bindex = 0; bindex < bbot; bindex++) { -+ br = au_sbr(sb, bindex); -+ if (au_br_fhsm(br->br_perm)) -+ au_fhsm_wrote(sb, bindex, force); -+ } -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static __poll_t au_fhsm_poll(struct file *file, struct poll_table_struct *wait) -+{ -+ __poll_t mask; -+ struct au_sbinfo *sbinfo; -+ struct au_fhsm *fhsm; -+ -+ mask = 0; -+ sbinfo = file->private_data; -+ fhsm = &sbinfo->si_fhsm; -+ poll_wait(file, &fhsm->fhsm_wqh, wait); -+ if (atomic_read(&fhsm->fhsm_readable)) -+ mask = EPOLLIN /* | EPOLLRDNORM */; -+ -+ if (!mask) -+ AuDbg("mask 0x%x\n", mask); -+ return mask; -+} -+ -+static int au_fhsm_do_read_one(struct aufs_stbr __user *stbr, -+ struct aufs_stfs *stfs, __s16 brid) -+{ -+ int err; -+ -+ err = copy_to_user(&stbr->stfs, stfs, sizeof(*stfs)); -+ if (!err) -+ err = __put_user(brid, &stbr->brid); -+ if (unlikely(err)) -+ err = -EFAULT; -+ -+ return err; -+} -+ -+static ssize_t au_fhsm_do_read(struct super_block *sb, -+ struct aufs_stbr __user *stbr, size_t count) -+{ -+ ssize_t err; -+ int nstbr; -+ aufs_bindex_t bindex, bbot; -+ struct au_branch *br; -+ struct au_br_fhsm *bf; -+ -+ /* except the bottom branch */ -+ err = 0; -+ nstbr = 0; -+ bbot = au_fhsm_bottom(sb); -+ for (bindex = 0; !err && bindex < bbot; bindex++) { -+ br = au_sbr(sb, bindex); -+ if (!au_br_fhsm(br->br_perm)) -+ continue; -+ -+ bf = br->br_fhsm; -+ mutex_lock(&bf->bf_lock); -+ if (bf->bf_readable) { -+ err = -EFAULT; -+ if (count >= sizeof(*stbr)) -+ err = au_fhsm_do_read_one(stbr++, &bf->bf_stfs, -+ br->br_id); -+ if (!err) { -+ bf->bf_readable = 0; -+ count -= sizeof(*stbr); -+ nstbr++; -+ } -+ } -+ mutex_unlock(&bf->bf_lock); -+ } -+ if (!err) -+ err = sizeof(*stbr) * nstbr; -+ -+ return err; -+} -+ -+static ssize_t au_fhsm_read(struct file *file, char __user *buf, size_t count, -+ loff_t *pos) -+{ -+ ssize_t err; -+ int readable; -+ aufs_bindex_t nfhsm, bindex, bbot; -+ struct au_sbinfo *sbinfo; -+ struct au_fhsm *fhsm; -+ struct au_branch *br; -+ struct super_block *sb; -+ -+ err = 0; -+ sbinfo = file->private_data; -+ fhsm = &sbinfo->si_fhsm; -+need_data: -+ spin_lock_irq(&fhsm->fhsm_wqh.lock); -+ if (!atomic_read(&fhsm->fhsm_readable)) { -+ if (vfsub_file_flags(file) & O_NONBLOCK) -+ err = -EAGAIN; -+ else -+ err = wait_event_interruptible_locked_irq -+ (fhsm->fhsm_wqh, -+ atomic_read(&fhsm->fhsm_readable)); -+ } -+ spin_unlock_irq(&fhsm->fhsm_wqh.lock); -+ if (unlikely(err)) -+ goto out; -+ -+ /* sb may already be dead */ -+ au_rw_read_lock(&sbinfo->si_rwsem); -+ readable = atomic_read(&fhsm->fhsm_readable); -+ if (readable > 0) { -+ sb = sbinfo->si_sb; -+ AuDebugOn(!sb); -+ /* exclude the bottom branch */ -+ nfhsm = 0; -+ bbot = au_fhsm_bottom(sb); -+ for (bindex = 0; bindex < bbot; bindex++) { -+ br = au_sbr(sb, bindex); -+ if (au_br_fhsm(br->br_perm)) -+ nfhsm++; -+ } -+ err = -EMSGSIZE; -+ if (nfhsm * sizeof(struct aufs_stbr) <= count) { -+ atomic_set(&fhsm->fhsm_readable, 0); -+ err = au_fhsm_do_read(sbinfo->si_sb, (void __user *)buf, -+ count); -+ } -+ } -+ au_rw_read_unlock(&sbinfo->si_rwsem); -+ if (!readable) -+ goto need_data; -+ -+out: -+ return err; -+} -+ -+static int au_fhsm_release(struct inode *inode, struct file *file) -+{ -+ struct au_sbinfo *sbinfo; -+ struct au_fhsm *fhsm; -+ -+ /* sb may already be dead */ -+ sbinfo = file->private_data; -+ fhsm = &sbinfo->si_fhsm; -+ spin_lock(&fhsm->fhsm_spin); -+ fhsm->fhsm_pid = 0; -+ spin_unlock(&fhsm->fhsm_spin); -+ kobject_put(&sbinfo->si_kobj); -+ -+ return 0; -+} -+ -+static const struct file_operations au_fhsm_fops = { -+ .owner = THIS_MODULE, -+ .llseek = noop_llseek, -+ .read = au_fhsm_read, -+ .poll = au_fhsm_poll, -+ .release = au_fhsm_release -+}; -+ -+int au_fhsm_fd(struct super_block *sb, int oflags) -+{ -+ int err, fd; -+ struct au_sbinfo *sbinfo; -+ struct au_fhsm *fhsm; -+ -+ err = -EPERM; -+ if (unlikely(!capable(CAP_SYS_ADMIN))) -+ goto out; -+ -+ err = -EINVAL; -+ if (unlikely(oflags & ~(O_CLOEXEC | O_NONBLOCK))) -+ goto out; -+ -+ err = 0; -+ sbinfo = au_sbi(sb); -+ fhsm = &sbinfo->si_fhsm; -+ spin_lock(&fhsm->fhsm_spin); -+ if (!fhsm->fhsm_pid) -+ fhsm->fhsm_pid = current->pid; -+ else -+ err = -EBUSY; -+ spin_unlock(&fhsm->fhsm_spin); -+ if (unlikely(err)) -+ goto out; -+ -+ oflags |= O_RDONLY; -+ /* oflags |= FMODE_NONOTIFY; */ -+ fd = anon_inode_getfd("[aufs_fhsm]", &au_fhsm_fops, sbinfo, oflags); -+ err = fd; -+ if (unlikely(fd < 0)) -+ goto out_pid; -+ -+ /* succeed regardless 'fhsm' status */ -+ kobject_get(&sbinfo->si_kobj); -+ si_noflush_read_lock(sb); -+ if (au_ftest_si(sbinfo, FHSM)) -+ au_fhsm_wrote_all(sb, /*force*/0); -+ si_read_unlock(sb); -+ goto out; /* success */ -+ -+out_pid: -+ spin_lock(&fhsm->fhsm_spin); -+ fhsm->fhsm_pid = 0; -+ spin_unlock(&fhsm->fhsm_spin); -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+int au_fhsm_br_alloc(struct au_branch *br) -+{ -+ int err; -+ -+ err = 0; -+ br->br_fhsm = kmalloc(sizeof(*br->br_fhsm), GFP_NOFS); -+ if (br->br_fhsm) -+ au_br_fhsm_init(br->br_fhsm); -+ else -+ err = -ENOMEM; -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+void au_fhsm_fin(struct super_block *sb) -+{ -+ au_fhsm_notify(sb, /*val*/-1); -+} -+ -+void au_fhsm_init(struct au_sbinfo *sbinfo) -+{ -+ struct au_fhsm *fhsm; -+ -+ fhsm = &sbinfo->si_fhsm; -+ spin_lock_init(&fhsm->fhsm_spin); -+ init_waitqueue_head(&fhsm->fhsm_wqh); -+ atomic_set(&fhsm->fhsm_readable, 0); -+ fhsm->fhsm_expire -+ = msecs_to_jiffies(AUFS_FHSM_CACHE_DEF_SEC * MSEC_PER_SEC); -+ fhsm->fhsm_bottom = -1; -+} -+ -+void au_fhsm_set(struct au_sbinfo *sbinfo, unsigned int sec) -+{ -+ sbinfo->si_fhsm.fhsm_expire -+ = msecs_to_jiffies(sec * MSEC_PER_SEC); -+} -+ -+void au_fhsm_show(struct seq_file *seq, struct au_sbinfo *sbinfo) -+{ -+ unsigned int u; -+ -+ if (!au_ftest_si(sbinfo, FHSM)) -+ return; -+ -+ u = jiffies_to_msecs(sbinfo->si_fhsm.fhsm_expire) / MSEC_PER_SEC; -+ if (u != AUFS_FHSM_CACHE_DEF_SEC) -+ seq_printf(seq, ",fhsm_sec=%u", u); -+} -diff --git a/fs/aufs/file.c b/fs/aufs/file.c -new file mode 100644 -index 000000000000..3911b2e7e46f ---- /dev/null -+++ b/fs/aufs/file.c -@@ -0,0 +1,850 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * handling file/dir, and address_space operation -+ */ -+ -+#ifdef CONFIG_AUFS_DEBUG -+#include -+#endif -+#include -+#include "aufs.h" -+ -+/* drop flags for writing */ -+unsigned int au_file_roflags(unsigned int flags) -+{ -+ flags &= ~(O_WRONLY | O_RDWR | O_APPEND | O_CREAT | O_TRUNC); -+ flags |= O_RDONLY | O_NOATIME; -+ return flags; -+} -+ -+/* common functions to regular file and dir */ -+struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags, -+ struct file *file, int force_wr) -+{ -+ struct file *h_file; -+ struct dentry *h_dentry; -+ struct inode *h_inode; -+ struct super_block *sb; -+ struct au_branch *br; -+ struct path h_path; -+ int err; -+ -+ /* a race condition can happen between open and unlink/rmdir */ -+ h_file = ERR_PTR(-ENOENT); -+ h_dentry = au_h_dptr(dentry, bindex); -+ if (au_test_nfsd() && (!h_dentry || d_is_negative(h_dentry))) -+ goto out; -+ h_inode = d_inode(h_dentry); -+ spin_lock(&h_dentry->d_lock); -+ err = (!d_unhashed(dentry) && d_unlinked(h_dentry)) -+ /* || !d_inode(dentry)->i_nlink */ -+ ; -+ spin_unlock(&h_dentry->d_lock); -+ if (unlikely(err)) -+ goto out; -+ -+ sb = dentry->d_sb; -+ br = au_sbr(sb, bindex); -+ err = au_br_test_oflag(flags, br); -+ h_file = ERR_PTR(err); -+ if (unlikely(err)) -+ goto out; -+ -+ /* drop flags for writing */ -+ if (au_test_ro(sb, bindex, d_inode(dentry))) { -+ if (force_wr && !(flags & O_WRONLY)) -+ force_wr = 0; -+ flags = au_file_roflags(flags); -+ if (force_wr) { -+ h_file = ERR_PTR(-EROFS); -+ flags = au_file_roflags(flags); -+ if (unlikely(vfsub_native_ro(h_inode) -+ || IS_APPEND(h_inode))) -+ goto out; -+ flags &= ~O_ACCMODE; -+ flags |= O_WRONLY; -+ } -+ } -+ flags &= ~O_CREAT; -+ au_lcnt_inc(&br->br_nfiles); -+ h_path.dentry = h_dentry; -+ h_path.mnt = au_br_mnt(br); -+ h_file = vfsub_dentry_open(&h_path, flags); -+ if (IS_ERR(h_file)) -+ goto out_br; -+ -+ if (flags & __FMODE_EXEC) { -+ err = deny_write_access(h_file); -+ if (unlikely(err)) { -+ fput(h_file); -+ h_file = ERR_PTR(err); -+ goto out_br; -+ } -+ } -+ fsnotify_open(h_file); -+ goto out; /* success */ -+ -+out_br: -+ au_lcnt_dec(&br->br_nfiles); -+out: -+ return h_file; -+} -+ -+static int au_cmoo(struct dentry *dentry) -+{ -+ int err, cmoo, matched; -+ unsigned int udba; -+ struct path h_path; -+ struct au_pin pin; -+ struct au_cp_generic cpg = { -+ .dentry = dentry, -+ .bdst = -1, -+ .bsrc = -1, -+ .len = -1, -+ .pin = &pin, -+ .flags = AuCpup_DTIME | AuCpup_HOPEN -+ }; -+ struct inode *delegated; -+ struct super_block *sb; -+ struct au_sbinfo *sbinfo; -+ struct au_fhsm *fhsm; -+ pid_t pid; -+ struct au_branch *br; -+ struct dentry *parent; -+ struct au_hinode *hdir; -+ -+ DiMustWriteLock(dentry); -+ IiMustWriteLock(d_inode(dentry)); -+ -+ err = 0; -+ if (IS_ROOT(dentry)) -+ goto out; -+ cpg.bsrc = au_dbtop(dentry); -+ if (!cpg.bsrc) -+ goto out; -+ -+ sb = dentry->d_sb; -+ sbinfo = au_sbi(sb); -+ fhsm = &sbinfo->si_fhsm; -+ pid = au_fhsm_pid(fhsm); -+ rcu_read_lock(); -+ matched = (pid -+ && (current->pid == pid -+ || rcu_dereference(current->real_parent)->pid == pid)); -+ rcu_read_unlock(); -+ if (matched) -+ goto out; -+ -+ br = au_sbr(sb, cpg.bsrc); -+ cmoo = au_br_cmoo(br->br_perm); -+ if (!cmoo) -+ goto out; -+ if (!d_is_reg(dentry)) -+ cmoo &= AuBrAttr_COO_ALL; -+ if (!cmoo) -+ goto out; -+ -+ parent = dget_parent(dentry); -+ di_write_lock_parent(parent); -+ err = au_wbr_do_copyup_bu(dentry, cpg.bsrc - 1); -+ cpg.bdst = err; -+ if (unlikely(err < 0)) { -+ err = 0; /* there is no upper writable branch */ -+ goto out_dgrade; -+ } -+ AuDbg("bsrc %d, bdst %d\n", cpg.bsrc, cpg.bdst); -+ -+ /* do not respect the coo attrib for the target branch */ -+ err = au_cpup_dirs(dentry, cpg.bdst); -+ if (unlikely(err)) -+ goto out_dgrade; -+ -+ di_downgrade_lock(parent, AuLock_IR); -+ udba = au_opt_udba(sb); -+ err = au_pin(&pin, dentry, cpg.bdst, udba, -+ AuPin_DI_LOCKED | AuPin_MNT_WRITE); -+ if (unlikely(err)) -+ goto out_parent; -+ -+ err = au_sio_cpup_simple(&cpg); -+ au_unpin(&pin); -+ if (unlikely(err)) -+ goto out_parent; -+ if (!(cmoo & AuBrWAttr_MOO)) -+ goto out_parent; /* success */ -+ -+ err = au_pin(&pin, dentry, cpg.bsrc, udba, -+ AuPin_DI_LOCKED | AuPin_MNT_WRITE); -+ if (unlikely(err)) -+ goto out_parent; -+ -+ h_path.mnt = au_br_mnt(br); -+ h_path.dentry = au_h_dptr(dentry, cpg.bsrc); -+ hdir = au_hi(d_inode(parent), cpg.bsrc); -+ delegated = NULL; -+ err = vfsub_unlink(hdir->hi_inode, &h_path, &delegated, /*force*/1); -+ au_unpin(&pin); -+ /* todo: keep h_dentry or not? */ -+ if (unlikely(err == -EWOULDBLOCK)) { -+ pr_warn("cannot retry for NFSv4 delegation" -+ " for an internal unlink\n"); -+ iput(delegated); -+ } -+ if (unlikely(err)) { -+ pr_err("unlink %pd after coo failed (%d), ignored\n", -+ dentry, err); -+ err = 0; -+ } -+ goto out_parent; /* success */ -+ -+out_dgrade: -+ di_downgrade_lock(parent, AuLock_IR); -+out_parent: -+ di_read_unlock(parent, AuLock_IR); -+ dput(parent); -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+int au_do_open(struct file *file, struct au_do_open_args *args) -+{ -+ int err, aopen = args->aopen; -+ struct dentry *dentry; -+ struct au_finfo *finfo; -+ -+ if (!aopen) -+ err = au_finfo_init(file, args->fidir); -+ else { -+ lockdep_off(); -+ err = au_finfo_init(file, args->fidir); -+ lockdep_on(); -+ } -+ if (unlikely(err)) -+ goto out; -+ -+ dentry = file->f_path.dentry; -+ AuDebugOn(IS_ERR_OR_NULL(dentry)); -+ di_write_lock_child(dentry); -+ err = au_cmoo(dentry); -+ di_downgrade_lock(dentry, AuLock_IR); -+ if (!err) { -+ if (!aopen) -+ err = args->open(file, vfsub_file_flags(file), NULL); -+ else { -+ lockdep_off(); -+ err = args->open(file, vfsub_file_flags(file), -+ args->h_file); -+ lockdep_on(); -+ } -+ } -+ di_read_unlock(dentry, AuLock_IR); -+ -+ finfo = au_fi(file); -+ if (!err) { -+ finfo->fi_file = file; -+ au_hbl_add(&finfo->fi_hlist, -+ &au_sbi(file->f_path.dentry->d_sb)->si_files); -+ } -+ if (!aopen) -+ fi_write_unlock(file); -+ else { -+ lockdep_off(); -+ fi_write_unlock(file); -+ lockdep_on(); -+ } -+ if (unlikely(err)) { -+ finfo->fi_hdir = NULL; -+ au_finfo_fin(file); -+ } -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+int au_reopen_nondir(struct file *file) -+{ -+ int err; -+ aufs_bindex_t btop; -+ struct dentry *dentry; -+ struct au_branch *br; -+ struct file *h_file, *h_file_tmp; -+ -+ dentry = file->f_path.dentry; -+ btop = au_dbtop(dentry); -+ br = au_sbr(dentry->d_sb, btop); -+ h_file_tmp = NULL; -+ if (au_fbtop(file) == btop) { -+ h_file = au_hf_top(file); -+ if (file->f_mode == h_file->f_mode) -+ return 0; /* success */ -+ h_file_tmp = h_file; -+ get_file(h_file_tmp); -+ au_lcnt_inc(&br->br_nfiles); -+ au_set_h_fptr(file, btop, NULL); -+ } -+ AuDebugOn(au_fi(file)->fi_hdir); -+ /* -+ * it can happen -+ * file exists on both of rw and ro -+ * open --> dbtop and fbtop are both 0 -+ * prepend a branch as rw, "rw" become ro -+ * remove rw/file -+ * delete the top branch, "rw" becomes rw again -+ * --> dbtop is 1, fbtop is still 0 -+ * write --> fbtop is 0 but dbtop is 1 -+ */ -+ /* AuDebugOn(au_fbtop(file) < btop); */ -+ -+ h_file = au_h_open(dentry, btop, vfsub_file_flags(file) & ~O_TRUNC, -+ file, /*force_wr*/0); -+ err = PTR_ERR(h_file); -+ if (IS_ERR(h_file)) { -+ if (h_file_tmp) { -+ /* revert */ -+ au_set_h_fptr(file, btop, h_file_tmp); -+ h_file_tmp = NULL; -+ } -+ goto out; /* todo: close all? */ -+ } -+ -+ err = 0; -+ au_set_fbtop(file, btop); -+ au_set_h_fptr(file, btop, h_file); -+ au_update_figen(file); -+ /* todo: necessary? */ -+ /* file->f_ra = h_file->f_ra; */ -+ -+out: -+ if (h_file_tmp) { -+ fput(h_file_tmp); -+ au_lcnt_dec(&br->br_nfiles); -+ } -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int au_reopen_wh(struct file *file, aufs_bindex_t btgt, -+ struct dentry *hi_wh) -+{ -+ int err; -+ aufs_bindex_t btop; -+ struct au_dinfo *dinfo; -+ struct dentry *h_dentry; -+ struct au_hdentry *hdp; -+ -+ dinfo = au_di(file->f_path.dentry); -+ AuRwMustWriteLock(&dinfo->di_rwsem); -+ -+ btop = dinfo->di_btop; -+ dinfo->di_btop = btgt; -+ hdp = au_hdentry(dinfo, btgt); -+ h_dentry = hdp->hd_dentry; -+ hdp->hd_dentry = hi_wh; -+ err = au_reopen_nondir(file); -+ hdp->hd_dentry = h_dentry; -+ dinfo->di_btop = btop; -+ -+ return err; -+} -+ -+static int au_ready_to_write_wh(struct file *file, loff_t len, -+ aufs_bindex_t bcpup, struct au_pin *pin) -+{ -+ int err; -+ struct inode *inode, *h_inode; -+ struct dentry *h_dentry, *hi_wh; -+ struct au_cp_generic cpg = { -+ .dentry = file->f_path.dentry, -+ .bdst = bcpup, -+ .bsrc = -1, -+ .len = len, -+ .pin = pin -+ }; -+ -+ au_update_dbtop(cpg.dentry); -+ inode = d_inode(cpg.dentry); -+ h_inode = NULL; -+ if (au_dbtop(cpg.dentry) <= bcpup -+ && au_dbbot(cpg.dentry) >= bcpup) { -+ h_dentry = au_h_dptr(cpg.dentry, bcpup); -+ if (h_dentry && d_is_positive(h_dentry)) -+ h_inode = d_inode(h_dentry); -+ } -+ hi_wh = au_hi_wh(inode, bcpup); -+ if (!hi_wh && !h_inode) -+ err = au_sio_cpup_wh(&cpg, file); -+ else -+ /* already copied-up after unlink */ -+ err = au_reopen_wh(file, bcpup, hi_wh); -+ -+ if (!err -+ && (inode->i_nlink > 1 -+ || (inode->i_state & I_LINKABLE)) -+ && au_opt_test(au_mntflags(cpg.dentry->d_sb), PLINK)) -+ au_plink_append(inode, bcpup, au_h_dptr(cpg.dentry, bcpup)); -+ -+ return err; -+} -+ -+/* -+ * prepare the @file for writing. -+ */ -+int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin) -+{ -+ int err; -+ aufs_bindex_t dbtop; -+ struct dentry *parent; -+ struct inode *inode; -+ struct super_block *sb; -+ struct file *h_file; -+ struct au_cp_generic cpg = { -+ .dentry = file->f_path.dentry, -+ .bdst = -1, -+ .bsrc = -1, -+ .len = len, -+ .pin = pin, -+ .flags = AuCpup_DTIME -+ }; -+ -+ sb = cpg.dentry->d_sb; -+ inode = d_inode(cpg.dentry); -+ cpg.bsrc = au_fbtop(file); -+ err = au_test_ro(sb, cpg.bsrc, inode); -+ if (!err && (au_hf_top(file)->f_mode & FMODE_WRITE)) { -+ err = au_pin(pin, cpg.dentry, cpg.bsrc, AuOpt_UDBA_NONE, -+ /*flags*/0); -+ goto out; -+ } -+ -+ /* need to cpup or reopen */ -+ parent = dget_parent(cpg.dentry); -+ di_write_lock_parent(parent); -+ err = AuWbrCopyup(au_sbi(sb), cpg.dentry); -+ cpg.bdst = err; -+ if (unlikely(err < 0)) -+ goto out_dgrade; -+ err = 0; -+ -+ if (!d_unhashed(cpg.dentry) && !au_h_dptr(parent, cpg.bdst)) { -+ err = au_cpup_dirs(cpg.dentry, cpg.bdst); -+ if (unlikely(err)) -+ goto out_dgrade; -+ } -+ -+ err = au_pin(pin, cpg.dentry, cpg.bdst, AuOpt_UDBA_NONE, -+ AuPin_DI_LOCKED | AuPin_MNT_WRITE); -+ if (unlikely(err)) -+ goto out_dgrade; -+ -+ dbtop = au_dbtop(cpg.dentry); -+ if (dbtop <= cpg.bdst) -+ cpg.bsrc = cpg.bdst; -+ -+ if (dbtop <= cpg.bdst /* just reopen */ -+ || !d_unhashed(cpg.dentry) /* copyup and reopen */ -+ ) { -+ h_file = au_h_open_pre(cpg.dentry, cpg.bsrc, /*force_wr*/0); -+ if (IS_ERR(h_file)) -+ err = PTR_ERR(h_file); -+ else { -+ di_downgrade_lock(parent, AuLock_IR); -+ if (dbtop > cpg.bdst) -+ err = au_sio_cpup_simple(&cpg); -+ if (!err) -+ err = au_reopen_nondir(file); -+ au_h_open_post(cpg.dentry, cpg.bsrc, h_file); -+ } -+ } else { /* copyup as wh and reopen */ -+ /* -+ * since writable hfsplus branch is not supported, -+ * h_open_pre/post() are unnecessary. -+ */ -+ err = au_ready_to_write_wh(file, len, cpg.bdst, pin); -+ di_downgrade_lock(parent, AuLock_IR); -+ } -+ -+ if (!err) { -+ au_pin_set_parent_lflag(pin, /*lflag*/0); -+ goto out_dput; /* success */ -+ } -+ au_unpin(pin); -+ goto out_unlock; -+ -+out_dgrade: -+ di_downgrade_lock(parent, AuLock_IR); -+out_unlock: -+ di_read_unlock(parent, AuLock_IR); -+out_dput: -+ dput(parent); -+out: -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+int au_do_flush(struct file *file, fl_owner_t id, -+ int (*flush)(struct file *file, fl_owner_t id)) -+{ -+ int err; -+ struct super_block *sb; -+ struct inode *inode; -+ -+ inode = file_inode(file); -+ sb = inode->i_sb; -+ si_noflush_read_lock(sb); -+ fi_read_lock(file); -+ ii_read_lock_child(inode); -+ -+ err = flush(file, id); -+ au_cpup_attr_timesizes(inode); -+ -+ ii_read_unlock(inode); -+ fi_read_unlock(file); -+ si_read_unlock(sb); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int au_file_refresh_by_inode(struct file *file, int *need_reopen) -+{ -+ int err; -+ struct au_pin pin; -+ struct au_finfo *finfo; -+ struct dentry *parent, *hi_wh; -+ struct inode *inode; -+ struct super_block *sb; -+ struct au_cp_generic cpg = { -+ .dentry = file->f_path.dentry, -+ .bdst = -1, -+ .bsrc = -1, -+ .len = -1, -+ .pin = &pin, -+ .flags = AuCpup_DTIME -+ }; -+ -+ FiMustWriteLock(file); -+ -+ err = 0; -+ finfo = au_fi(file); -+ sb = cpg.dentry->d_sb; -+ inode = d_inode(cpg.dentry); -+ cpg.bdst = au_ibtop(inode); -+ if (cpg.bdst == finfo->fi_btop || IS_ROOT(cpg.dentry)) -+ goto out; -+ -+ parent = dget_parent(cpg.dentry); -+ if (au_test_ro(sb, cpg.bdst, inode)) { -+ di_read_lock_parent(parent, !AuLock_IR); -+ err = AuWbrCopyup(au_sbi(sb), cpg.dentry); -+ cpg.bdst = err; -+ di_read_unlock(parent, !AuLock_IR); -+ if (unlikely(err < 0)) -+ goto out_parent; -+ err = 0; -+ } -+ -+ di_read_lock_parent(parent, AuLock_IR); -+ hi_wh = au_hi_wh(inode, cpg.bdst); -+ if (!S_ISDIR(inode->i_mode) -+ && au_opt_test(au_mntflags(sb), PLINK) -+ && au_plink_test(inode) -+ && !d_unhashed(cpg.dentry) -+ && cpg.bdst < au_dbtop(cpg.dentry)) { -+ err = au_test_and_cpup_dirs(cpg.dentry, cpg.bdst); -+ if (unlikely(err)) -+ goto out_unlock; -+ -+ /* always superio. */ -+ err = au_pin(&pin, cpg.dentry, cpg.bdst, AuOpt_UDBA_NONE, -+ AuPin_DI_LOCKED | AuPin_MNT_WRITE); -+ if (!err) { -+ err = au_sio_cpup_simple(&cpg); -+ au_unpin(&pin); -+ } -+ } else if (hi_wh) { -+ /* already copied-up after unlink */ -+ err = au_reopen_wh(file, cpg.bdst, hi_wh); -+ *need_reopen = 0; -+ } -+ -+out_unlock: -+ di_read_unlock(parent, AuLock_IR); -+out_parent: -+ dput(parent); -+out: -+ return err; -+} -+ -+static void au_do_refresh_dir(struct file *file) -+{ -+ aufs_bindex_t bindex, bbot, new_bindex, brid; -+ struct au_hfile *p, tmp, *q; -+ struct au_finfo *finfo; -+ struct super_block *sb; -+ struct au_fidir *fidir; -+ -+ FiMustWriteLock(file); -+ -+ sb = file->f_path.dentry->d_sb; -+ finfo = au_fi(file); -+ fidir = finfo->fi_hdir; -+ AuDebugOn(!fidir); -+ p = fidir->fd_hfile + finfo->fi_btop; -+ brid = p->hf_br->br_id; -+ bbot = fidir->fd_bbot; -+ for (bindex = finfo->fi_btop; bindex <= bbot; bindex++, p++) { -+ if (!p->hf_file) -+ continue; -+ -+ new_bindex = au_br_index(sb, p->hf_br->br_id); -+ if (new_bindex == bindex) -+ continue; -+ if (new_bindex < 0) { -+ au_set_h_fptr(file, bindex, NULL); -+ continue; -+ } -+ -+ /* swap two lower inode, and loop again */ -+ q = fidir->fd_hfile + new_bindex; -+ tmp = *q; -+ *q = *p; -+ *p = tmp; -+ if (tmp.hf_file) { -+ bindex--; -+ p--; -+ } -+ } -+ -+ p = fidir->fd_hfile; -+ if (!au_test_mmapped(file) && !d_unlinked(file->f_path.dentry)) { -+ bbot = au_sbbot(sb); -+ for (finfo->fi_btop = 0; finfo->fi_btop <= bbot; -+ finfo->fi_btop++, p++) -+ if (p->hf_file) { -+ if (file_inode(p->hf_file)) -+ break; -+ au_hfput(p, /*execed*/0); -+ } -+ } else { -+ bbot = au_br_index(sb, brid); -+ for (finfo->fi_btop = 0; finfo->fi_btop < bbot; -+ finfo->fi_btop++, p++) -+ if (p->hf_file) -+ au_hfput(p, /*execed*/0); -+ bbot = au_sbbot(sb); -+ } -+ -+ p = fidir->fd_hfile + bbot; -+ for (fidir->fd_bbot = bbot; fidir->fd_bbot >= finfo->fi_btop; -+ fidir->fd_bbot--, p--) -+ if (p->hf_file) { -+ if (file_inode(p->hf_file)) -+ break; -+ au_hfput(p, /*execed*/0); -+ } -+ AuDebugOn(fidir->fd_bbot < finfo->fi_btop); -+} -+ -+/* -+ * after branch manipulating, refresh the file. -+ */ -+static int refresh_file(struct file *file, int (*reopen)(struct file *file)) -+{ -+ int err, need_reopen, nbr; -+ aufs_bindex_t bbot, bindex; -+ struct dentry *dentry; -+ struct super_block *sb; -+ struct au_finfo *finfo; -+ struct au_hfile *hfile; -+ -+ dentry = file->f_path.dentry; -+ sb = dentry->d_sb; -+ nbr = au_sbbot(sb) + 1; -+ finfo = au_fi(file); -+ if (!finfo->fi_hdir) { -+ hfile = &finfo->fi_htop; -+ AuDebugOn(!hfile->hf_file); -+ bindex = au_br_index(sb, hfile->hf_br->br_id); -+ AuDebugOn(bindex < 0); -+ if (bindex != finfo->fi_btop) -+ au_set_fbtop(file, bindex); -+ } else { -+ err = au_fidir_realloc(finfo, nbr, /*may_shrink*/0); -+ if (unlikely(err)) -+ goto out; -+ au_do_refresh_dir(file); -+ } -+ -+ err = 0; -+ need_reopen = 1; -+ if (!au_test_mmapped(file)) -+ err = au_file_refresh_by_inode(file, &need_reopen); -+ if (finfo->fi_hdir) -+ /* harmless if err */ -+ au_fidir_realloc(finfo, nbr, /*may_shrink*/1); -+ if (!err && need_reopen && !d_unlinked(dentry)) -+ err = reopen(file); -+ if (!err) { -+ au_update_figen(file); -+ goto out; /* success */ -+ } -+ -+ /* error, close all lower files */ -+ if (finfo->fi_hdir) { -+ bbot = au_fbbot_dir(file); -+ for (bindex = au_fbtop(file); bindex <= bbot; bindex++) -+ au_set_h_fptr(file, bindex, NULL); -+ } -+ -+out: -+ return err; -+} -+ -+/* common function to regular file and dir */ -+int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file), -+ int wlock, unsigned int fi_lsc) -+{ -+ int err; -+ unsigned int sigen, figen; -+ aufs_bindex_t btop; -+ unsigned char pseudo_link; -+ struct dentry *dentry; -+ struct inode *inode; -+ -+ err = 0; -+ dentry = file->f_path.dentry; -+ inode = d_inode(dentry); -+ sigen = au_sigen(dentry->d_sb); -+ fi_write_lock_nested(file, fi_lsc); -+ figen = au_figen(file); -+ if (!fi_lsc) -+ di_write_lock_child(dentry); -+ else -+ di_write_lock_child2(dentry); -+ btop = au_dbtop(dentry); -+ pseudo_link = (btop != au_ibtop(inode)); -+ if (sigen == figen && !pseudo_link && au_fbtop(file) == btop) { -+ if (!wlock) { -+ di_downgrade_lock(dentry, AuLock_IR); -+ fi_downgrade_lock(file); -+ } -+ goto out; /* success */ -+ } -+ -+ AuDbg("sigen %d, figen %d\n", sigen, figen); -+ if (au_digen_test(dentry, sigen)) { -+ err = au_reval_dpath(dentry, sigen); -+ AuDebugOn(!err && au_digen_test(dentry, sigen)); -+ } -+ -+ if (!err) -+ err = refresh_file(file, reopen); -+ if (!err) { -+ if (!wlock) { -+ di_downgrade_lock(dentry, AuLock_IR); -+ fi_downgrade_lock(file); -+ } -+ } else { -+ di_write_unlock(dentry); -+ fi_write_unlock(file); -+ } -+ -+out: -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* cf. aufs_nopage() */ -+/* for madvise(2) */ -+static int aufs_readpage(struct file *file __maybe_unused, struct page *page) -+{ -+ unlock_page(page); -+ return 0; -+} -+ -+/* it will never be called, but necessary to support O_DIRECT */ -+static ssize_t aufs_direct_IO(struct kiocb *iocb, struct iov_iter *iter) -+{ BUG(); return 0; } -+ -+/* they will never be called. */ -+#ifdef CONFIG_AUFS_DEBUG -+static int aufs_write_begin(struct file *file, struct address_space *mapping, -+ loff_t pos, unsigned len, unsigned flags, -+ struct page **pagep, void **fsdata) -+{ AuUnsupport(); return 0; } -+static int aufs_write_end(struct file *file, struct address_space *mapping, -+ loff_t pos, unsigned len, unsigned copied, -+ struct page *page, void *fsdata) -+{ AuUnsupport(); return 0; } -+static int aufs_writepage(struct page *page, struct writeback_control *wbc) -+{ AuUnsupport(); return 0; } -+ -+static int aufs_set_page_dirty(struct page *page) -+{ AuUnsupport(); return 0; } -+static void aufs_invalidatepage(struct page *page, unsigned int offset, -+ unsigned int length) -+{ AuUnsupport(); } -+static int aufs_releasepage(struct page *page, gfp_t gfp) -+{ AuUnsupport(); return 0; } -+#if 0 /* called by memory compaction regardless file */ -+static int aufs_migratepage(struct address_space *mapping, struct page *newpage, -+ struct page *page, enum migrate_mode mode) -+{ AuUnsupport(); return 0; } -+#endif -+static bool aufs_isolate_page(struct page *page, isolate_mode_t mode) -+{ AuUnsupport(); return true; } -+static void aufs_putback_page(struct page *page) -+{ AuUnsupport(); } -+static int aufs_launder_page(struct page *page) -+{ AuUnsupport(); return 0; } -+static int aufs_is_partially_uptodate(struct page *page, -+ unsigned long from, -+ unsigned long count) -+{ AuUnsupport(); return 0; } -+static void aufs_is_dirty_writeback(struct page *page, bool *dirty, -+ bool *writeback) -+{ AuUnsupport(); } -+static int aufs_error_remove_page(struct address_space *mapping, -+ struct page *page) -+{ AuUnsupport(); return 0; } -+static int aufs_swap_activate(struct swap_info_struct *sis, struct file *file, -+ sector_t *span) -+{ AuUnsupport(); return 0; } -+static void aufs_swap_deactivate(struct file *file) -+{ AuUnsupport(); } -+#endif /* CONFIG_AUFS_DEBUG */ -+ -+const struct address_space_operations aufs_aop = { -+ .readpage = aufs_readpage, -+ .direct_IO = aufs_direct_IO, -+#ifdef CONFIG_AUFS_DEBUG -+ .writepage = aufs_writepage, -+ /* no writepages, because of writepage */ -+ .set_page_dirty = aufs_set_page_dirty, -+ /* no readpages, because of readpage */ -+ .write_begin = aufs_write_begin, -+ .write_end = aufs_write_end, -+ /* no bmap, no block device */ -+ .invalidatepage = aufs_invalidatepage, -+ .releasepage = aufs_releasepage, -+ /* is fallback_migrate_page ok? */ -+ /* .migratepage = aufs_migratepage, */ -+ .isolate_page = aufs_isolate_page, -+ .putback_page = aufs_putback_page, -+ .launder_page = aufs_launder_page, -+ .is_partially_uptodate = aufs_is_partially_uptodate, -+ .is_dirty_writeback = aufs_is_dirty_writeback, -+ .error_remove_page = aufs_error_remove_page, -+ .swap_activate = aufs_swap_activate, -+ .swap_deactivate = aufs_swap_deactivate -+#endif /* CONFIG_AUFS_DEBUG */ -+}; -diff --git a/fs/aufs/file.h b/fs/aufs/file.h -new file mode 100644 -index 000000000000..8bf8e67650d0 ---- /dev/null -+++ b/fs/aufs/file.h -@@ -0,0 +1,329 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * file operations -+ */ -+ -+#ifndef __AUFS_FILE_H__ -+#define __AUFS_FILE_H__ -+ -+#ifdef __KERNEL__ -+ -+#include -+#include -+#include -+#include -+#include "rwsem.h" -+ -+struct au_branch; -+struct au_hfile { -+ struct file *hf_file; -+ struct au_branch *hf_br; -+}; -+ -+struct au_vdir; -+struct au_fidir { -+ aufs_bindex_t fd_bbot; -+ aufs_bindex_t fd_nent; -+ struct au_vdir *fd_vdir_cache; -+ struct au_hfile fd_hfile[]; -+}; -+ -+static inline int au_fidir_sz(int nent) -+{ -+ AuDebugOn(nent < 0); -+ return sizeof(struct au_fidir) + sizeof(struct au_hfile) * nent; -+} -+ -+struct au_finfo { -+ atomic_t fi_generation; -+ -+ struct au_rwsem fi_rwsem; -+ aufs_bindex_t fi_btop; -+ -+ /* do not union them */ -+ struct { /* for non-dir */ -+ struct au_hfile fi_htop; -+ atomic_t fi_mmapped; -+ }; -+ struct au_fidir *fi_hdir; /* for dir only */ -+ -+ struct hlist_bl_node fi_hlist; -+ struct file *fi_file; /* very ugly */ -+ struct rcu_head rcu; -+} ____cacheline_aligned_in_smp; -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* file.c */ -+extern const struct address_space_operations aufs_aop; -+unsigned int au_file_roflags(unsigned int flags); -+struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags, -+ struct file *file, int force_wr); -+struct au_do_open_args { -+ int aopen; -+ int (*open)(struct file *file, int flags, -+ struct file *h_file); -+ struct au_fidir *fidir; -+ struct file *h_file; -+}; -+int au_do_open(struct file *file, struct au_do_open_args *args); -+int au_reopen_nondir(struct file *file); -+struct au_pin; -+int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin); -+int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file), -+ int wlock, unsigned int fi_lsc); -+int au_do_flush(struct file *file, fl_owner_t id, -+ int (*flush)(struct file *file, fl_owner_t id)); -+ -+/* poll.c */ -+#ifdef CONFIG_AUFS_POLL -+__poll_t aufs_poll(struct file *file, struct poll_table_struct *pt); -+#endif -+ -+#ifdef CONFIG_AUFS_BR_HFSPLUS -+/* hfsplus.c */ -+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex, -+ int force_wr); -+void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex, -+ struct file *h_file); -+#else -+AuStub(struct file *, au_h_open_pre, return NULL, struct dentry *dentry, -+ aufs_bindex_t bindex, int force_wr) -+AuStubVoid(au_h_open_post, struct dentry *dentry, aufs_bindex_t bindex, -+ struct file *h_file); -+#endif -+ -+/* f_op.c */ -+extern const struct file_operations aufs_file_fop; -+int au_do_open_nondir(struct file *file, int flags, struct file *h_file); -+int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file); -+struct file *au_read_pre(struct file *file, int keep_fi, unsigned int lsc); -+ -+/* finfo.c */ -+void au_hfput(struct au_hfile *hf, int execed); -+void au_set_h_fptr(struct file *file, aufs_bindex_t bindex, -+ struct file *h_file); -+ -+void au_update_figen(struct file *file); -+struct au_fidir *au_fidir_alloc(struct super_block *sb); -+int au_fidir_realloc(struct au_finfo *finfo, int nbr, int may_shrink); -+ -+void au_fi_init_once(void *_fi); -+void au_finfo_fin(struct file *file); -+int au_finfo_init(struct file *file, struct au_fidir *fidir); -+ -+/* ioctl.c */ -+long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg); -+#ifdef CONFIG_COMPAT -+long aufs_compat_ioctl_dir(struct file *file, unsigned int cmd, -+ unsigned long arg); -+long aufs_compat_ioctl_nondir(struct file *file, unsigned int cmd, -+ unsigned long arg); -+#endif -+ -+/* ---------------------------------------------------------------------- */ -+ -+static inline struct au_finfo *au_fi(struct file *file) -+{ -+ return file->private_data; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+#define fi_read_lock(f) au_rw_read_lock(&au_fi(f)->fi_rwsem) -+#define fi_write_lock(f) au_rw_write_lock(&au_fi(f)->fi_rwsem) -+#define fi_read_trylock(f) au_rw_read_trylock(&au_fi(f)->fi_rwsem) -+#define fi_write_trylock(f) au_rw_write_trylock(&au_fi(f)->fi_rwsem) -+/* -+#define fi_read_trylock_nested(f) \ -+ au_rw_read_trylock_nested(&au_fi(f)->fi_rwsem) -+#define fi_write_trylock_nested(f) \ -+ au_rw_write_trylock_nested(&au_fi(f)->fi_rwsem) -+*/ -+ -+#define fi_read_unlock(f) au_rw_read_unlock(&au_fi(f)->fi_rwsem) -+#define fi_write_unlock(f) au_rw_write_unlock(&au_fi(f)->fi_rwsem) -+#define fi_downgrade_lock(f) au_rw_dgrade_lock(&au_fi(f)->fi_rwsem) -+ -+/* lock subclass for finfo */ -+enum { -+ AuLsc_FI_1, -+ AuLsc_FI_2 -+}; -+ -+static inline void fi_read_lock_nested(struct file *f, unsigned int lsc) -+{ -+ au_rw_read_lock_nested(&au_fi(f)->fi_rwsem, lsc); -+} -+ -+static inline void fi_write_lock_nested(struct file *f, unsigned int lsc) -+{ -+ au_rw_write_lock_nested(&au_fi(f)->fi_rwsem, lsc); -+} -+ -+/* -+ * fi_read_lock_1, fi_write_lock_1, -+ * fi_read_lock_2, fi_write_lock_2 -+ */ -+#define AuReadLockFunc(name) \ -+static inline void fi_read_lock_##name(struct file *f) \ -+{ fi_read_lock_nested(f, AuLsc_FI_##name); } -+ -+#define AuWriteLockFunc(name) \ -+static inline void fi_write_lock_##name(struct file *f) \ -+{ fi_write_lock_nested(f, AuLsc_FI_##name); } -+ -+#define AuRWLockFuncs(name) \ -+ AuReadLockFunc(name) \ -+ AuWriteLockFunc(name) -+ -+AuRWLockFuncs(1); -+AuRWLockFuncs(2); -+ -+#undef AuReadLockFunc -+#undef AuWriteLockFunc -+#undef AuRWLockFuncs -+ -+#define FiMustNoWaiters(f) AuRwMustNoWaiters(&au_fi(f)->fi_rwsem) -+#define FiMustAnyLock(f) AuRwMustAnyLock(&au_fi(f)->fi_rwsem) -+#define FiMustWriteLock(f) AuRwMustWriteLock(&au_fi(f)->fi_rwsem) -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* todo: hard/soft set? */ -+static inline aufs_bindex_t au_fbtop(struct file *file) -+{ -+ FiMustAnyLock(file); -+ return au_fi(file)->fi_btop; -+} -+ -+static inline aufs_bindex_t au_fbbot_dir(struct file *file) -+{ -+ FiMustAnyLock(file); -+ AuDebugOn(!au_fi(file)->fi_hdir); -+ return au_fi(file)->fi_hdir->fd_bbot; -+} -+ -+static inline struct au_vdir *au_fvdir_cache(struct file *file) -+{ -+ FiMustAnyLock(file); -+ AuDebugOn(!au_fi(file)->fi_hdir); -+ return au_fi(file)->fi_hdir->fd_vdir_cache; -+} -+ -+static inline void au_set_fbtop(struct file *file, aufs_bindex_t bindex) -+{ -+ FiMustWriteLock(file); -+ au_fi(file)->fi_btop = bindex; -+} -+ -+static inline void au_set_fbbot_dir(struct file *file, aufs_bindex_t bindex) -+{ -+ FiMustWriteLock(file); -+ AuDebugOn(!au_fi(file)->fi_hdir); -+ au_fi(file)->fi_hdir->fd_bbot = bindex; -+} -+ -+static inline void au_set_fvdir_cache(struct file *file, -+ struct au_vdir *vdir_cache) -+{ -+ FiMustWriteLock(file); -+ AuDebugOn(!au_fi(file)->fi_hdir); -+ au_fi(file)->fi_hdir->fd_vdir_cache = vdir_cache; -+} -+ -+static inline struct file *au_hf_top(struct file *file) -+{ -+ FiMustAnyLock(file); -+ AuDebugOn(au_fi(file)->fi_hdir); -+ return au_fi(file)->fi_htop.hf_file; -+} -+ -+static inline struct file *au_hf_dir(struct file *file, aufs_bindex_t bindex) -+{ -+ FiMustAnyLock(file); -+ AuDebugOn(!au_fi(file)->fi_hdir); -+ return au_fi(file)->fi_hdir->fd_hfile[0 + bindex].hf_file; -+} -+ -+/* todo: memory barrier? */ -+static inline unsigned int au_figen(struct file *f) -+{ -+ return atomic_read(&au_fi(f)->fi_generation); -+} -+ -+static inline void au_set_mmapped(struct file *f) -+{ -+ if (atomic_inc_return(&au_fi(f)->fi_mmapped)) -+ return; -+ pr_warn("fi_mmapped wrapped around\n"); -+ while (!atomic_inc_return(&au_fi(f)->fi_mmapped)) -+ ; -+} -+ -+static inline void au_unset_mmapped(struct file *f) -+{ -+ atomic_dec(&au_fi(f)->fi_mmapped); -+} -+ -+static inline int au_test_mmapped(struct file *f) -+{ -+ return atomic_read(&au_fi(f)->fi_mmapped); -+} -+ -+/* customize vma->vm_file */ -+ -+static inline void au_do_vm_file_reset(struct vm_area_struct *vma, -+ struct file *file) -+{ -+ struct file *f; -+ -+ f = vma->vm_file; -+ get_file(file); -+ vma->vm_file = file; -+ fput(f); -+} -+ -+#ifdef CONFIG_MMU -+#define AuDbgVmRegion(file, vma) do {} while (0) -+ -+static inline void au_vm_file_reset(struct vm_area_struct *vma, -+ struct file *file) -+{ -+ au_do_vm_file_reset(vma, file); -+} -+#else -+#define AuDbgVmRegion(file, vma) \ -+ AuDebugOn((vma)->vm_region && (vma)->vm_region->vm_file != (file)) -+ -+static inline void au_vm_file_reset(struct vm_area_struct *vma, -+ struct file *file) -+{ -+ struct file *f; -+ -+ au_do_vm_file_reset(vma, file); -+ f = vma->vm_region->vm_file; -+ get_file(file); -+ vma->vm_region->vm_file = file; -+ fput(f); -+} -+#endif /* CONFIG_MMU */ -+ -+/* handle vma->vm_prfile */ -+static inline void au_vm_prfile_set(struct vm_area_struct *vma, -+ struct file *file) -+{ -+ get_file(file); -+ vma->vm_prfile = file; -+#ifndef CONFIG_MMU -+ get_file(file); -+ vma->vm_region->vm_prfile = file; -+#endif -+} -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_FILE_H__ */ -diff --git a/fs/aufs/finfo.c b/fs/aufs/finfo.c -new file mode 100644 -index 000000000000..e2d6859850b6 ---- /dev/null -+++ b/fs/aufs/finfo.c -@@ -0,0 +1,136 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * file private data -+ */ -+ -+#include "aufs.h" -+ -+void au_hfput(struct au_hfile *hf, int execed) -+{ -+ if (execed) -+ allow_write_access(hf->hf_file); -+ fput(hf->hf_file); -+ hf->hf_file = NULL; -+ au_lcnt_dec(&hf->hf_br->br_nfiles); -+ hf->hf_br = NULL; -+} -+ -+void au_set_h_fptr(struct file *file, aufs_bindex_t bindex, struct file *val) -+{ -+ struct au_finfo *finfo = au_fi(file); -+ struct au_hfile *hf; -+ struct au_fidir *fidir; -+ -+ fidir = finfo->fi_hdir; -+ if (!fidir) { -+ AuDebugOn(finfo->fi_btop != bindex); -+ hf = &finfo->fi_htop; -+ } else -+ hf = fidir->fd_hfile + bindex; -+ -+ if (hf && hf->hf_file) -+ au_hfput(hf, vfsub_file_execed(file)); -+ if (val) { -+ FiMustWriteLock(file); -+ AuDebugOn(IS_ERR_OR_NULL(file->f_path.dentry)); -+ hf->hf_file = val; -+ hf->hf_br = au_sbr(file->f_path.dentry->d_sb, bindex); -+ } -+} -+ -+void au_update_figen(struct file *file) -+{ -+ atomic_set(&au_fi(file)->fi_generation, au_digen(file->f_path.dentry)); -+ /* smp_mb(); */ /* atomic_set */ -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct au_fidir *au_fidir_alloc(struct super_block *sb) -+{ -+ struct au_fidir *fidir; -+ int nbr; -+ -+ nbr = au_sbbot(sb) + 1; -+ if (nbr < 2) -+ nbr = 2; /* initial allocate for 2 branches */ -+ fidir = kzalloc(au_fidir_sz(nbr), GFP_NOFS); -+ if (fidir) { -+ fidir->fd_bbot = -1; -+ fidir->fd_nent = nbr; -+ } -+ -+ return fidir; -+} -+ -+int au_fidir_realloc(struct au_finfo *finfo, int nbr, int may_shrink) -+{ -+ int err; -+ struct au_fidir *fidir, *p; -+ -+ AuRwMustWriteLock(&finfo->fi_rwsem); -+ fidir = finfo->fi_hdir; -+ AuDebugOn(!fidir); -+ -+ err = -ENOMEM; -+ p = au_kzrealloc(fidir, au_fidir_sz(fidir->fd_nent), au_fidir_sz(nbr), -+ GFP_NOFS, may_shrink); -+ if (p) { -+ p->fd_nent = nbr; -+ finfo->fi_hdir = p; -+ err = 0; -+ } -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+void au_finfo_fin(struct file *file) -+{ -+ struct au_finfo *finfo; -+ -+ au_lcnt_dec(&au_sbi(file->f_path.dentry->d_sb)->si_nfiles); -+ -+ finfo = au_fi(file); -+ AuDebugOn(finfo->fi_hdir); -+ AuRwDestroy(&finfo->fi_rwsem); -+ au_cache_free_finfo(finfo); -+} -+ -+void au_fi_init_once(void *_finfo) -+{ -+ struct au_finfo *finfo = _finfo; -+ -+ au_rw_init(&finfo->fi_rwsem); -+} -+ -+int au_finfo_init(struct file *file, struct au_fidir *fidir) -+{ -+ int err; -+ struct au_finfo *finfo; -+ struct dentry *dentry; -+ -+ err = -ENOMEM; -+ dentry = file->f_path.dentry; -+ finfo = au_cache_alloc_finfo(); -+ if (unlikely(!finfo)) -+ goto out; -+ -+ err = 0; -+ au_lcnt_inc(&au_sbi(dentry->d_sb)->si_nfiles); -+ au_rw_write_lock(&finfo->fi_rwsem); -+ finfo->fi_btop = -1; -+ finfo->fi_hdir = fidir; -+ atomic_set(&finfo->fi_generation, au_digen(dentry)); -+ /* smp_mb(); */ /* atomic_set */ -+ -+ file->private_data = finfo; -+ -+out: -+ return err; -+} -diff --git a/fs/aufs/fstype.h b/fs/aufs/fstype.h -new file mode 100644 -index 000000000000..7c001dae1859 ---- /dev/null -+++ b/fs/aufs/fstype.h -@@ -0,0 +1,388 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * judging filesystem type -+ */ -+ -+#ifndef __AUFS_FSTYPE_H__ -+#define __AUFS_FSTYPE_H__ -+ -+#ifdef __KERNEL__ -+ -+#include -+#include -+#include -+#include -+ -+static inline int au_test_aufs(struct super_block *sb) -+{ -+ return sb->s_magic == AUFS_SUPER_MAGIC; -+} -+ -+static inline const char *au_sbtype(struct super_block *sb) -+{ -+ return sb->s_type->name; -+} -+ -+static inline int au_test_iso9660(struct super_block *sb __maybe_unused) -+{ -+#if IS_ENABLED(CONFIG_ISO9660_FS) -+ return sb->s_magic == ISOFS_SUPER_MAGIC; -+#else -+ return 0; -+#endif -+} -+ -+static inline int au_test_romfs(struct super_block *sb __maybe_unused) -+{ -+#if IS_ENABLED(CONFIG_ROMFS_FS) -+ return sb->s_magic == ROMFS_MAGIC; -+#else -+ return 0; -+#endif -+} -+ -+static inline int au_test_cramfs(struct super_block *sb __maybe_unused) -+{ -+#if IS_ENABLED(CONFIG_CRAMFS) -+ return sb->s_magic == CRAMFS_MAGIC; -+#endif -+ return 0; -+} -+ -+static inline int au_test_nfs(struct super_block *sb __maybe_unused) -+{ -+#if IS_ENABLED(CONFIG_NFS_FS) -+ return sb->s_magic == NFS_SUPER_MAGIC; -+#else -+ return 0; -+#endif -+} -+ -+static inline int au_test_fuse(struct super_block *sb __maybe_unused) -+{ -+#if IS_ENABLED(CONFIG_FUSE_FS) -+ return sb->s_magic == FUSE_SUPER_MAGIC; -+#else -+ return 0; -+#endif -+} -+ -+static inline int au_test_xfs(struct super_block *sb __maybe_unused) -+{ -+#if IS_ENABLED(CONFIG_XFS_FS) -+ return sb->s_magic == XFS_SB_MAGIC; -+#else -+ return 0; -+#endif -+} -+ -+static inline int au_test_tmpfs(struct super_block *sb __maybe_unused) -+{ -+#ifdef CONFIG_TMPFS -+ return sb->s_magic == TMPFS_MAGIC; -+#else -+ return 0; -+#endif -+} -+ -+static inline int au_test_ecryptfs(struct super_block *sb __maybe_unused) -+{ -+#if IS_ENABLED(CONFIG_ECRYPT_FS) -+ return !strcmp(au_sbtype(sb), "ecryptfs"); -+#else -+ return 0; -+#endif -+} -+ -+static inline int au_test_ramfs(struct super_block *sb) -+{ -+ return sb->s_magic == RAMFS_MAGIC; -+} -+ -+static inline int au_test_ubifs(struct super_block *sb __maybe_unused) -+{ -+#if IS_ENABLED(CONFIG_UBIFS_FS) -+ return sb->s_magic == UBIFS_SUPER_MAGIC; -+#else -+ return 0; -+#endif -+} -+ -+static inline int au_test_procfs(struct super_block *sb __maybe_unused) -+{ -+#ifdef CONFIG_PROC_FS -+ return sb->s_magic == PROC_SUPER_MAGIC; -+#else -+ return 0; -+#endif -+} -+ -+static inline int au_test_sysfs(struct super_block *sb __maybe_unused) -+{ -+#ifdef CONFIG_SYSFS -+ return sb->s_magic == SYSFS_MAGIC; -+#else -+ return 0; -+#endif -+} -+ -+static inline int au_test_configfs(struct super_block *sb __maybe_unused) -+{ -+#if IS_ENABLED(CONFIG_CONFIGFS_FS) -+ return sb->s_magic == CONFIGFS_MAGIC; -+#else -+ return 0; -+#endif -+} -+ -+static inline int au_test_minix(struct super_block *sb __maybe_unused) -+{ -+#if IS_ENABLED(CONFIG_MINIX_FS) -+ return sb->s_magic == MINIX3_SUPER_MAGIC -+ || sb->s_magic == MINIX2_SUPER_MAGIC -+ || sb->s_magic == MINIX2_SUPER_MAGIC2 -+ || sb->s_magic == MINIX_SUPER_MAGIC -+ || sb->s_magic == MINIX_SUPER_MAGIC2; -+#else -+ return 0; -+#endif -+} -+ -+static inline int au_test_fat(struct super_block *sb __maybe_unused) -+{ -+#if IS_ENABLED(CONFIG_FAT_FS) -+ return sb->s_magic == MSDOS_SUPER_MAGIC; -+#else -+ return 0; -+#endif -+} -+ -+static inline int au_test_msdos(struct super_block *sb) -+{ -+ return au_test_fat(sb); -+} -+ -+static inline int au_test_vfat(struct super_block *sb) -+{ -+ return au_test_fat(sb); -+} -+ -+static inline int au_test_securityfs(struct super_block *sb __maybe_unused) -+{ -+#ifdef CONFIG_SECURITYFS -+ return sb->s_magic == SECURITYFS_MAGIC; -+#else -+ return 0; -+#endif -+} -+ -+static inline int au_test_squashfs(struct super_block *sb __maybe_unused) -+{ -+#if IS_ENABLED(CONFIG_SQUASHFS) -+ return sb->s_magic == SQUASHFS_MAGIC; -+#else -+ return 0; -+#endif -+} -+ -+static inline int au_test_btrfs(struct super_block *sb __maybe_unused) -+{ -+#if IS_ENABLED(CONFIG_BTRFS_FS) -+ return sb->s_magic == BTRFS_SUPER_MAGIC; -+#else -+ return 0; -+#endif -+} -+ -+static inline int au_test_xenfs(struct super_block *sb __maybe_unused) -+{ -+#if IS_ENABLED(CONFIG_XENFS) -+ return sb->s_magic == XENFS_SUPER_MAGIC; -+#else -+ return 0; -+#endif -+} -+ -+static inline int au_test_debugfs(struct super_block *sb __maybe_unused) -+{ -+#ifdef CONFIG_DEBUG_FS -+ return sb->s_magic == DEBUGFS_MAGIC; -+#else -+ return 0; -+#endif -+} -+ -+static inline int au_test_nilfs(struct super_block *sb __maybe_unused) -+{ -+#if IS_ENABLED(CONFIG_NILFS) -+ return sb->s_magic == NILFS_SUPER_MAGIC; -+#else -+ return 0; -+#endif -+} -+ -+static inline int au_test_hfsplus(struct super_block *sb __maybe_unused) -+{ -+#if IS_ENABLED(CONFIG_HFSPLUS_FS) -+ return sb->s_magic == HFSPLUS_SUPER_MAGIC; -+#else -+ return 0; -+#endif -+} -+ -+/* ---------------------------------------------------------------------- */ -+/* -+ * they can't be an aufs branch. -+ */ -+static inline int au_test_fs_unsuppoted(struct super_block *sb) -+{ -+ return -+#ifndef CONFIG_AUFS_BR_RAMFS -+ au_test_ramfs(sb) || -+#endif -+ au_test_procfs(sb) -+ || au_test_sysfs(sb) -+ || au_test_configfs(sb) -+ || au_test_debugfs(sb) -+ || au_test_securityfs(sb) -+ || au_test_xenfs(sb) -+ || au_test_ecryptfs(sb) -+ /* || !strcmp(au_sbtype(sb), "unionfs") */ -+ || au_test_aufs(sb); /* will be supported in next version */ -+} -+ -+static inline int au_test_fs_remote(struct super_block *sb) -+{ -+ return !au_test_tmpfs(sb) -+#ifdef CONFIG_AUFS_BR_RAMFS -+ && !au_test_ramfs(sb) -+#endif -+ && !(sb->s_type->fs_flags & FS_REQUIRES_DEV); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * Note: these functions (below) are created after reading ->getattr() in all -+ * filesystems under linux/fs. it means we have to do so in every update... -+ */ -+ -+/* -+ * some filesystems require getattr to refresh the inode attributes before -+ * referencing. -+ * in most cases, we can rely on the inode attribute in NFS (or every remote fs) -+ * and leave the work for d_revalidate() -+ */ -+static inline int au_test_fs_refresh_iattr(struct super_block *sb) -+{ -+ return au_test_nfs(sb) -+ || au_test_fuse(sb) -+ /* || au_test_btrfs(sb) */ /* untested */ -+ ; -+} -+ -+/* -+ * filesystems which don't maintain i_size or i_blocks. -+ */ -+static inline int au_test_fs_bad_iattr_size(struct super_block *sb) -+{ -+ return au_test_xfs(sb) -+ || au_test_btrfs(sb) -+ || au_test_ubifs(sb) -+ || au_test_hfsplus(sb) /* maintained, but incorrect */ -+ /* || au_test_minix(sb) */ /* untested */ -+ ; -+} -+ -+/* -+ * filesystems which don't store the correct value in some of their inode -+ * attributes. -+ */ -+static inline int au_test_fs_bad_iattr(struct super_block *sb) -+{ -+ return au_test_fs_bad_iattr_size(sb) -+ || au_test_fat(sb) -+ || au_test_msdos(sb) -+ || au_test_vfat(sb); -+} -+ -+/* they don't check i_nlink in link(2) */ -+static inline int au_test_fs_no_limit_nlink(struct super_block *sb) -+{ -+ return au_test_tmpfs(sb) -+#ifdef CONFIG_AUFS_BR_RAMFS -+ || au_test_ramfs(sb) -+#endif -+ || au_test_ubifs(sb) -+ || au_test_hfsplus(sb); -+} -+ -+/* -+ * filesystems which sets S_NOATIME and S_NOCMTIME. -+ */ -+static inline int au_test_fs_notime(struct super_block *sb) -+{ -+ return au_test_nfs(sb) -+ || au_test_fuse(sb) -+ || au_test_ubifs(sb) -+ ; -+} -+ -+/* temporary support for i#1 in cramfs */ -+static inline int au_test_fs_unique_ino(struct inode *inode) -+{ -+ if (au_test_cramfs(inode->i_sb)) -+ return inode->i_ino != 1; -+ return 1; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * the filesystem where the xino files placed must support i/o after unlink and -+ * maintain i_size and i_blocks. -+ */ -+static inline int au_test_fs_bad_xino(struct super_block *sb) -+{ -+ return au_test_fs_remote(sb) -+ || au_test_fs_bad_iattr_size(sb) -+ /* don't want unnecessary work for xino */ -+ || au_test_aufs(sb) -+ || au_test_ecryptfs(sb) -+ || au_test_nilfs(sb); -+} -+ -+static inline int au_test_fs_trunc_xino(struct super_block *sb) -+{ -+ return au_test_tmpfs(sb) -+ || au_test_ramfs(sb); -+} -+ -+/* -+ * test if the @sb is real-readonly. -+ */ -+static inline int au_test_fs_rr(struct super_block *sb) -+{ -+ return au_test_squashfs(sb) -+ || au_test_iso9660(sb) -+ || au_test_cramfs(sb) -+ || au_test_romfs(sb); -+} -+ -+/* -+ * test if the @inode is nfs with 'noacl' option -+ * NFS always sets SB_POSIXACL regardless its mount option 'noacl.' -+ */ -+static inline int au_test_nfs_noacl(struct inode *inode) -+{ -+ return au_test_nfs(inode->i_sb) -+ /* && IS_POSIXACL(inode) */ -+ && !nfs_server_capable(inode, NFS_CAP_ACLS); -+} -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_FSTYPE_H__ */ -diff --git a/fs/aufs/hbl.h b/fs/aufs/hbl.h -new file mode 100644 -index 000000000000..571efb1e2300 ---- /dev/null -+++ b/fs/aufs/hbl.h -@@ -0,0 +1,52 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2017-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * helpers for hlist_bl.h -+ */ -+ -+#ifndef __AUFS_HBL_H__ -+#define __AUFS_HBL_H__ -+ -+#ifdef __KERNEL__ -+ -+#include -+ -+static inline void au_hbl_add(struct hlist_bl_node *node, -+ struct hlist_bl_head *hbl) -+{ -+ hlist_bl_lock(hbl); -+ hlist_bl_add_head(node, hbl); -+ hlist_bl_unlock(hbl); -+} -+ -+static inline void au_hbl_del(struct hlist_bl_node *node, -+ struct hlist_bl_head *hbl) -+{ -+ hlist_bl_lock(hbl); -+ hlist_bl_del(node); -+ hlist_bl_unlock(hbl); -+} -+ -+#define au_hbl_for_each(pos, head) \ -+ for (pos = hlist_bl_first(head); \ -+ pos; \ -+ pos = pos->next) -+ -+static inline unsigned long au_hbl_count(struct hlist_bl_head *hbl) -+{ -+ unsigned long cnt; -+ struct hlist_bl_node *pos; -+ -+ cnt = 0; -+ hlist_bl_lock(hbl); -+ au_hbl_for_each(pos, hbl) -+ cnt++; -+ hlist_bl_unlock(hbl); -+ return cnt; -+} -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_HBL_H__ */ -diff --git a/fs/aufs/hfsnotify.c b/fs/aufs/hfsnotify.c -new file mode 100644 -index 000000000000..65acdd7f5b69 ---- /dev/null -+++ b/fs/aufs/hfsnotify.c -@@ -0,0 +1,275 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * fsnotify for the lower directories -+ */ -+ -+#include "aufs.h" -+ -+/* FS_IN_IGNORED is unnecessary */ -+static const __u32 AuHfsnMask = (FS_MOVED_TO | FS_MOVED_FROM | FS_DELETE -+ | FS_CREATE | FS_EVENT_ON_CHILD); -+static DECLARE_WAIT_QUEUE_HEAD(au_hfsn_wq); -+static __cacheline_aligned_in_smp atomic64_t au_hfsn_ifree = ATOMIC64_INIT(0); -+ -+static void au_hfsn_free_mark(struct fsnotify_mark *mark) -+{ -+ struct au_hnotify *hn = container_of(mark, struct au_hnotify, -+ hn_mark); -+ /* AuDbg("here\n"); */ -+ au_cache_free_hnotify(hn); -+ smp_mb__before_atomic(); /* for atomic64_dec */ -+ if (atomic64_dec_and_test(&au_hfsn_ifree)) -+ wake_up(&au_hfsn_wq); -+} -+ -+static int au_hfsn_alloc(struct au_hinode *hinode) -+{ -+ int err; -+ struct au_hnotify *hn; -+ struct super_block *sb; -+ struct au_branch *br; -+ struct fsnotify_mark *mark; -+ aufs_bindex_t bindex; -+ -+ hn = hinode->hi_notify; -+ sb = hn->hn_aufs_inode->i_sb; -+ bindex = au_br_index(sb, hinode->hi_id); -+ br = au_sbr(sb, bindex); -+ AuDebugOn(!br->br_hfsn); -+ -+ mark = &hn->hn_mark; -+ fsnotify_init_mark(mark, br->br_hfsn->hfsn_group); -+ mark->mask = AuHfsnMask; -+ /* -+ * by udba rename or rmdir, aufs assign a new inode to the known -+ * h_inode, so specify 1 to allow dups. -+ */ -+ lockdep_off(); -+ err = fsnotify_add_inode_mark(mark, hinode->hi_inode, /*allow_dups*/1); -+ lockdep_on(); -+ -+ return err; -+} -+ -+static int au_hfsn_free(struct au_hinode *hinode, struct au_hnotify *hn) -+{ -+ struct fsnotify_mark *mark; -+ unsigned long long ull; -+ struct fsnotify_group *group; -+ -+ ull = atomic64_inc_return(&au_hfsn_ifree); -+ BUG_ON(!ull); -+ -+ mark = &hn->hn_mark; -+ spin_lock(&mark->lock); -+ group = mark->group; -+ fsnotify_get_group(group); -+ spin_unlock(&mark->lock); -+ lockdep_off(); -+ fsnotify_destroy_mark(mark, group); -+ fsnotify_put_mark(mark); -+ fsnotify_put_group(group); -+ lockdep_on(); -+ -+ /* free hn by myself */ -+ return 0; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static void au_hfsn_ctl(struct au_hinode *hinode, int do_set) -+{ -+ struct fsnotify_mark *mark; -+ -+ mark = &hinode->hi_notify->hn_mark; -+ spin_lock(&mark->lock); -+ if (do_set) { -+ AuDebugOn(mark->mask & AuHfsnMask); -+ mark->mask |= AuHfsnMask; -+ } else { -+ AuDebugOn(!(mark->mask & AuHfsnMask)); -+ mark->mask &= ~AuHfsnMask; -+ } -+ spin_unlock(&mark->lock); -+ /* fsnotify_recalc_inode_mask(hinode->hi_inode); */ -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* #define AuDbgHnotify */ -+#ifdef AuDbgHnotify -+static char *au_hfsn_name(u32 mask) -+{ -+#ifdef CONFIG_AUFS_DEBUG -+#define test_ret(flag) \ -+ do { \ -+ if (mask & flag) \ -+ return #flag; \ -+ } while (0) -+ test_ret(FS_ACCESS); -+ test_ret(FS_MODIFY); -+ test_ret(FS_ATTRIB); -+ test_ret(FS_CLOSE_WRITE); -+ test_ret(FS_CLOSE_NOWRITE); -+ test_ret(FS_OPEN); -+ test_ret(FS_MOVED_FROM); -+ test_ret(FS_MOVED_TO); -+ test_ret(FS_CREATE); -+ test_ret(FS_DELETE); -+ test_ret(FS_DELETE_SELF); -+ test_ret(FS_MOVE_SELF); -+ test_ret(FS_UNMOUNT); -+ test_ret(FS_Q_OVERFLOW); -+ test_ret(FS_IN_IGNORED); -+ test_ret(FS_ISDIR); -+ test_ret(FS_IN_ONESHOT); -+ test_ret(FS_EVENT_ON_CHILD); -+ return ""; -+#undef test_ret -+#else -+ return "??"; -+#endif -+} -+#endif -+ -+/* ---------------------------------------------------------------------- */ -+ -+static void au_hfsn_free_group(struct fsnotify_group *group) -+{ -+ struct au_br_hfsnotify *hfsn = group->private; -+ -+ /* AuDbg("here\n"); */ -+ au_kfree_try_rcu(hfsn); -+} -+ -+static int au_hfsn_handle_event(struct fsnotify_group *group, -+ struct inode *inode, -+ u32 mask, const void *data, int data_type, -+ const struct qstr *file_name, u32 cookie, -+ struct fsnotify_iter_info *iter_info) -+{ -+ int err; -+ struct au_hnotify *hnotify; -+ struct inode *h_dir, *h_inode; -+ struct fsnotify_mark *inode_mark; -+ -+ AuDebugOn(data_type != FSNOTIFY_EVENT_INODE); -+ -+ err = 0; -+ /* if FS_UNMOUNT happens, there must be another bug */ -+ AuDebugOn(mask & FS_UNMOUNT); -+ if (mask & (FS_IN_IGNORED | FS_UNMOUNT)) -+ goto out; -+ -+ h_dir = inode; -+ h_inode = NULL; -+#ifdef AuDbgHnotify -+ au_debug_on(); -+ if (1 || h_child_qstr.len != sizeof(AUFS_XINO_FNAME) - 1 -+ || strncmp(h_child_qstr.name, AUFS_XINO_FNAME, h_child_qstr.len)) { -+ AuDbg("i%lu, mask 0x%x %s, hcname %.*s, hi%lu\n", -+ h_dir->i_ino, mask, au_hfsn_name(mask), -+ AuLNPair(&h_child_qstr), h_inode ? h_inode->i_ino : 0); -+ /* WARN_ON(1); */ -+ } -+ au_debug_off(); -+#endif -+ -+ inode_mark = fsnotify_iter_inode_mark(iter_info); -+ AuDebugOn(!inode_mark); -+ hnotify = container_of(inode_mark, struct au_hnotify, hn_mark); -+ err = au_hnotify(h_dir, hnotify, mask, file_name, h_inode); -+ -+out: -+ return err; -+} -+ -+static struct fsnotify_ops au_hfsn_ops = { -+ .handle_event = au_hfsn_handle_event, -+ .free_group_priv = au_hfsn_free_group, -+ .free_mark = au_hfsn_free_mark -+}; -+ -+/* ---------------------------------------------------------------------- */ -+ -+static void au_hfsn_fin_br(struct au_branch *br) -+{ -+ struct au_br_hfsnotify *hfsn; -+ -+ hfsn = br->br_hfsn; -+ if (hfsn) { -+ lockdep_off(); -+ fsnotify_put_group(hfsn->hfsn_group); -+ lockdep_on(); -+ } -+} -+ -+static int au_hfsn_init_br(struct au_branch *br, int perm) -+{ -+ int err; -+ struct fsnotify_group *group; -+ struct au_br_hfsnotify *hfsn; -+ -+ err = 0; -+ br->br_hfsn = NULL; -+ if (!au_br_hnotifyable(perm)) -+ goto out; -+ -+ err = -ENOMEM; -+ hfsn = kmalloc(sizeof(*hfsn), GFP_NOFS); -+ if (unlikely(!hfsn)) -+ goto out; -+ -+ err = 0; -+ group = fsnotify_alloc_group(&au_hfsn_ops); -+ if (IS_ERR(group)) { -+ err = PTR_ERR(group); -+ pr_err("fsnotify_alloc_group() failed, %d\n", err); -+ goto out_hfsn; -+ } -+ -+ group->private = hfsn; -+ hfsn->hfsn_group = group; -+ br->br_hfsn = hfsn; -+ goto out; /* success */ -+ -+out_hfsn: -+ au_kfree_try_rcu(hfsn); -+out: -+ return err; -+} -+ -+static int au_hfsn_reset_br(unsigned int udba, struct au_branch *br, int perm) -+{ -+ int err; -+ -+ err = 0; -+ if (!br->br_hfsn) -+ err = au_hfsn_init_br(br, perm); -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static void au_hfsn_fin(void) -+{ -+ AuDbg("au_hfsn_ifree %lld\n", (long long)atomic64_read(&au_hfsn_ifree)); -+ wait_event(au_hfsn_wq, !atomic64_read(&au_hfsn_ifree)); -+} -+ -+const struct au_hnotify_op au_hnotify_op = { -+ .ctl = au_hfsn_ctl, -+ .alloc = au_hfsn_alloc, -+ .free = au_hfsn_free, -+ -+ .fin = au_hfsn_fin, -+ -+ .reset_br = au_hfsn_reset_br, -+ .fin_br = au_hfsn_fin_br, -+ .init_br = au_hfsn_init_br -+}; -diff --git a/fs/aufs/hfsplus.c b/fs/aufs/hfsplus.c -new file mode 100644 -index 000000000000..3d4fed48bf16 ---- /dev/null -+++ b/fs/aufs/hfsplus.c -@@ -0,0 +1,47 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2010-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * special support for filesystems which acquires an inode mutex -+ * at final closing a file, eg, hfsplus. -+ * -+ * This trick is very simple and stupid, just to open the file before really -+ * necessary open to tell hfsplus that this is not the final closing. -+ * The caller should call au_h_open_pre() after acquiring the inode mutex, -+ * and au_h_open_post() after releasing it. -+ */ -+ -+#include "aufs.h" -+ -+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex, -+ int force_wr) -+{ -+ struct file *h_file; -+ struct dentry *h_dentry; -+ -+ h_dentry = au_h_dptr(dentry, bindex); -+ AuDebugOn(!h_dentry); -+ AuDebugOn(d_is_negative(h_dentry)); -+ -+ h_file = NULL; -+ if (au_test_hfsplus(h_dentry->d_sb) -+ && d_is_reg(h_dentry)) -+ h_file = au_h_open(dentry, bindex, -+ O_RDONLY | O_NOATIME | O_LARGEFILE, -+ /*file*/NULL, force_wr); -+ return h_file; -+} -+ -+void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex, -+ struct file *h_file) -+{ -+ struct au_branch *br; -+ -+ if (h_file) { -+ fput(h_file); -+ br = au_sbr(dentry->d_sb, bindex); -+ au_lcnt_dec(&br->br_nfiles); -+ } -+} -diff --git a/fs/aufs/hnotify.c b/fs/aufs/hnotify.c -new file mode 100644 -index 000000000000..e082f63ccaf9 ---- /dev/null -+++ b/fs/aufs/hnotify.c -@@ -0,0 +1,702 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * abstraction to notify the direct changes on lower directories -+ */ -+ -+/* #include */ -+#include "aufs.h" -+ -+int au_hn_alloc(struct au_hinode *hinode, struct inode *inode) -+{ -+ int err; -+ struct au_hnotify *hn; -+ -+ err = -ENOMEM; -+ hn = au_cache_alloc_hnotify(); -+ if (hn) { -+ hn->hn_aufs_inode = inode; -+ hinode->hi_notify = hn; -+ err = au_hnotify_op.alloc(hinode); -+ AuTraceErr(err); -+ if (unlikely(err)) { -+ hinode->hi_notify = NULL; -+ au_cache_free_hnotify(hn); -+ /* -+ * The upper dir was removed by udba, but the same named -+ * dir left. In this case, aufs assigns a new inode -+ * number and set the monitor again. -+ * For the lower dir, the old monitor is still left. -+ */ -+ if (err == -EEXIST) -+ err = 0; -+ } -+ } -+ -+ AuTraceErr(err); -+ return err; -+} -+ -+void au_hn_free(struct au_hinode *hinode) -+{ -+ struct au_hnotify *hn; -+ -+ hn = hinode->hi_notify; -+ if (hn) { -+ hinode->hi_notify = NULL; -+ if (au_hnotify_op.free(hinode, hn)) -+ au_cache_free_hnotify(hn); -+ } -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+void au_hn_ctl(struct au_hinode *hinode, int do_set) -+{ -+ if (hinode->hi_notify) -+ au_hnotify_op.ctl(hinode, do_set); -+} -+ -+void au_hn_reset(struct inode *inode, unsigned int flags) -+{ -+ aufs_bindex_t bindex, bbot; -+ struct inode *hi; -+ struct dentry *iwhdentry; -+ -+ bbot = au_ibbot(inode); -+ for (bindex = au_ibtop(inode); bindex <= bbot; bindex++) { -+ hi = au_h_iptr(inode, bindex); -+ if (!hi) -+ continue; -+ -+ /* inode_lock_nested(hi, AuLsc_I_CHILD); */ -+ iwhdentry = au_hi_wh(inode, bindex); -+ if (iwhdentry) -+ dget(iwhdentry); -+ au_igrab(hi); -+ au_set_h_iptr(inode, bindex, NULL, 0); -+ au_set_h_iptr(inode, bindex, au_igrab(hi), -+ flags & ~AuHi_XINO); -+ iput(hi); -+ dput(iwhdentry); -+ /* inode_unlock(hi); */ -+ } -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int hn_xino(struct inode *inode, struct inode *h_inode) -+{ -+ int err; -+ aufs_bindex_t bindex, bbot, bfound, btop; -+ struct inode *h_i; -+ -+ err = 0; -+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) { -+ pr_warn("branch root dir was changed\n"); -+ goto out; -+ } -+ -+ bfound = -1; -+ bbot = au_ibbot(inode); -+ btop = au_ibtop(inode); -+#if 0 /* reserved for future use */ -+ if (bindex == bbot) { -+ /* keep this ino in rename case */ -+ goto out; -+ } -+#endif -+ for (bindex = btop; bindex <= bbot; bindex++) -+ if (au_h_iptr(inode, bindex) == h_inode) { -+ bfound = bindex; -+ break; -+ } -+ if (bfound < 0) -+ goto out; -+ -+ for (bindex = btop; bindex <= bbot; bindex++) { -+ h_i = au_h_iptr(inode, bindex); -+ if (!h_i) -+ continue; -+ -+ err = au_xino_write(inode->i_sb, bindex, h_i->i_ino, /*ino*/0); -+ /* ignore this error */ -+ /* bad action? */ -+ } -+ -+ /* children inode number will be broken */ -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+static int hn_gen_tree(struct dentry *dentry) -+{ -+ int err, i, j, ndentry; -+ struct au_dcsub_pages dpages; -+ struct au_dpage *dpage; -+ struct dentry **dentries; -+ -+ err = au_dpages_init(&dpages, GFP_NOFS); -+ if (unlikely(err)) -+ goto out; -+ err = au_dcsub_pages(&dpages, dentry, NULL, NULL); -+ if (unlikely(err)) -+ goto out_dpages; -+ -+ for (i = 0; i < dpages.ndpage; i++) { -+ dpage = dpages.dpages + i; -+ dentries = dpage->dentries; -+ ndentry = dpage->ndentry; -+ for (j = 0; j < ndentry; j++) { -+ struct dentry *d; -+ -+ d = dentries[j]; -+ if (IS_ROOT(d)) -+ continue; -+ -+ au_digen_dec(d); -+ if (d_really_is_positive(d)) -+ /* todo: reset children xino? -+ cached children only? */ -+ au_iigen_dec(d_inode(d)); -+ } -+ } -+ -+out_dpages: -+ au_dpages_free(&dpages); -+out: -+ return err; -+} -+ -+/* -+ * return 0 if processed. -+ */ -+static int hn_gen_by_inode(char *name, unsigned int nlen, struct inode *inode, -+ const unsigned int isdir) -+{ -+ int err; -+ struct dentry *d; -+ struct qstr *dname; -+ -+ err = 1; -+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) { -+ pr_warn("branch root dir was changed\n"); -+ err = 0; -+ goto out; -+ } -+ -+ if (!isdir) { -+ AuDebugOn(!name); -+ au_iigen_dec(inode); -+ spin_lock(&inode->i_lock); -+ hlist_for_each_entry(d, &inode->i_dentry, d_u.d_alias) { -+ spin_lock(&d->d_lock); -+ dname = &d->d_name; -+ if (dname->len != nlen -+ && memcmp(dname->name, name, nlen)) { -+ spin_unlock(&d->d_lock); -+ continue; -+ } -+ err = 0; -+ au_digen_dec(d); -+ spin_unlock(&d->d_lock); -+ break; -+ } -+ spin_unlock(&inode->i_lock); -+ } else { -+ au_fset_si(au_sbi(inode->i_sb), FAILED_REFRESH_DIR); -+ d = d_find_any_alias(inode); -+ if (!d) { -+ au_iigen_dec(inode); -+ goto out; -+ } -+ -+ spin_lock(&d->d_lock); -+ dname = &d->d_name; -+ if (dname->len == nlen && !memcmp(dname->name, name, nlen)) { -+ spin_unlock(&d->d_lock); -+ err = hn_gen_tree(d); -+ spin_lock(&d->d_lock); -+ } -+ spin_unlock(&d->d_lock); -+ dput(d); -+ } -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+static int hn_gen_by_name(struct dentry *dentry, const unsigned int isdir) -+{ -+ int err; -+ -+ if (IS_ROOT(dentry)) { -+ pr_warn("branch root dir was changed\n"); -+ return 0; -+ } -+ -+ err = 0; -+ if (!isdir) { -+ au_digen_dec(dentry); -+ if (d_really_is_positive(dentry)) -+ au_iigen_dec(d_inode(dentry)); -+ } else { -+ au_fset_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIR); -+ if (d_really_is_positive(dentry)) -+ err = hn_gen_tree(dentry); -+ } -+ -+ AuTraceErr(err); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* hnotify job flags */ -+#define AuHnJob_XINO0 1 -+#define AuHnJob_GEN (1 << 1) -+#define AuHnJob_DIRENT (1 << 2) -+#define AuHnJob_ISDIR (1 << 3) -+#define AuHnJob_TRYXINO0 (1 << 4) -+#define AuHnJob_MNTPNT (1 << 5) -+#define au_ftest_hnjob(flags, name) ((flags) & AuHnJob_##name) -+#define au_fset_hnjob(flags, name) \ -+ do { (flags) |= AuHnJob_##name; } while (0) -+#define au_fclr_hnjob(flags, name) \ -+ do { (flags) &= ~AuHnJob_##name; } while (0) -+ -+enum { -+ AuHn_CHILD, -+ AuHn_PARENT, -+ AuHnLast -+}; -+ -+struct au_hnotify_args { -+ struct inode *h_dir, *dir, *h_child_inode; -+ u32 mask; -+ unsigned int flags[AuHnLast]; -+ unsigned int h_child_nlen; -+ char h_child_name[]; -+}; -+ -+struct hn_job_args { -+ unsigned int flags; -+ struct inode *inode, *h_inode, *dir, *h_dir; -+ struct dentry *dentry; -+ char *h_name; -+ int h_nlen; -+}; -+ -+static int hn_job(struct hn_job_args *a) -+{ -+ const unsigned int isdir = au_ftest_hnjob(a->flags, ISDIR); -+ int e; -+ -+ /* reset xino */ -+ if (au_ftest_hnjob(a->flags, XINO0) && a->inode) -+ hn_xino(a->inode, a->h_inode); /* ignore this error */ -+ -+ if (au_ftest_hnjob(a->flags, TRYXINO0) -+ && a->inode -+ && a->h_inode) { -+ inode_lock_shared_nested(a->h_inode, AuLsc_I_CHILD); -+ if (!a->h_inode->i_nlink -+ && !(a->h_inode->i_state & I_LINKABLE)) -+ hn_xino(a->inode, a->h_inode); /* ignore this error */ -+ inode_unlock_shared(a->h_inode); -+ } -+ -+ /* make the generation obsolete */ -+ if (au_ftest_hnjob(a->flags, GEN)) { -+ e = -1; -+ if (a->inode) -+ e = hn_gen_by_inode(a->h_name, a->h_nlen, a->inode, -+ isdir); -+ if (e && a->dentry) -+ hn_gen_by_name(a->dentry, isdir); -+ /* ignore this error */ -+ } -+ -+ /* make dir entries obsolete */ -+ if (au_ftest_hnjob(a->flags, DIRENT) && a->inode) { -+ struct au_vdir *vdir; -+ -+ vdir = au_ivdir(a->inode); -+ if (vdir) -+ vdir->vd_jiffy = 0; -+ /* IMustLock(a->inode); */ -+ /* inode_inc_iversion(a->inode); */ -+ } -+ -+ /* can do nothing but warn */ -+ if (au_ftest_hnjob(a->flags, MNTPNT) -+ && a->dentry -+ && d_mountpoint(a->dentry)) -+ pr_warn("mount-point %pd is removed or renamed\n", a->dentry); -+ -+ return 0; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static struct dentry *lookup_wlock_by_name(char *name, unsigned int nlen, -+ struct inode *dir) -+{ -+ struct dentry *dentry, *d, *parent; -+ struct qstr *dname; -+ -+ parent = d_find_any_alias(dir); -+ if (!parent) -+ return NULL; -+ -+ dentry = NULL; -+ spin_lock(&parent->d_lock); -+ list_for_each_entry(d, &parent->d_subdirs, d_child) { -+ /* AuDbg("%pd\n", d); */ -+ spin_lock_nested(&d->d_lock, DENTRY_D_LOCK_NESTED); -+ dname = &d->d_name; -+ if (dname->len != nlen || memcmp(dname->name, name, nlen)) -+ goto cont_unlock; -+ if (au_di(d)) -+ au_digen_dec(d); -+ else -+ goto cont_unlock; -+ if (au_dcount(d) > 0) { -+ dentry = dget_dlock(d); -+ spin_unlock(&d->d_lock); -+ break; -+ } -+ -+cont_unlock: -+ spin_unlock(&d->d_lock); -+ } -+ spin_unlock(&parent->d_lock); -+ dput(parent); -+ -+ if (dentry) -+ di_write_lock_child(dentry); -+ -+ return dentry; -+} -+ -+static struct inode *lookup_wlock_by_ino(struct super_block *sb, -+ aufs_bindex_t bindex, ino_t h_ino) -+{ -+ struct inode *inode; -+ ino_t ino; -+ int err; -+ -+ inode = NULL; -+ err = au_xino_read(sb, bindex, h_ino, &ino); -+ if (!err && ino) -+ inode = ilookup(sb, ino); -+ if (!inode) -+ goto out; -+ -+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) { -+ pr_warn("wrong root branch\n"); -+ iput(inode); -+ inode = NULL; -+ goto out; -+ } -+ -+ ii_write_lock_child(inode); -+ -+out: -+ return inode; -+} -+ -+static void au_hn_bh(void *_args) -+{ -+ struct au_hnotify_args *a = _args; -+ struct super_block *sb; -+ aufs_bindex_t bindex, bbot, bfound; -+ unsigned char xino, try_iput; -+ int err; -+ struct inode *inode; -+ ino_t h_ino; -+ struct hn_job_args args; -+ struct dentry *dentry; -+ struct au_sbinfo *sbinfo; -+ -+ AuDebugOn(!_args); -+ AuDebugOn(!a->h_dir); -+ AuDebugOn(!a->dir); -+ AuDebugOn(!a->mask); -+ AuDbg("mask 0x%x, i%lu, hi%lu, hci%lu\n", -+ a->mask, a->dir->i_ino, a->h_dir->i_ino, -+ a->h_child_inode ? a->h_child_inode->i_ino : 0); -+ -+ inode = NULL; -+ dentry = NULL; -+ /* -+ * do not lock a->dir->i_mutex here -+ * because of d_revalidate() may cause a deadlock. -+ */ -+ sb = a->dir->i_sb; -+ AuDebugOn(!sb); -+ sbinfo = au_sbi(sb); -+ AuDebugOn(!sbinfo); -+ si_write_lock(sb, AuLock_NOPLMW); -+ -+ if (au_opt_test(sbinfo->si_mntflags, DIRREN)) -+ switch (a->mask & FS_EVENTS_POSS_ON_CHILD) { -+ case FS_MOVED_FROM: -+ case FS_MOVED_TO: -+ AuWarn1("DIRREN with UDBA may not work correctly " -+ "for the direct rename(2)\n"); -+ } -+ -+ ii_read_lock_parent(a->dir); -+ bfound = -1; -+ bbot = au_ibbot(a->dir); -+ for (bindex = au_ibtop(a->dir); bindex <= bbot; bindex++) -+ if (au_h_iptr(a->dir, bindex) == a->h_dir) { -+ bfound = bindex; -+ break; -+ } -+ ii_read_unlock(a->dir); -+ if (unlikely(bfound < 0)) -+ goto out; -+ -+ xino = !!au_opt_test(au_mntflags(sb), XINO); -+ h_ino = 0; -+ if (a->h_child_inode) -+ h_ino = a->h_child_inode->i_ino; -+ -+ if (a->h_child_nlen -+ && (au_ftest_hnjob(a->flags[AuHn_CHILD], GEN) -+ || au_ftest_hnjob(a->flags[AuHn_CHILD], MNTPNT))) -+ dentry = lookup_wlock_by_name(a->h_child_name, a->h_child_nlen, -+ a->dir); -+ try_iput = 0; -+ if (dentry && d_really_is_positive(dentry)) -+ inode = d_inode(dentry); -+ if (xino && !inode && h_ino -+ && (au_ftest_hnjob(a->flags[AuHn_CHILD], XINO0) -+ || au_ftest_hnjob(a->flags[AuHn_CHILD], TRYXINO0) -+ || au_ftest_hnjob(a->flags[AuHn_CHILD], GEN))) { -+ inode = lookup_wlock_by_ino(sb, bfound, h_ino); -+ try_iput = 1; -+ } -+ -+ args.flags = a->flags[AuHn_CHILD]; -+ args.dentry = dentry; -+ args.inode = inode; -+ args.h_inode = a->h_child_inode; -+ args.dir = a->dir; -+ args.h_dir = a->h_dir; -+ args.h_name = a->h_child_name; -+ args.h_nlen = a->h_child_nlen; -+ err = hn_job(&args); -+ if (dentry) { -+ if (au_di(dentry)) -+ di_write_unlock(dentry); -+ dput(dentry); -+ } -+ if (inode && try_iput) { -+ ii_write_unlock(inode); -+ iput(inode); -+ } -+ -+ ii_write_lock_parent(a->dir); -+ args.flags = a->flags[AuHn_PARENT]; -+ args.dentry = NULL; -+ args.inode = a->dir; -+ args.h_inode = a->h_dir; -+ args.dir = NULL; -+ args.h_dir = NULL; -+ args.h_name = NULL; -+ args.h_nlen = 0; -+ err = hn_job(&args); -+ ii_write_unlock(a->dir); -+ -+out: -+ iput(a->h_child_inode); -+ iput(a->h_dir); -+ iput(a->dir); -+ si_write_unlock(sb); -+ au_nwt_done(&sbinfo->si_nowait); -+ au_kfree_rcu(a); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+int au_hnotify(struct inode *h_dir, struct au_hnotify *hnotify, u32 mask, -+ const struct qstr *h_child_qstr, struct inode *h_child_inode) -+{ -+ int err, len; -+ unsigned int flags[AuHnLast], f; -+ unsigned char isdir, isroot, wh; -+ struct inode *dir; -+ struct au_hnotify_args *args; -+ char *p, *h_child_name; -+ -+ err = 0; -+ AuDebugOn(!hnotify || !hnotify->hn_aufs_inode); -+ dir = igrab(hnotify->hn_aufs_inode); -+ if (!dir) -+ goto out; -+ -+ isroot = (dir->i_ino == AUFS_ROOT_INO); -+ wh = 0; -+ h_child_name = (void *)h_child_qstr->name; -+ len = h_child_qstr->len; -+ if (h_child_name) { -+ if (len > AUFS_WH_PFX_LEN -+ && !memcmp(h_child_name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) { -+ h_child_name += AUFS_WH_PFX_LEN; -+ len -= AUFS_WH_PFX_LEN; -+ wh = 1; -+ } -+ } -+ -+ isdir = 0; -+ if (h_child_inode) -+ isdir = !!S_ISDIR(h_child_inode->i_mode); -+ flags[AuHn_PARENT] = AuHnJob_ISDIR; -+ flags[AuHn_CHILD] = 0; -+ if (isdir) -+ flags[AuHn_CHILD] = AuHnJob_ISDIR; -+ au_fset_hnjob(flags[AuHn_PARENT], DIRENT); -+ au_fset_hnjob(flags[AuHn_CHILD], GEN); -+ switch (mask & ALL_FSNOTIFY_DIRENT_EVENTS) { -+ case FS_MOVED_FROM: -+ case FS_MOVED_TO: -+ au_fset_hnjob(flags[AuHn_CHILD], XINO0); -+ au_fset_hnjob(flags[AuHn_CHILD], MNTPNT); -+ /*FALLTHROUGH*/ -+ case FS_CREATE: -+ AuDebugOn(!h_child_name); -+ break; -+ -+ case FS_DELETE: -+ /* -+ * aufs never be able to get this child inode. -+ * revalidation should be in d_revalidate() -+ * by checking i_nlink, i_generation or d_unhashed(). -+ */ -+ AuDebugOn(!h_child_name); -+ au_fset_hnjob(flags[AuHn_CHILD], TRYXINO0); -+ au_fset_hnjob(flags[AuHn_CHILD], MNTPNT); -+ break; -+ -+ default: -+ AuDebugOn(1); -+ } -+ -+ if (wh) -+ h_child_inode = NULL; -+ -+ err = -ENOMEM; -+ /* iput() and kfree() will be called in au_hnotify() */ -+ args = kmalloc(sizeof(*args) + len + 1, GFP_NOFS); -+ if (unlikely(!args)) { -+ AuErr1("no memory\n"); -+ iput(dir); -+ goto out; -+ } -+ args->flags[AuHn_PARENT] = flags[AuHn_PARENT]; -+ args->flags[AuHn_CHILD] = flags[AuHn_CHILD]; -+ args->mask = mask; -+ args->dir = dir; -+ args->h_dir = igrab(h_dir); -+ if (h_child_inode) -+ h_child_inode = igrab(h_child_inode); /* can be NULL */ -+ args->h_child_inode = h_child_inode; -+ args->h_child_nlen = len; -+ if (len) { -+ p = (void *)args; -+ p += sizeof(*args); -+ memcpy(p, h_child_name, len); -+ p[len] = 0; -+ } -+ -+ /* NFS fires the event for silly-renamed one from kworker */ -+ f = 0; -+ if (!dir->i_nlink -+ || (au_test_nfs(h_dir->i_sb) && (mask & FS_DELETE))) -+ f = AuWkq_NEST; -+ err = au_wkq_nowait(au_hn_bh, args, dir->i_sb, f); -+ if (unlikely(err)) { -+ pr_err("wkq %d\n", err); -+ iput(args->h_child_inode); -+ iput(args->h_dir); -+ iput(args->dir); -+ au_kfree_rcu(args); -+ } -+ -+out: -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+int au_hnotify_reset_br(unsigned int udba, struct au_branch *br, int perm) -+{ -+ int err; -+ -+ AuDebugOn(!(udba & AuOptMask_UDBA)); -+ -+ err = 0; -+ if (au_hnotify_op.reset_br) -+ err = au_hnotify_op.reset_br(udba, br, perm); -+ -+ return err; -+} -+ -+int au_hnotify_init_br(struct au_branch *br, int perm) -+{ -+ int err; -+ -+ err = 0; -+ if (au_hnotify_op.init_br) -+ err = au_hnotify_op.init_br(br, perm); -+ -+ return err; -+} -+ -+void au_hnotify_fin_br(struct au_branch *br) -+{ -+ if (au_hnotify_op.fin_br) -+ au_hnotify_op.fin_br(br); -+} -+ -+static void au_hn_destroy_cache(void) -+{ -+ kmem_cache_destroy(au_cache[AuCache_HNOTIFY]); -+ au_cache[AuCache_HNOTIFY] = NULL; -+} -+ -+int __init au_hnotify_init(void) -+{ -+ int err; -+ -+ err = -ENOMEM; -+ au_cache[AuCache_HNOTIFY] = AuCache(au_hnotify); -+ if (au_cache[AuCache_HNOTIFY]) { -+ err = 0; -+ if (au_hnotify_op.init) -+ err = au_hnotify_op.init(); -+ if (unlikely(err)) -+ au_hn_destroy_cache(); -+ } -+ AuTraceErr(err); -+ return err; -+} -+ -+void au_hnotify_fin(void) -+{ -+ if (au_hnotify_op.fin) -+ au_hnotify_op.fin(); -+ -+ /* cf. au_cache_fin() */ -+ if (au_cache[AuCache_HNOTIFY]) -+ au_hn_destroy_cache(); -+} -diff --git a/fs/aufs/i_op.c b/fs/aufs/i_op.c -new file mode 100644 -index 000000000000..42bc497e2630 ---- /dev/null -+++ b/fs/aufs/i_op.c -@@ -0,0 +1,1489 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * inode operations (except add/del/rename) -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include "aufs.h" -+ -+static int h_permission(struct inode *h_inode, int mask, -+ struct path *h_path, int brperm) -+{ -+ int err; -+ const unsigned char write_mask = !!(mask & (MAY_WRITE | MAY_APPEND)); -+ -+ err = -EPERM; -+ if (write_mask && IS_IMMUTABLE(h_inode)) -+ goto out; -+ -+ err = -EACCES; -+ if (((mask & MAY_EXEC) -+ && S_ISREG(h_inode->i_mode) -+ && (path_noexec(h_path) -+ || !(h_inode->i_mode & 0111)))) -+ goto out; -+ -+ /* -+ * - skip the lower fs test in the case of write to ro branch. -+ * - nfs dir permission write check is optimized, but a policy for -+ * link/rename requires a real check. -+ * - nfs always sets SB_POSIXACL regardless its mount option 'noacl.' -+ * in this case, generic_permission() returns -EOPNOTSUPP. -+ */ -+ if ((write_mask && !au_br_writable(brperm)) -+ || (au_test_nfs(h_inode->i_sb) && S_ISDIR(h_inode->i_mode) -+ && write_mask && !(mask & MAY_READ)) -+ || !h_inode->i_op->permission) { -+ /* AuLabel(generic_permission); */ -+ /* AuDbg("get_acl %ps\n", h_inode->i_op->get_acl); */ -+ err = generic_permission(h_inode, mask); -+ if (err == -EOPNOTSUPP && au_test_nfs_noacl(h_inode)) -+ err = h_inode->i_op->permission(h_inode, mask); -+ AuTraceErr(err); -+ } else { -+ /* AuLabel(h_inode->permission); */ -+ err = h_inode->i_op->permission(h_inode, mask); -+ AuTraceErr(err); -+ } -+ -+ if (!err) -+ err = devcgroup_inode_permission(h_inode, mask); -+ if (!err) -+ err = security_inode_permission(h_inode, mask); -+ -+out: -+ return err; -+} -+ -+static int aufs_permission(struct inode *inode, int mask) -+{ -+ int err; -+ aufs_bindex_t bindex, bbot; -+ const unsigned char isdir = !!S_ISDIR(inode->i_mode), -+ write_mask = !!(mask & (MAY_WRITE | MAY_APPEND)); -+ struct inode *h_inode; -+ struct super_block *sb; -+ struct au_branch *br; -+ -+ /* todo: support rcu-walk? */ -+ if (mask & MAY_NOT_BLOCK) -+ return -ECHILD; -+ -+ sb = inode->i_sb; -+ si_read_lock(sb, AuLock_FLUSH); -+ ii_read_lock_child(inode); -+#if 0 /* reserved for future use */ -+ /* -+ * This test may be rather 'too much' since the test is essentially done -+ * in the aufs_lookup(). Theoretically it is possible that the inode -+ * generation doesn't match to the superblock's here. But it isn't a -+ * big deal I suppose. -+ */ -+ err = au_iigen_test(inode, au_sigen(sb)); -+ if (unlikely(err)) -+ goto out; -+#endif -+ -+ if (!isdir -+ || write_mask -+ || au_opt_test(au_mntflags(sb), DIRPERM1)) { -+ err = au_busy_or_stale(); -+ h_inode = au_h_iptr(inode, au_ibtop(inode)); -+ if (unlikely(!h_inode -+ || (h_inode->i_mode & S_IFMT) -+ != (inode->i_mode & S_IFMT))) -+ goto out; -+ -+ err = 0; -+ bindex = au_ibtop(inode); -+ br = au_sbr(sb, bindex); -+ err = h_permission(h_inode, mask, &br->br_path, br->br_perm); -+ if (write_mask -+ && !err -+ && !special_file(h_inode->i_mode)) { -+ /* test whether the upper writable branch exists */ -+ err = -EROFS; -+ for (; bindex >= 0; bindex--) -+ if (!au_br_rdonly(au_sbr(sb, bindex))) { -+ err = 0; -+ break; -+ } -+ } -+ goto out; -+ } -+ -+ /* non-write to dir */ -+ err = 0; -+ bbot = au_ibbot(inode); -+ for (bindex = au_ibtop(inode); !err && bindex <= bbot; bindex++) { -+ h_inode = au_h_iptr(inode, bindex); -+ if (h_inode) { -+ err = au_busy_or_stale(); -+ if (unlikely(!S_ISDIR(h_inode->i_mode))) -+ break; -+ -+ br = au_sbr(sb, bindex); -+ err = h_permission(h_inode, mask, &br->br_path, -+ br->br_perm); -+ } -+ } -+ -+out: -+ ii_read_unlock(inode); -+ si_read_unlock(sb); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static struct dentry *aufs_lookup(struct inode *dir, struct dentry *dentry, -+ unsigned int flags) -+{ -+ struct dentry *ret, *parent; -+ struct inode *inode; -+ struct super_block *sb; -+ int err, npositive; -+ -+ IMustLock(dir); -+ -+ /* todo: support rcu-walk? */ -+ ret = ERR_PTR(-ECHILD); -+ if (flags & LOOKUP_RCU) -+ goto out; -+ -+ ret = ERR_PTR(-ENAMETOOLONG); -+ if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN)) -+ goto out; -+ -+ sb = dir->i_sb; -+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM); -+ ret = ERR_PTR(err); -+ if (unlikely(err)) -+ goto out; -+ -+ err = au_di_init(dentry); -+ ret = ERR_PTR(err); -+ if (unlikely(err)) -+ goto out_si; -+ -+ inode = NULL; -+ npositive = 0; /* suppress a warning */ -+ parent = dentry->d_parent; /* dir inode is locked */ -+ di_read_lock_parent(parent, AuLock_IR); -+ err = au_alive_dir(parent); -+ if (!err) -+ err = au_digen_test(parent, au_sigen(sb)); -+ if (!err) { -+ /* regardless LOOKUP_CREATE, always ALLOW_NEG */ -+ npositive = au_lkup_dentry(dentry, au_dbtop(parent), -+ AuLkup_ALLOW_NEG); -+ err = npositive; -+ } -+ di_read_unlock(parent, AuLock_IR); -+ ret = ERR_PTR(err); -+ if (unlikely(err < 0)) -+ goto out_unlock; -+ -+ if (npositive) { -+ inode = au_new_inode(dentry, /*must_new*/0); -+ if (IS_ERR(inode)) { -+ ret = (void *)inode; -+ inode = NULL; -+ goto out_unlock; -+ } -+ } -+ -+ if (inode) -+ atomic_inc(&inode->i_count); -+ ret = d_splice_alias(inode, dentry); -+#if 0 /* reserved for future use */ -+ if (unlikely(d_need_lookup(dentry))) { -+ spin_lock(&dentry->d_lock); -+ dentry->d_flags &= ~DCACHE_NEED_LOOKUP; -+ spin_unlock(&dentry->d_lock); -+ } else -+#endif -+ if (inode) { -+ if (!IS_ERR(ret)) { -+ iput(inode); -+ if (ret && ret != dentry) -+ ii_write_unlock(inode); -+ } else { -+ ii_write_unlock(inode); -+ iput(inode); -+ inode = NULL; -+ } -+ } -+ -+out_unlock: -+ di_write_unlock(dentry); -+out_si: -+ si_read_unlock(sb); -+out: -+ return ret; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * very dirty and complicated aufs ->atomic_open(). -+ * aufs_atomic_open() -+ * + au_aopen_or_create() -+ * + add_simple() -+ * + vfsub_atomic_open() -+ * + branch fs ->atomic_open() -+ * may call the actual 'open' for h_file -+ * + inc br_nfiles only if opened -+ * + au_aopen_no_open() or au_aopen_do_open() -+ * -+ * au_aopen_do_open() -+ * + finish_open() -+ * + au_do_aopen() -+ * + au_do_open() the body of all 'open' -+ * + au_do_open_nondir() -+ * set the passed h_file -+ * -+ * au_aopen_no_open() -+ * + finish_no_open() -+ */ -+ -+struct aopen_node { -+ struct hlist_bl_node hblist; -+ struct file *file, *h_file; -+}; -+ -+static int au_do_aopen(struct inode *inode, struct file *file) -+{ -+ struct hlist_bl_head *aopen; -+ struct hlist_bl_node *pos; -+ struct aopen_node *node; -+ struct au_do_open_args args = { -+ .aopen = 1, -+ .open = au_do_open_nondir -+ }; -+ -+ aopen = &au_sbi(inode->i_sb)->si_aopen; -+ hlist_bl_lock(aopen); -+ hlist_bl_for_each_entry(node, pos, aopen, hblist) -+ if (node->file == file) { -+ args.h_file = node->h_file; -+ break; -+ } -+ hlist_bl_unlock(aopen); -+ /* AuDebugOn(!args.h_file); */ -+ -+ return au_do_open(file, &args); -+} -+ -+static int au_aopen_do_open(struct file *file, struct dentry *dentry, -+ struct aopen_node *aopen_node) -+{ -+ int err; -+ struct hlist_bl_head *aopen; -+ -+ AuLabel(here); -+ aopen = &au_sbi(dentry->d_sb)->si_aopen; -+ au_hbl_add(&aopen_node->hblist, aopen); -+ err = finish_open(file, dentry, au_do_aopen); -+ au_hbl_del(&aopen_node->hblist, aopen); -+ /* AuDbgFile(file); */ -+ AuDbg("%pd%s%s\n", dentry, -+ (file->f_mode & FMODE_CREATED) ? " created" : "", -+ (file->f_mode & FMODE_OPENED) ? " opened" : ""); -+ -+ AuTraceErr(err); -+ return err; -+} -+ -+static int au_aopen_no_open(struct file *file, struct dentry *dentry) -+{ -+ int err; -+ -+ AuLabel(here); -+ dget(dentry); -+ err = finish_no_open(file, dentry); -+ -+ AuTraceErr(err); -+ return err; -+} -+ -+static int aufs_atomic_open(struct inode *dir, struct dentry *dentry, -+ struct file *file, unsigned int open_flag, -+ umode_t create_mode) -+{ -+ int err, did_open; -+ unsigned int lkup_flags; -+ aufs_bindex_t bindex; -+ struct super_block *sb; -+ struct dentry *parent, *d; -+ struct vfsub_aopen_args args = { -+ .open_flag = open_flag, -+ .create_mode = create_mode -+ }; -+ struct aopen_node aopen_node = { -+ .file = file -+ }; -+ -+ IMustLock(dir); -+ AuDbg("open_flag 0%o\n", open_flag); -+ AuDbgDentry(dentry); -+ -+ err = 0; -+ if (!au_di(dentry)) { -+ lkup_flags = LOOKUP_OPEN; -+ if (open_flag & O_CREAT) -+ lkup_flags |= LOOKUP_CREATE; -+ d = aufs_lookup(dir, dentry, lkup_flags); -+ if (IS_ERR(d)) { -+ err = PTR_ERR(d); -+ AuTraceErr(err); -+ goto out; -+ } else if (d) { -+ /* -+ * obsoleted dentry found. -+ * another error will be returned later. -+ */ -+ d_drop(d); -+ AuDbgDentry(d); -+ dput(d); -+ } -+ AuDbgDentry(dentry); -+ } -+ -+ if (d_is_positive(dentry) -+ || d_unhashed(dentry) -+ || d_unlinked(dentry) -+ || !(open_flag & O_CREAT)) { -+ err = au_aopen_no_open(file, dentry); -+ goto out; /* success */ -+ } -+ -+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH | AuLock_GEN); -+ if (unlikely(err)) -+ goto out; -+ -+ sb = dentry->d_sb; -+ parent = dentry->d_parent; /* dir is locked */ -+ di_write_lock_parent(parent); -+ err = au_lkup_dentry(dentry, /*btop*/0, AuLkup_ALLOW_NEG); -+ if (unlikely(err < 0)) -+ goto out_parent; -+ -+ AuDbgDentry(dentry); -+ if (d_is_positive(dentry)) { -+ err = au_aopen_no_open(file, dentry); -+ goto out_parent; /* success */ -+ } -+ -+ args.file = alloc_empty_file(file->f_flags, current_cred()); -+ err = PTR_ERR(args.file); -+ if (IS_ERR(args.file)) -+ goto out_parent; -+ -+ bindex = au_dbtop(dentry); -+ err = au_aopen_or_create(dir, dentry, &args); -+ AuTraceErr(err); -+ AuDbgFile(args.file); -+ file->f_mode = args.file->f_mode & ~FMODE_OPENED; -+ did_open = !!(args.file->f_mode & FMODE_OPENED); -+ if (!did_open) { -+ fput(args.file); -+ args.file = NULL; -+ } -+ di_write_unlock(parent); -+ di_write_unlock(dentry); -+ if (unlikely(err < 0)) { -+ if (args.file) -+ fput(args.file); -+ goto out_sb; -+ } -+ -+ if (!did_open) -+ err = au_aopen_no_open(file, dentry); -+ else { -+ aopen_node.h_file = args.file; -+ err = au_aopen_do_open(file, dentry, &aopen_node); -+ } -+ if (unlikely(err < 0)) { -+ if (args.file) -+ fput(args.file); -+ if (did_open) -+ au_lcnt_dec(&args.br->br_nfiles); -+ } -+ goto out_sb; /* success */ -+ -+out_parent: -+ di_write_unlock(parent); -+ di_write_unlock(dentry); -+out_sb: -+ si_read_unlock(sb); -+out: -+ AuTraceErr(err); -+ AuDbgFile(file); -+ return err; -+} -+ -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int au_wr_dir_cpup(struct dentry *dentry, struct dentry *parent, -+ const unsigned char add_entry, aufs_bindex_t bcpup, -+ aufs_bindex_t btop) -+{ -+ int err; -+ struct dentry *h_parent; -+ struct inode *h_dir; -+ -+ if (add_entry) -+ IMustLock(d_inode(parent)); -+ else -+ di_write_lock_parent(parent); -+ -+ err = 0; -+ if (!au_h_dptr(parent, bcpup)) { -+ if (btop > bcpup) -+ err = au_cpup_dirs(dentry, bcpup); -+ else if (btop < bcpup) -+ err = au_cpdown_dirs(dentry, bcpup); -+ else -+ BUG(); -+ } -+ if (!err && add_entry && !au_ftest_wrdir(add_entry, TMPFILE)) { -+ h_parent = au_h_dptr(parent, bcpup); -+ h_dir = d_inode(h_parent); -+ inode_lock_shared_nested(h_dir, AuLsc_I_PARENT); -+ err = au_lkup_neg(dentry, bcpup, /*wh*/0); -+ /* todo: no unlock here */ -+ inode_unlock_shared(h_dir); -+ -+ AuDbg("bcpup %d\n", bcpup); -+ if (!err) { -+ if (d_really_is_negative(dentry)) -+ au_set_h_dptr(dentry, btop, NULL); -+ au_update_dbrange(dentry, /*do_put_zero*/0); -+ } -+ } -+ -+ if (!add_entry) -+ di_write_unlock(parent); -+ if (!err) -+ err = bcpup; /* success */ -+ -+ AuTraceErr(err); -+ return err; -+} -+ -+/* -+ * decide the branch and the parent dir where we will create a new entry. -+ * returns new bindex or an error. -+ * copyup the parent dir if needed. -+ */ -+int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry, -+ struct au_wr_dir_args *args) -+{ -+ int err; -+ unsigned int flags; -+ aufs_bindex_t bcpup, btop, src_btop; -+ const unsigned char add_entry -+ = au_ftest_wrdir(args->flags, ADD_ENTRY) -+ | au_ftest_wrdir(args->flags, TMPFILE); -+ struct super_block *sb; -+ struct dentry *parent; -+ struct au_sbinfo *sbinfo; -+ -+ sb = dentry->d_sb; -+ sbinfo = au_sbi(sb); -+ parent = dget_parent(dentry); -+ btop = au_dbtop(dentry); -+ bcpup = btop; -+ if (args->force_btgt < 0) { -+ if (src_dentry) { -+ src_btop = au_dbtop(src_dentry); -+ if (src_btop < btop) -+ bcpup = src_btop; -+ } else if (add_entry) { -+ flags = 0; -+ if (au_ftest_wrdir(args->flags, ISDIR)) -+ au_fset_wbr(flags, DIR); -+ err = AuWbrCreate(sbinfo, dentry, flags); -+ bcpup = err; -+ } -+ -+ if (bcpup < 0 || au_test_ro(sb, bcpup, d_inode(dentry))) { -+ if (add_entry) -+ err = AuWbrCopyup(sbinfo, dentry); -+ else { -+ if (!IS_ROOT(dentry)) { -+ di_read_lock_parent(parent, !AuLock_IR); -+ err = AuWbrCopyup(sbinfo, dentry); -+ di_read_unlock(parent, !AuLock_IR); -+ } else -+ err = AuWbrCopyup(sbinfo, dentry); -+ } -+ bcpup = err; -+ if (unlikely(err < 0)) -+ goto out; -+ } -+ } else { -+ bcpup = args->force_btgt; -+ AuDebugOn(au_test_ro(sb, bcpup, d_inode(dentry))); -+ } -+ -+ AuDbg("btop %d, bcpup %d\n", btop, bcpup); -+ err = bcpup; -+ if (bcpup == btop) -+ goto out; /* success */ -+ -+ /* copyup the new parent into the branch we process */ -+ err = au_wr_dir_cpup(dentry, parent, add_entry, bcpup, btop); -+ if (err >= 0) { -+ if (d_really_is_negative(dentry)) { -+ au_set_h_dptr(dentry, btop, NULL); -+ au_set_dbtop(dentry, bcpup); -+ au_set_dbbot(dentry, bcpup); -+ } -+ AuDebugOn(add_entry -+ && !au_ftest_wrdir(args->flags, TMPFILE) -+ && !au_h_dptr(dentry, bcpup)); -+ } -+ -+out: -+ dput(parent); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+void au_pin_hdir_unlock(struct au_pin *p) -+{ -+ if (p->hdir) -+ au_hn_inode_unlock(p->hdir); -+} -+ -+int au_pin_hdir_lock(struct au_pin *p) -+{ -+ int err; -+ -+ err = 0; -+ if (!p->hdir) -+ goto out; -+ -+ /* even if an error happens later, keep this lock */ -+ au_hn_inode_lock_nested(p->hdir, p->lsc_hi); -+ -+ err = -EBUSY; -+ if (unlikely(p->hdir->hi_inode != d_inode(p->h_parent))) -+ goto out; -+ -+ err = 0; -+ if (p->h_dentry) -+ err = au_h_verify(p->h_dentry, p->udba, p->hdir->hi_inode, -+ p->h_parent, p->br); -+ -+out: -+ return err; -+} -+ -+int au_pin_hdir_relock(struct au_pin *p) -+{ -+ int err, i; -+ struct inode *h_i; -+ struct dentry *h_d[] = { -+ p->h_dentry, -+ p->h_parent -+ }; -+ -+ err = au_pin_hdir_lock(p); -+ if (unlikely(err)) -+ goto out; -+ -+ for (i = 0; !err && i < sizeof(h_d)/sizeof(*h_d); i++) { -+ if (!h_d[i]) -+ continue; -+ if (d_is_positive(h_d[i])) { -+ h_i = d_inode(h_d[i]); -+ err = !h_i->i_nlink; -+ } -+ } -+ -+out: -+ return err; -+} -+ -+static void au_pin_hdir_set_owner(struct au_pin *p, struct task_struct *task) -+{ -+ atomic_long_set(&p->hdir->hi_inode->i_rwsem.owner, (long)task); -+} -+ -+void au_pin_hdir_acquire_nest(struct au_pin *p) -+{ -+ if (p->hdir) { -+ rwsem_acquire_nest(&p->hdir->hi_inode->i_rwsem.dep_map, -+ p->lsc_hi, 0, NULL, _RET_IP_); -+ au_pin_hdir_set_owner(p, current); -+ } -+} -+ -+void au_pin_hdir_release(struct au_pin *p) -+{ -+ if (p->hdir) { -+ au_pin_hdir_set_owner(p, p->task); -+ rwsem_release(&p->hdir->hi_inode->i_rwsem.dep_map, _RET_IP_); -+ } -+} -+ -+struct dentry *au_pinned_h_parent(struct au_pin *pin) -+{ -+ if (pin && pin->parent) -+ return au_h_dptr(pin->parent, pin->bindex); -+ return NULL; -+} -+ -+void au_unpin(struct au_pin *p) -+{ -+ if (p->hdir) -+ au_pin_hdir_unlock(p); -+ if (p->h_mnt && au_ftest_pin(p->flags, MNT_WRITE)) -+ vfsub_mnt_drop_write(p->h_mnt); -+ if (!p->hdir) -+ return; -+ -+ if (!au_ftest_pin(p->flags, DI_LOCKED)) -+ di_read_unlock(p->parent, AuLock_IR); -+ iput(p->hdir->hi_inode); -+ dput(p->parent); -+ p->parent = NULL; -+ p->hdir = NULL; -+ p->h_mnt = NULL; -+ /* do not clear p->task */ -+} -+ -+int au_do_pin(struct au_pin *p) -+{ -+ int err; -+ struct super_block *sb; -+ struct inode *h_dir; -+ -+ err = 0; -+ sb = p->dentry->d_sb; -+ p->br = au_sbr(sb, p->bindex); -+ if (IS_ROOT(p->dentry)) { -+ if (au_ftest_pin(p->flags, MNT_WRITE)) { -+ p->h_mnt = au_br_mnt(p->br); -+ err = vfsub_mnt_want_write(p->h_mnt); -+ if (unlikely(err)) { -+ au_fclr_pin(p->flags, MNT_WRITE); -+ goto out_err; -+ } -+ } -+ goto out; -+ } -+ -+ p->h_dentry = NULL; -+ if (p->bindex <= au_dbbot(p->dentry)) -+ p->h_dentry = au_h_dptr(p->dentry, p->bindex); -+ -+ p->parent = dget_parent(p->dentry); -+ if (!au_ftest_pin(p->flags, DI_LOCKED)) -+ di_read_lock(p->parent, AuLock_IR, p->lsc_di); -+ -+ h_dir = NULL; -+ p->h_parent = au_h_dptr(p->parent, p->bindex); -+ p->hdir = au_hi(d_inode(p->parent), p->bindex); -+ if (p->hdir) -+ h_dir = p->hdir->hi_inode; -+ -+ /* -+ * udba case, or -+ * if DI_LOCKED is not set, then p->parent may be different -+ * and h_parent can be NULL. -+ */ -+ if (unlikely(!p->hdir || !h_dir || !p->h_parent)) { -+ err = -EBUSY; -+ if (!au_ftest_pin(p->flags, DI_LOCKED)) -+ di_read_unlock(p->parent, AuLock_IR); -+ dput(p->parent); -+ p->parent = NULL; -+ goto out_err; -+ } -+ -+ if (au_ftest_pin(p->flags, MNT_WRITE)) { -+ p->h_mnt = au_br_mnt(p->br); -+ err = vfsub_mnt_want_write(p->h_mnt); -+ if (unlikely(err)) { -+ au_fclr_pin(p->flags, MNT_WRITE); -+ if (!au_ftest_pin(p->flags, DI_LOCKED)) -+ di_read_unlock(p->parent, AuLock_IR); -+ dput(p->parent); -+ p->parent = NULL; -+ goto out_err; -+ } -+ } -+ -+ au_igrab(h_dir); -+ err = au_pin_hdir_lock(p); -+ if (!err) -+ goto out; /* success */ -+ -+ au_unpin(p); -+ -+out_err: -+ pr_err("err %d\n", err); -+ err = au_busy_or_stale(); -+out: -+ return err; -+} -+ -+void au_pin_init(struct au_pin *p, struct dentry *dentry, -+ aufs_bindex_t bindex, int lsc_di, int lsc_hi, -+ unsigned int udba, unsigned char flags) -+{ -+ p->dentry = dentry; -+ p->udba = udba; -+ p->lsc_di = lsc_di; -+ p->lsc_hi = lsc_hi; -+ p->flags = flags; -+ p->bindex = bindex; -+ -+ p->parent = NULL; -+ p->hdir = NULL; -+ p->h_mnt = NULL; -+ -+ p->h_dentry = NULL; -+ p->h_parent = NULL; -+ p->br = NULL; -+ p->task = current; -+} -+ -+int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex, -+ unsigned int udba, unsigned char flags) -+{ -+ au_pin_init(pin, dentry, bindex, AuLsc_DI_PARENT, AuLsc_I_PARENT2, -+ udba, flags); -+ return au_do_pin(pin); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * ->setattr() and ->getattr() are called in various cases. -+ * chmod, stat: dentry is revalidated. -+ * fchmod, fstat: file and dentry are not revalidated, additionally they may be -+ * unhashed. -+ * for ->setattr(), ia->ia_file is passed from ftruncate only. -+ */ -+/* todo: consolidate with do_refresh() and simple_reval_dpath() */ -+int au_reval_for_attr(struct dentry *dentry, unsigned int sigen) -+{ -+ int err; -+ struct dentry *parent; -+ -+ err = 0; -+ if (au_digen_test(dentry, sigen)) { -+ parent = dget_parent(dentry); -+ di_read_lock_parent(parent, AuLock_IR); -+ err = au_refresh_dentry(dentry, parent); -+ di_read_unlock(parent, AuLock_IR); -+ dput(parent); -+ } -+ -+ AuTraceErr(err); -+ return err; -+} -+ -+int au_pin_and_icpup(struct dentry *dentry, struct iattr *ia, -+ struct au_icpup_args *a) -+{ -+ int err; -+ loff_t sz; -+ aufs_bindex_t btop, ibtop; -+ struct dentry *hi_wh, *parent; -+ struct inode *inode; -+ struct au_wr_dir_args wr_dir_args = { -+ .force_btgt = -1, -+ .flags = 0 -+ }; -+ -+ if (d_is_dir(dentry)) -+ au_fset_wrdir(wr_dir_args.flags, ISDIR); -+ /* plink or hi_wh() case */ -+ btop = au_dbtop(dentry); -+ inode = d_inode(dentry); -+ ibtop = au_ibtop(inode); -+ if (btop != ibtop && !au_test_ro(inode->i_sb, ibtop, inode)) -+ wr_dir_args.force_btgt = ibtop; -+ err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args); -+ if (unlikely(err < 0)) -+ goto out; -+ a->btgt = err; -+ if (err != btop) -+ au_fset_icpup(a->flags, DID_CPUP); -+ -+ err = 0; -+ a->pin_flags = AuPin_MNT_WRITE; -+ parent = NULL; -+ if (!IS_ROOT(dentry)) { -+ au_fset_pin(a->pin_flags, DI_LOCKED); -+ parent = dget_parent(dentry); -+ di_write_lock_parent(parent); -+ } -+ -+ err = au_pin(&a->pin, dentry, a->btgt, a->udba, a->pin_flags); -+ if (unlikely(err)) -+ goto out_parent; -+ -+ sz = -1; -+ a->h_path.dentry = au_h_dptr(dentry, btop); -+ a->h_inode = d_inode(a->h_path.dentry); -+ if (ia && (ia->ia_valid & ATTR_SIZE)) { -+ inode_lock_shared_nested(a->h_inode, AuLsc_I_CHILD); -+ if (ia->ia_size < i_size_read(a->h_inode)) -+ sz = ia->ia_size; -+ inode_unlock_shared(a->h_inode); -+ } -+ -+ hi_wh = NULL; -+ if (au_ftest_icpup(a->flags, DID_CPUP) && d_unlinked(dentry)) { -+ hi_wh = au_hi_wh(inode, a->btgt); -+ if (!hi_wh) { -+ struct au_cp_generic cpg = { -+ .dentry = dentry, -+ .bdst = a->btgt, -+ .bsrc = -1, -+ .len = sz, -+ .pin = &a->pin -+ }; -+ err = au_sio_cpup_wh(&cpg, /*file*/NULL); -+ if (unlikely(err)) -+ goto out_unlock; -+ hi_wh = au_hi_wh(inode, a->btgt); -+ /* todo: revalidate hi_wh? */ -+ } -+ } -+ -+ if (parent) { -+ au_pin_set_parent_lflag(&a->pin, /*lflag*/0); -+ di_downgrade_lock(parent, AuLock_IR); -+ dput(parent); -+ parent = NULL; -+ } -+ if (!au_ftest_icpup(a->flags, DID_CPUP)) -+ goto out; /* success */ -+ -+ if (!d_unhashed(dentry)) { -+ struct au_cp_generic cpg = { -+ .dentry = dentry, -+ .bdst = a->btgt, -+ .bsrc = btop, -+ .len = sz, -+ .pin = &a->pin, -+ .flags = AuCpup_DTIME | AuCpup_HOPEN -+ }; -+ err = au_sio_cpup_simple(&cpg); -+ if (!err) -+ a->h_path.dentry = au_h_dptr(dentry, a->btgt); -+ } else if (!hi_wh) -+ a->h_path.dentry = au_h_dptr(dentry, a->btgt); -+ else -+ a->h_path.dentry = hi_wh; /* do not dget here */ -+ -+out_unlock: -+ a->h_inode = d_inode(a->h_path.dentry); -+ if (!err) -+ goto out; /* success */ -+ au_unpin(&a->pin); -+out_parent: -+ if (parent) { -+ di_write_unlock(parent); -+ dput(parent); -+ } -+out: -+ if (!err) -+ inode_lock_nested(a->h_inode, AuLsc_I_CHILD); -+ return err; -+} -+ -+static int aufs_setattr(struct dentry *dentry, struct iattr *ia) -+{ -+ int err; -+ struct inode *inode, *delegated; -+ struct super_block *sb; -+ struct file *file; -+ struct au_icpup_args *a; -+ -+ inode = d_inode(dentry); -+ IMustLock(inode); -+ -+ err = setattr_prepare(dentry, ia); -+ if (unlikely(err)) -+ goto out; -+ -+ err = -ENOMEM; -+ a = kzalloc(sizeof(*a), GFP_NOFS); -+ if (unlikely(!a)) -+ goto out; -+ -+ if (ia->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID)) -+ ia->ia_valid &= ~ATTR_MODE; -+ -+ file = NULL; -+ sb = dentry->d_sb; -+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM); -+ if (unlikely(err)) -+ goto out_kfree; -+ -+ if (ia->ia_valid & ATTR_FILE) { -+ /* currently ftruncate(2) only */ -+ AuDebugOn(!d_is_reg(dentry)); -+ file = ia->ia_file; -+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1, -+ /*fi_lsc*/0); -+ if (unlikely(err)) -+ goto out_si; -+ ia->ia_file = au_hf_top(file); -+ a->udba = AuOpt_UDBA_NONE; -+ } else { -+ /* fchmod() doesn't pass ia_file */ -+ a->udba = au_opt_udba(sb); -+ di_write_lock_child(dentry); -+ /* no d_unlinked(), to set UDBA_NONE for root */ -+ if (d_unhashed(dentry)) -+ a->udba = AuOpt_UDBA_NONE; -+ if (a->udba != AuOpt_UDBA_NONE) { -+ AuDebugOn(IS_ROOT(dentry)); -+ err = au_reval_for_attr(dentry, au_sigen(sb)); -+ if (unlikely(err)) -+ goto out_dentry; -+ } -+ } -+ -+ err = au_pin_and_icpup(dentry, ia, a); -+ if (unlikely(err < 0)) -+ goto out_dentry; -+ if (au_ftest_icpup(a->flags, DID_CPUP)) { -+ ia->ia_file = NULL; -+ ia->ia_valid &= ~ATTR_FILE; -+ } -+ -+ a->h_path.mnt = au_sbr_mnt(sb, a->btgt); -+ if ((ia->ia_valid & (ATTR_MODE | ATTR_CTIME)) -+ == (ATTR_MODE | ATTR_CTIME)) { -+ err = security_path_chmod(&a->h_path, ia->ia_mode); -+ if (unlikely(err)) -+ goto out_unlock; -+ } else if ((ia->ia_valid & (ATTR_UID | ATTR_GID)) -+ && (ia->ia_valid & ATTR_CTIME)) { -+ err = security_path_chown(&a->h_path, ia->ia_uid, ia->ia_gid); -+ if (unlikely(err)) -+ goto out_unlock; -+ } -+ -+ if (ia->ia_valid & ATTR_SIZE) { -+ struct file *f; -+ -+ if (ia->ia_size < i_size_read(inode)) -+ /* unmap only */ -+ truncate_setsize(inode, ia->ia_size); -+ -+ f = NULL; -+ if (ia->ia_valid & ATTR_FILE) -+ f = ia->ia_file; -+ inode_unlock(a->h_inode); -+ err = vfsub_trunc(&a->h_path, ia->ia_size, ia->ia_valid, f); -+ inode_lock_nested(a->h_inode, AuLsc_I_CHILD); -+ } else { -+ delegated = NULL; -+ while (1) { -+ err = vfsub_notify_change(&a->h_path, ia, &delegated); -+ if (delegated) { -+ err = break_deleg_wait(&delegated); -+ if (!err) -+ continue; -+ } -+ break; -+ } -+ } -+ /* -+ * regardless aufs 'acl' option setting. -+ * why don't all acl-aware fs call this func from their ->setattr()? -+ */ -+ if (!err && (ia->ia_valid & ATTR_MODE)) -+ err = vfsub_acl_chmod(a->h_inode, ia->ia_mode); -+ if (!err) -+ au_cpup_attr_changeable(inode); -+ -+out_unlock: -+ inode_unlock(a->h_inode); -+ au_unpin(&a->pin); -+ if (unlikely(err)) -+ au_update_dbtop(dentry); -+out_dentry: -+ di_write_unlock(dentry); -+ if (file) { -+ fi_write_unlock(file); -+ ia->ia_file = file; -+ ia->ia_valid |= ATTR_FILE; -+ } -+out_si: -+ si_read_unlock(sb); -+out_kfree: -+ au_kfree_rcu(a); -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+#if IS_ENABLED(CONFIG_AUFS_XATTR) || IS_ENABLED(CONFIG_FS_POSIX_ACL) -+static int au_h_path_to_set_attr(struct dentry *dentry, -+ struct au_icpup_args *a, struct path *h_path) -+{ -+ int err; -+ struct super_block *sb; -+ -+ sb = dentry->d_sb; -+ a->udba = au_opt_udba(sb); -+ /* no d_unlinked(), to set UDBA_NONE for root */ -+ if (d_unhashed(dentry)) -+ a->udba = AuOpt_UDBA_NONE; -+ if (a->udba != AuOpt_UDBA_NONE) { -+ AuDebugOn(IS_ROOT(dentry)); -+ err = au_reval_for_attr(dentry, au_sigen(sb)); -+ if (unlikely(err)) -+ goto out; -+ } -+ err = au_pin_and_icpup(dentry, /*ia*/NULL, a); -+ if (unlikely(err < 0)) -+ goto out; -+ -+ h_path->dentry = a->h_path.dentry; -+ h_path->mnt = au_sbr_mnt(sb, a->btgt); -+ -+out: -+ return err; -+} -+ -+ssize_t au_sxattr(struct dentry *dentry, struct inode *inode, -+ struct au_sxattr *arg) -+{ -+ int err; -+ struct path h_path; -+ struct super_block *sb; -+ struct au_icpup_args *a; -+ struct inode *h_inode; -+ -+ IMustLock(inode); -+ -+ err = -ENOMEM; -+ a = kzalloc(sizeof(*a), GFP_NOFS); -+ if (unlikely(!a)) -+ goto out; -+ -+ sb = dentry->d_sb; -+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM); -+ if (unlikely(err)) -+ goto out_kfree; -+ -+ h_path.dentry = NULL; /* silence gcc */ -+ di_write_lock_child(dentry); -+ err = au_h_path_to_set_attr(dentry, a, &h_path); -+ if (unlikely(err)) -+ goto out_di; -+ -+ inode_unlock(a->h_inode); -+ switch (arg->type) { -+ case AU_XATTR_SET: -+ AuDebugOn(d_is_negative(h_path.dentry)); -+ err = vfsub_setxattr(h_path.dentry, -+ arg->u.set.name, arg->u.set.value, -+ arg->u.set.size, arg->u.set.flags); -+ break; -+ case AU_ACL_SET: -+ err = -EOPNOTSUPP; -+ h_inode = d_inode(h_path.dentry); -+ if (h_inode->i_op->set_acl) -+ /* this will call posix_acl_update_mode */ -+ err = h_inode->i_op->set_acl(h_inode, -+ arg->u.acl_set.acl, -+ arg->u.acl_set.type); -+ break; -+ } -+ if (!err) -+ au_cpup_attr_timesizes(inode); -+ -+ au_unpin(&a->pin); -+ if (unlikely(err)) -+ au_update_dbtop(dentry); -+ -+out_di: -+ di_write_unlock(dentry); -+ si_read_unlock(sb); -+out_kfree: -+ au_kfree_rcu(a); -+out: -+ AuTraceErr(err); -+ return err; -+} -+#endif -+ -+static void au_refresh_iattr(struct inode *inode, struct kstat *st, -+ unsigned int nlink) -+{ -+ unsigned int n; -+ -+ inode->i_mode = st->mode; -+ /* don't i_[ug]id_write() here */ -+ inode->i_uid = st->uid; -+ inode->i_gid = st->gid; -+ inode->i_atime = st->atime; -+ inode->i_mtime = st->mtime; -+ inode->i_ctime = st->ctime; -+ -+ au_cpup_attr_nlink(inode, /*force*/0); -+ if (S_ISDIR(inode->i_mode)) { -+ n = inode->i_nlink; -+ n -= nlink; -+ n += st->nlink; -+ smp_mb(); /* for i_nlink */ -+ /* 0 can happen */ -+ set_nlink(inode, n); -+ } -+ -+ spin_lock(&inode->i_lock); -+ inode->i_blocks = st->blocks; -+ i_size_write(inode, st->size); -+ spin_unlock(&inode->i_lock); -+} -+ -+/* -+ * common routine for aufs_getattr() and au_getxattr(). -+ * returns zero or negative (an error). -+ * @dentry will be read-locked in success. -+ */ -+int au_h_path_getattr(struct dentry *dentry, struct inode *inode, int force, -+ struct path *h_path, int locked) -+{ -+ int err; -+ unsigned int mnt_flags, sigen; -+ unsigned char udba_none; -+ aufs_bindex_t bindex; -+ struct super_block *sb, *h_sb; -+ -+ h_path->mnt = NULL; -+ h_path->dentry = NULL; -+ -+ err = 0; -+ sb = dentry->d_sb; -+ mnt_flags = au_mntflags(sb); -+ udba_none = !!au_opt_test(mnt_flags, UDBA_NONE); -+ -+ if (unlikely(locked)) -+ goto body; /* skip locking dinfo */ -+ -+ /* support fstat(2) */ -+ if (!d_unlinked(dentry) && !udba_none) { -+ sigen = au_sigen(sb); -+ err = au_digen_test(dentry, sigen); -+ if (!err) { -+ di_read_lock_child(dentry, AuLock_IR); -+ err = au_dbrange_test(dentry); -+ if (unlikely(err)) { -+ di_read_unlock(dentry, AuLock_IR); -+ goto out; -+ } -+ } else { -+ AuDebugOn(IS_ROOT(dentry)); -+ di_write_lock_child(dentry); -+ err = au_dbrange_test(dentry); -+ if (!err) -+ err = au_reval_for_attr(dentry, sigen); -+ if (!err) -+ di_downgrade_lock(dentry, AuLock_IR); -+ else { -+ di_write_unlock(dentry); -+ goto out; -+ } -+ } -+ } else -+ di_read_lock_child(dentry, AuLock_IR); -+ -+body: -+ if (!inode) { -+ inode = d_inode(dentry); -+ if (unlikely(!inode)) -+ goto out; -+ } -+ bindex = au_ibtop(inode); -+ h_path->mnt = au_sbr_mnt(sb, bindex); -+ h_sb = h_path->mnt->mnt_sb; -+ if (!force -+ && !au_test_fs_bad_iattr(h_sb) -+ && udba_none) -+ goto out; /* success */ -+ -+ if (au_dbtop(dentry) == bindex) -+ h_path->dentry = au_h_dptr(dentry, bindex); -+ else if (au_opt_test(mnt_flags, PLINK) && au_plink_test(inode)) { -+ h_path->dentry = au_plink_lkup(inode, bindex); -+ if (IS_ERR(h_path->dentry)) -+ /* pretending success */ -+ h_path->dentry = NULL; -+ else -+ dput(h_path->dentry); -+ } -+ -+out: -+ return err; -+} -+ -+static int aufs_getattr(const struct path *path, struct kstat *st, -+ u32 request, unsigned int query) -+{ -+ int err; -+ unsigned char positive; -+ struct path h_path; -+ struct dentry *dentry; -+ struct inode *inode; -+ struct super_block *sb; -+ -+ dentry = path->dentry; -+ inode = d_inode(dentry); -+ sb = dentry->d_sb; -+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM); -+ if (unlikely(err)) -+ goto out; -+ err = au_h_path_getattr(dentry, /*inode*/NULL, /*force*/0, &h_path, -+ /*locked*/0); -+ if (unlikely(err)) -+ goto out_si; -+ if (unlikely(!h_path.dentry)) -+ /* illegally overlapped or something */ -+ goto out_fill; /* pretending success */ -+ -+ positive = d_is_positive(h_path.dentry); -+ if (positive) -+ /* no vfsub version */ -+ err = vfs_getattr(&h_path, st, request, query); -+ if (!err) { -+ if (positive) -+ au_refresh_iattr(inode, st, -+ d_inode(h_path.dentry)->i_nlink); -+ goto out_fill; /* success */ -+ } -+ AuTraceErr(err); -+ goto out_di; -+ -+out_fill: -+ generic_fillattr(inode, st); -+out_di: -+ di_read_unlock(dentry, AuLock_IR); -+out_si: -+ si_read_unlock(sb); -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static const char *aufs_get_link(struct dentry *dentry, struct inode *inode, -+ struct delayed_call *done) -+{ -+ const char *ret; -+ struct dentry *h_dentry; -+ struct inode *h_inode; -+ int err; -+ aufs_bindex_t bindex; -+ -+ ret = NULL; /* suppress a warning */ -+ err = -ECHILD; -+ if (!dentry) -+ goto out; -+ -+ err = aufs_read_lock(dentry, AuLock_IR | AuLock_GEN); -+ if (unlikely(err)) -+ goto out; -+ -+ err = au_d_hashed_positive(dentry); -+ if (unlikely(err)) -+ goto out_unlock; -+ -+ err = -EINVAL; -+ inode = d_inode(dentry); -+ bindex = au_ibtop(inode); -+ h_inode = au_h_iptr(inode, bindex); -+ if (unlikely(!h_inode->i_op->get_link)) -+ goto out_unlock; -+ -+ err = -EBUSY; -+ h_dentry = NULL; -+ if (au_dbtop(dentry) <= bindex) { -+ h_dentry = au_h_dptr(dentry, bindex); -+ if (h_dentry) -+ dget(h_dentry); -+ } -+ if (!h_dentry) { -+ h_dentry = d_find_any_alias(h_inode); -+ if (IS_ERR(h_dentry)) { -+ err = PTR_ERR(h_dentry); -+ goto out_unlock; -+ } -+ } -+ if (unlikely(!h_dentry)) -+ goto out_unlock; -+ -+ err = 0; -+ AuDbg("%ps\n", h_inode->i_op->get_link); -+ AuDbgDentry(h_dentry); -+ ret = vfs_get_link(h_dentry, done); -+ dput(h_dentry); -+ if (IS_ERR(ret)) -+ err = PTR_ERR(ret); -+ -+out_unlock: -+ aufs_read_unlock(dentry, AuLock_IR); -+out: -+ if (unlikely(err)) -+ ret = ERR_PTR(err); -+ AuTraceErrPtr(ret); -+ return ret; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int au_is_special(struct inode *inode) -+{ -+ return (inode->i_mode & (S_IFBLK | S_IFCHR | S_IFIFO | S_IFSOCK)); -+} -+ -+static int aufs_update_time(struct inode *inode, struct timespec64 *ts, -+ int flags) -+{ -+ int err; -+ aufs_bindex_t bindex; -+ struct super_block *sb; -+ struct inode *h_inode; -+ struct vfsmount *h_mnt; -+ -+ sb = inode->i_sb; -+ WARN_ONCE((flags & S_ATIME) && !IS_NOATIME(inode), -+ "unexpected s_flags 0x%lx", sb->s_flags); -+ -+ /* mmap_sem might be acquired already, cf. aufs_mmap() */ -+ lockdep_off(); -+ si_read_lock(sb, AuLock_FLUSH); -+ ii_write_lock_child(inode); -+ -+ err = 0; -+ bindex = au_ibtop(inode); -+ h_inode = au_h_iptr(inode, bindex); -+ if (!au_test_ro(sb, bindex, inode)) { -+ h_mnt = au_sbr_mnt(sb, bindex); -+ err = vfsub_mnt_want_write(h_mnt); -+ if (!err) { -+ err = vfsub_update_time(h_inode, ts, flags); -+ vfsub_mnt_drop_write(h_mnt); -+ } -+ } else if (au_is_special(h_inode)) { -+ /* -+ * Never copy-up here. -+ * These special files may already be opened and used for -+ * communicating. If we copied it up, then the communication -+ * would be corrupted. -+ */ -+ AuWarn1("timestamps for i%lu are ignored " -+ "since it is on readonly branch (hi%lu).\n", -+ inode->i_ino, h_inode->i_ino); -+ } else if (flags & ~S_ATIME) { -+ err = -EIO; -+ AuIOErr1("unexpected flags 0x%x\n", flags); -+ AuDebugOn(1); -+ } -+ -+ if (!err) -+ au_cpup_attr_timesizes(inode); -+ ii_write_unlock(inode); -+ si_read_unlock(sb); -+ lockdep_on(); -+ -+ if (!err && (flags & S_VERSION)) -+ inode_inc_iversion(inode); -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* no getattr version will be set by module.c:aufs_init() */ -+struct inode_operations aufs_iop_nogetattr[AuIop_Last], -+ aufs_iop[] = { -+ [AuIop_SYMLINK] = { -+ .permission = aufs_permission, -+#ifdef CONFIG_FS_POSIX_ACL -+ .get_acl = aufs_get_acl, -+ .set_acl = aufs_set_acl, /* unsupport for symlink? */ -+#endif -+ -+ .setattr = aufs_setattr, -+ .getattr = aufs_getattr, -+ -+#ifdef CONFIG_AUFS_XATTR -+ .listxattr = aufs_listxattr, -+#endif -+ -+ .get_link = aufs_get_link, -+ -+ /* .update_time = aufs_update_time */ -+ }, -+ [AuIop_DIR] = { -+ .create = aufs_create, -+ .lookup = aufs_lookup, -+ .link = aufs_link, -+ .unlink = aufs_unlink, -+ .symlink = aufs_symlink, -+ .mkdir = aufs_mkdir, -+ .rmdir = aufs_rmdir, -+ .mknod = aufs_mknod, -+ .rename = aufs_rename, -+ -+ .permission = aufs_permission, -+#ifdef CONFIG_FS_POSIX_ACL -+ .get_acl = aufs_get_acl, -+ .set_acl = aufs_set_acl, -+#endif -+ -+ .setattr = aufs_setattr, -+ .getattr = aufs_getattr, -+ -+#ifdef CONFIG_AUFS_XATTR -+ .listxattr = aufs_listxattr, -+#endif -+ -+ .update_time = aufs_update_time, -+ .atomic_open = aufs_atomic_open, -+ .tmpfile = aufs_tmpfile -+ }, -+ [AuIop_OTHER] = { -+ .permission = aufs_permission, -+#ifdef CONFIG_FS_POSIX_ACL -+ .get_acl = aufs_get_acl, -+ .set_acl = aufs_set_acl, -+#endif -+ -+ .setattr = aufs_setattr, -+ .getattr = aufs_getattr, -+ -+#ifdef CONFIG_AUFS_XATTR -+ .listxattr = aufs_listxattr, -+#endif -+ -+ .update_time = aufs_update_time -+ } -+}; -diff --git a/fs/aufs/i_op_add.c b/fs/aufs/i_op_add.c -new file mode 100644 -index 000000000000..853c99e200da ---- /dev/null -+++ b/fs/aufs/i_op_add.c -@@ -0,0 +1,923 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * inode operations (add entry) -+ */ -+ -+#include -+#include "aufs.h" -+ -+/* -+ * final procedure of adding a new entry, except link(2). -+ * remove whiteout, instantiate, copyup the parent dir's times and size -+ * and update version. -+ * if it failed, re-create the removed whiteout. -+ */ -+static int epilog(struct inode *dir, aufs_bindex_t bindex, -+ struct dentry *wh_dentry, struct dentry *dentry) -+{ -+ int err, rerr; -+ aufs_bindex_t bwh; -+ struct path h_path; -+ struct super_block *sb; -+ struct inode *inode, *h_dir; -+ struct dentry *wh; -+ -+ bwh = -1; -+ sb = dir->i_sb; -+ if (wh_dentry) { -+ h_dir = d_inode(wh_dentry->d_parent); /* dir inode is locked */ -+ IMustLock(h_dir); -+ AuDebugOn(au_h_iptr(dir, bindex) != h_dir); -+ bwh = au_dbwh(dentry); -+ h_path.dentry = wh_dentry; -+ h_path.mnt = au_sbr_mnt(sb, bindex); -+ err = au_wh_unlink_dentry(au_h_iptr(dir, bindex), &h_path, -+ dentry); -+ if (unlikely(err)) -+ goto out; -+ } -+ -+ inode = au_new_inode(dentry, /*must_new*/1); -+ if (!IS_ERR(inode)) { -+ d_instantiate(dentry, inode); -+ dir = d_inode(dentry->d_parent); /* dir inode is locked */ -+ IMustLock(dir); -+ au_dir_ts(dir, bindex); -+ inode_inc_iversion(dir); -+ au_fhsm_wrote(sb, bindex, /*force*/0); -+ return 0; /* success */ -+ } -+ -+ err = PTR_ERR(inode); -+ if (!wh_dentry) -+ goto out; -+ -+ /* revert */ -+ /* dir inode is locked */ -+ wh = au_wh_create(dentry, bwh, wh_dentry->d_parent); -+ rerr = PTR_ERR(wh); -+ if (IS_ERR(wh)) { -+ AuIOErr("%pd reverting whiteout failed(%d, %d)\n", -+ dentry, err, rerr); -+ err = -EIO; -+ } else -+ dput(wh); -+ -+out: -+ return err; -+} -+ -+static int au_d_may_add(struct dentry *dentry) -+{ -+ int err; -+ -+ err = 0; -+ if (unlikely(d_unhashed(dentry))) -+ err = -ENOENT; -+ if (unlikely(d_really_is_positive(dentry))) -+ err = -EEXIST; -+ return err; -+} -+ -+/* -+ * simple tests for the adding inode operations. -+ * following the checks in vfs, plus the parent-child relationship. -+ */ -+int au_may_add(struct dentry *dentry, aufs_bindex_t bindex, -+ struct dentry *h_parent, int isdir) -+{ -+ int err; -+ umode_t h_mode; -+ struct dentry *h_dentry; -+ struct inode *h_inode; -+ -+ err = -ENAMETOOLONG; -+ if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN)) -+ goto out; -+ -+ h_dentry = au_h_dptr(dentry, bindex); -+ if (d_really_is_negative(dentry)) { -+ err = -EEXIST; -+ if (unlikely(d_is_positive(h_dentry))) -+ goto out; -+ } else { -+ /* rename(2) case */ -+ err = -EIO; -+ if (unlikely(d_is_negative(h_dentry))) -+ goto out; -+ h_inode = d_inode(h_dentry); -+ if (unlikely(!h_inode->i_nlink)) -+ goto out; -+ -+ h_mode = h_inode->i_mode; -+ if (!isdir) { -+ err = -EISDIR; -+ if (unlikely(S_ISDIR(h_mode))) -+ goto out; -+ } else if (unlikely(!S_ISDIR(h_mode))) { -+ err = -ENOTDIR; -+ goto out; -+ } -+ } -+ -+ err = 0; -+ /* expected parent dir is locked */ -+ if (unlikely(h_parent != h_dentry->d_parent)) -+ err = -EIO; -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+/* -+ * initial procedure of adding a new entry. -+ * prepare writable branch and the parent dir, lock it, -+ * and lookup whiteout for the new entry. -+ */ -+static struct dentry* -+lock_hdir_lkup_wh(struct dentry *dentry, struct au_dtime *dt, -+ struct dentry *src_dentry, struct au_pin *pin, -+ struct au_wr_dir_args *wr_dir_args) -+{ -+ struct dentry *wh_dentry, *h_parent; -+ struct super_block *sb; -+ struct au_branch *br; -+ int err; -+ unsigned int udba; -+ aufs_bindex_t bcpup; -+ -+ AuDbg("%pd\n", dentry); -+ -+ err = au_wr_dir(dentry, src_dentry, wr_dir_args); -+ bcpup = err; -+ wh_dentry = ERR_PTR(err); -+ if (unlikely(err < 0)) -+ goto out; -+ -+ sb = dentry->d_sb; -+ udba = au_opt_udba(sb); -+ err = au_pin(pin, dentry, bcpup, udba, -+ AuPin_DI_LOCKED | AuPin_MNT_WRITE); -+ wh_dentry = ERR_PTR(err); -+ if (unlikely(err)) -+ goto out; -+ -+ h_parent = au_pinned_h_parent(pin); -+ if (udba != AuOpt_UDBA_NONE -+ && au_dbtop(dentry) == bcpup) -+ err = au_may_add(dentry, bcpup, h_parent, -+ au_ftest_wrdir(wr_dir_args->flags, ISDIR)); -+ else if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN)) -+ err = -ENAMETOOLONG; -+ wh_dentry = ERR_PTR(err); -+ if (unlikely(err)) -+ goto out_unpin; -+ -+ br = au_sbr(sb, bcpup); -+ if (dt) { -+ struct path tmp = { -+ .dentry = h_parent, -+ .mnt = au_br_mnt(br) -+ }; -+ au_dtime_store(dt, au_pinned_parent(pin), &tmp); -+ } -+ -+ wh_dentry = NULL; -+ if (bcpup != au_dbwh(dentry)) -+ goto out; /* success */ -+ -+ /* -+ * ENAMETOOLONG here means that if we allowed create such name, then it -+ * would not be able to removed in the future. So we don't allow such -+ * name here and we don't handle ENAMETOOLONG differently here. -+ */ -+ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, br); -+ -+out_unpin: -+ if (IS_ERR(wh_dentry)) -+ au_unpin(pin); -+out: -+ return wh_dentry; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+enum { Mknod, Symlink, Creat }; -+struct simple_arg { -+ int type; -+ union { -+ struct { -+ umode_t mode; -+ bool want_excl; -+ bool try_aopen; -+ struct vfsub_aopen_args *aopen; -+ } c; -+ struct { -+ const char *symname; -+ } s; -+ struct { -+ umode_t mode; -+ dev_t dev; -+ } m; -+ } u; -+}; -+ -+static int add_simple(struct inode *dir, struct dentry *dentry, -+ struct simple_arg *arg) -+{ -+ int err, rerr; -+ aufs_bindex_t btop; -+ unsigned char created; -+ const unsigned char try_aopen -+ = (arg->type == Creat && arg->u.c.try_aopen); -+ struct vfsub_aopen_args *aopen = arg->u.c.aopen; -+ struct dentry *wh_dentry, *parent; -+ struct inode *h_dir; -+ struct super_block *sb; -+ struct au_branch *br; -+ /* to reduce stack size */ -+ struct { -+ struct au_dtime dt; -+ struct au_pin pin; -+ struct path h_path; -+ struct au_wr_dir_args wr_dir_args; -+ } *a; -+ -+ AuDbg("%pd\n", dentry); -+ IMustLock(dir); -+ -+ err = -ENOMEM; -+ a = kmalloc(sizeof(*a), GFP_NOFS); -+ if (unlikely(!a)) -+ goto out; -+ a->wr_dir_args.force_btgt = -1; -+ a->wr_dir_args.flags = AuWrDir_ADD_ENTRY; -+ -+ parent = dentry->d_parent; /* dir inode is locked */ -+ if (!try_aopen) { -+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN); -+ if (unlikely(err)) -+ goto out_free; -+ } -+ err = au_d_may_add(dentry); -+ if (unlikely(err)) -+ goto out_unlock; -+ if (!try_aopen) -+ di_write_lock_parent(parent); -+ wh_dentry = lock_hdir_lkup_wh(dentry, &a->dt, /*src_dentry*/NULL, -+ &a->pin, &a->wr_dir_args); -+ err = PTR_ERR(wh_dentry); -+ if (IS_ERR(wh_dentry)) -+ goto out_parent; -+ -+ btop = au_dbtop(dentry); -+ sb = dentry->d_sb; -+ br = au_sbr(sb, btop); -+ a->h_path.dentry = au_h_dptr(dentry, btop); -+ a->h_path.mnt = au_br_mnt(br); -+ h_dir = au_pinned_h_dir(&a->pin); -+ switch (arg->type) { -+ case Creat: -+ if (!try_aopen || !h_dir->i_op->atomic_open) { -+ err = vfsub_create(h_dir, &a->h_path, arg->u.c.mode, -+ arg->u.c.want_excl); -+ created = !err; -+ if (!err && try_aopen) -+ aopen->file->f_mode |= FMODE_CREATED; -+ } else { -+ aopen->br = br; -+ err = vfsub_atomic_open(h_dir, a->h_path.dentry, aopen); -+ AuDbg("err %d\n", err); -+ AuDbgFile(aopen->file); -+ created = err >= 0 -+ && !!(aopen->file->f_mode & FMODE_CREATED); -+ } -+ break; -+ case Symlink: -+ err = vfsub_symlink(h_dir, &a->h_path, arg->u.s.symname); -+ created = !err; -+ break; -+ case Mknod: -+ err = vfsub_mknod(h_dir, &a->h_path, arg->u.m.mode, -+ arg->u.m.dev); -+ created = !err; -+ break; -+ default: -+ BUG(); -+ } -+ if (unlikely(err < 0)) -+ goto out_unpin; -+ -+ err = epilog(dir, btop, wh_dentry, dentry); -+ if (!err) -+ goto out_unpin; /* success */ -+ -+ /* revert */ -+ if (created /* && d_is_positive(a->h_path.dentry) */) { -+ /* no delegation since it is just created */ -+ rerr = vfsub_unlink(h_dir, &a->h_path, /*delegated*/NULL, -+ /*force*/0); -+ if (rerr) { -+ AuIOErr("%pd revert failure(%d, %d)\n", -+ dentry, err, rerr); -+ err = -EIO; -+ } -+ au_dtime_revert(&a->dt); -+ } -+ if (try_aopen && h_dir->i_op->atomic_open -+ && (aopen->file->f_mode & FMODE_OPENED)) -+ /* aopen->file is still opened */ -+ au_lcnt_dec(&aopen->br->br_nfiles); -+ -+out_unpin: -+ au_unpin(&a->pin); -+ dput(wh_dentry); -+out_parent: -+ if (!try_aopen) -+ di_write_unlock(parent); -+out_unlock: -+ if (unlikely(err)) { -+ au_update_dbtop(dentry); -+ d_drop(dentry); -+ } -+ if (!try_aopen) -+ aufs_read_unlock(dentry, AuLock_DW); -+out_free: -+ au_kfree_rcu(a); -+out: -+ return err; -+} -+ -+int aufs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, -+ dev_t dev) -+{ -+ struct simple_arg arg = { -+ .type = Mknod, -+ .u.m = { -+ .mode = mode, -+ .dev = dev -+ } -+ }; -+ return add_simple(dir, dentry, &arg); -+} -+ -+int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) -+{ -+ struct simple_arg arg = { -+ .type = Symlink, -+ .u.s.symname = symname -+ }; -+ return add_simple(dir, dentry, &arg); -+} -+ -+int aufs_create(struct inode *dir, struct dentry *dentry, umode_t mode, -+ bool want_excl) -+{ -+ struct simple_arg arg = { -+ .type = Creat, -+ .u.c = { -+ .mode = mode, -+ .want_excl = want_excl -+ } -+ }; -+ return add_simple(dir, dentry, &arg); -+} -+ -+int au_aopen_or_create(struct inode *dir, struct dentry *dentry, -+ struct vfsub_aopen_args *aopen_args) -+{ -+ struct simple_arg arg = { -+ .type = Creat, -+ .u.c = { -+ .mode = aopen_args->create_mode, -+ .want_excl = aopen_args->open_flag & O_EXCL, -+ .try_aopen = true, -+ .aopen = aopen_args -+ } -+ }; -+ return add_simple(dir, dentry, &arg); -+} -+ -+int aufs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode) -+{ -+ int err; -+ aufs_bindex_t bindex; -+ struct super_block *sb; -+ struct dentry *parent, *h_parent, *h_dentry; -+ struct inode *h_dir, *inode; -+ struct vfsmount *h_mnt; -+ struct au_wr_dir_args wr_dir_args = { -+ .force_btgt = -1, -+ .flags = AuWrDir_TMPFILE -+ }; -+ -+ /* copy-up may happen */ -+ inode_lock(dir); -+ -+ sb = dir->i_sb; -+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM); -+ if (unlikely(err)) -+ goto out; -+ -+ err = au_di_init(dentry); -+ if (unlikely(err)) -+ goto out_si; -+ -+ err = -EBUSY; -+ parent = d_find_any_alias(dir); -+ AuDebugOn(!parent); -+ di_write_lock_parent(parent); -+ if (unlikely(d_inode(parent) != dir)) -+ goto out_parent; -+ -+ err = au_digen_test(parent, au_sigen(sb)); -+ if (unlikely(err)) -+ goto out_parent; -+ -+ bindex = au_dbtop(parent); -+ au_set_dbtop(dentry, bindex); -+ au_set_dbbot(dentry, bindex); -+ err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args); -+ bindex = err; -+ if (unlikely(err < 0)) -+ goto out_parent; -+ -+ err = -EOPNOTSUPP; -+ h_dir = au_h_iptr(dir, bindex); -+ if (unlikely(!h_dir->i_op->tmpfile)) -+ goto out_parent; -+ -+ h_mnt = au_sbr_mnt(sb, bindex); -+ err = vfsub_mnt_want_write(h_mnt); -+ if (unlikely(err)) -+ goto out_parent; -+ -+ h_parent = au_h_dptr(parent, bindex); -+ h_dentry = vfs_tmpfile(h_parent, mode, /*open_flag*/0); -+ if (IS_ERR(h_dentry)) { -+ err = PTR_ERR(h_dentry); -+ goto out_mnt; -+ } -+ -+ au_set_dbtop(dentry, bindex); -+ au_set_dbbot(dentry, bindex); -+ au_set_h_dptr(dentry, bindex, dget(h_dentry)); -+ inode = au_new_inode(dentry, /*must_new*/1); -+ if (IS_ERR(inode)) { -+ err = PTR_ERR(inode); -+ au_set_h_dptr(dentry, bindex, NULL); -+ au_set_dbtop(dentry, -1); -+ au_set_dbbot(dentry, -1); -+ } else { -+ if (!inode->i_nlink) -+ set_nlink(inode, 1); -+ d_tmpfile(dentry, inode); -+ au_di(dentry)->di_tmpfile = 1; -+ -+ /* update without i_mutex */ -+ if (au_ibtop(dir) == au_dbtop(dentry)) -+ au_cpup_attr_timesizes(dir); -+ } -+ dput(h_dentry); -+ -+out_mnt: -+ vfsub_mnt_drop_write(h_mnt); -+out_parent: -+ di_write_unlock(parent); -+ dput(parent); -+ di_write_unlock(dentry); -+ if (unlikely(err)) { -+ au_di_fin(dentry); -+ dentry->d_fsdata = NULL; -+ } -+out_si: -+ si_read_unlock(sb); -+out: -+ inode_unlock(dir); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct au_link_args { -+ aufs_bindex_t bdst, bsrc; -+ struct au_pin pin; -+ struct path h_path; -+ struct dentry *src_parent, *parent; -+}; -+ -+static int au_cpup_before_link(struct dentry *src_dentry, -+ struct au_link_args *a) -+{ -+ int err; -+ struct dentry *h_src_dentry; -+ struct au_cp_generic cpg = { -+ .dentry = src_dentry, -+ .bdst = a->bdst, -+ .bsrc = a->bsrc, -+ .len = -1, -+ .pin = &a->pin, -+ .flags = AuCpup_DTIME | AuCpup_HOPEN /* | AuCpup_KEEPLINO */ -+ }; -+ -+ di_read_lock_parent(a->src_parent, AuLock_IR); -+ err = au_test_and_cpup_dirs(src_dentry, a->bdst); -+ if (unlikely(err)) -+ goto out; -+ -+ h_src_dentry = au_h_dptr(src_dentry, a->bsrc); -+ err = au_pin(&a->pin, src_dentry, a->bdst, -+ au_opt_udba(src_dentry->d_sb), -+ AuPin_DI_LOCKED | AuPin_MNT_WRITE); -+ if (unlikely(err)) -+ goto out; -+ -+ err = au_sio_cpup_simple(&cpg); -+ au_unpin(&a->pin); -+ -+out: -+ di_read_unlock(a->src_parent, AuLock_IR); -+ return err; -+} -+ -+static int au_cpup_or_link(struct dentry *src_dentry, struct dentry *dentry, -+ struct au_link_args *a) -+{ -+ int err; -+ unsigned char plink; -+ aufs_bindex_t bbot; -+ struct dentry *h_src_dentry; -+ struct inode *h_inode, *inode, *delegated; -+ struct super_block *sb; -+ struct file *h_file; -+ -+ plink = 0; -+ h_inode = NULL; -+ sb = src_dentry->d_sb; -+ inode = d_inode(src_dentry); -+ if (au_ibtop(inode) <= a->bdst) -+ h_inode = au_h_iptr(inode, a->bdst); -+ if (!h_inode || !h_inode->i_nlink) { -+ /* copyup src_dentry as the name of dentry. */ -+ bbot = au_dbbot(dentry); -+ if (bbot < a->bsrc) -+ au_set_dbbot(dentry, a->bsrc); -+ au_set_h_dptr(dentry, a->bsrc, -+ dget(au_h_dptr(src_dentry, a->bsrc))); -+ dget(a->h_path.dentry); -+ au_set_h_dptr(dentry, a->bdst, NULL); -+ AuDbg("temporary d_inode...\n"); -+ spin_lock(&dentry->d_lock); -+ dentry->d_inode = d_inode(src_dentry); /* tmp */ -+ spin_unlock(&dentry->d_lock); -+ h_file = au_h_open_pre(dentry, a->bsrc, /*force_wr*/0); -+ if (IS_ERR(h_file)) -+ err = PTR_ERR(h_file); -+ else { -+ struct au_cp_generic cpg = { -+ .dentry = dentry, -+ .bdst = a->bdst, -+ .bsrc = -1, -+ .len = -1, -+ .pin = &a->pin, -+ .flags = AuCpup_KEEPLINO -+ }; -+ err = au_sio_cpup_simple(&cpg); -+ au_h_open_post(dentry, a->bsrc, h_file); -+ if (!err) { -+ dput(a->h_path.dentry); -+ a->h_path.dentry = au_h_dptr(dentry, a->bdst); -+ } else -+ au_set_h_dptr(dentry, a->bdst, -+ a->h_path.dentry); -+ } -+ spin_lock(&dentry->d_lock); -+ dentry->d_inode = NULL; /* restore */ -+ spin_unlock(&dentry->d_lock); -+ AuDbg("temporary d_inode...done\n"); -+ au_set_h_dptr(dentry, a->bsrc, NULL); -+ au_set_dbbot(dentry, bbot); -+ } else { -+ /* the inode of src_dentry already exists on a.bdst branch */ -+ h_src_dentry = d_find_alias(h_inode); -+ if (!h_src_dentry && au_plink_test(inode)) { -+ plink = 1; -+ h_src_dentry = au_plink_lkup(inode, a->bdst); -+ err = PTR_ERR(h_src_dentry); -+ if (IS_ERR(h_src_dentry)) -+ goto out; -+ -+ if (unlikely(d_is_negative(h_src_dentry))) { -+ dput(h_src_dentry); -+ h_src_dentry = NULL; -+ } -+ -+ } -+ if (h_src_dentry) { -+ delegated = NULL; -+ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin), -+ &a->h_path, &delegated); -+ if (unlikely(err == -EWOULDBLOCK)) { -+ pr_warn("cannot retry for NFSv4 delegation" -+ " for an internal link\n"); -+ iput(delegated); -+ } -+ dput(h_src_dentry); -+ } else { -+ AuIOErr("no dentry found for hi%lu on b%d\n", -+ h_inode->i_ino, a->bdst); -+ err = -EIO; -+ } -+ } -+ -+ if (!err && !plink) -+ au_plink_append(inode, a->bdst, a->h_path.dentry); -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+int aufs_link(struct dentry *src_dentry, struct inode *dir, -+ struct dentry *dentry) -+{ -+ int err, rerr; -+ struct au_dtime dt; -+ struct au_link_args *a; -+ struct dentry *wh_dentry, *h_src_dentry; -+ struct inode *inode, *delegated; -+ struct super_block *sb; -+ struct au_wr_dir_args wr_dir_args = { -+ /* .force_btgt = -1, */ -+ .flags = AuWrDir_ADD_ENTRY -+ }; -+ -+ IMustLock(dir); -+ inode = d_inode(src_dentry); -+ IMustLock(inode); -+ -+ err = -ENOMEM; -+ a = kzalloc(sizeof(*a), GFP_NOFS); -+ if (unlikely(!a)) -+ goto out; -+ -+ a->parent = dentry->d_parent; /* dir inode is locked */ -+ err = aufs_read_and_write_lock2(dentry, src_dentry, -+ AuLock_NOPLM | AuLock_GEN); -+ if (unlikely(err)) -+ goto out_kfree; -+ err = au_d_linkable(src_dentry); -+ if (unlikely(err)) -+ goto out_unlock; -+ err = au_d_may_add(dentry); -+ if (unlikely(err)) -+ goto out_unlock; -+ -+ a->src_parent = dget_parent(src_dentry); -+ wr_dir_args.force_btgt = au_ibtop(inode); -+ -+ di_write_lock_parent(a->parent); -+ wr_dir_args.force_btgt = au_wbr(dentry, wr_dir_args.force_btgt); -+ wh_dentry = lock_hdir_lkup_wh(dentry, &dt, src_dentry, &a->pin, -+ &wr_dir_args); -+ err = PTR_ERR(wh_dentry); -+ if (IS_ERR(wh_dentry)) -+ goto out_parent; -+ -+ err = 0; -+ sb = dentry->d_sb; -+ a->bdst = au_dbtop(dentry); -+ a->h_path.dentry = au_h_dptr(dentry, a->bdst); -+ a->h_path.mnt = au_sbr_mnt(sb, a->bdst); -+ a->bsrc = au_ibtop(inode); -+ h_src_dentry = au_h_d_alias(src_dentry, a->bsrc); -+ if (!h_src_dentry && au_di(src_dentry)->di_tmpfile) -+ h_src_dentry = dget(au_hi_wh(inode, a->bsrc)); -+ if (!h_src_dentry) { -+ a->bsrc = au_dbtop(src_dentry); -+ h_src_dentry = au_h_d_alias(src_dentry, a->bsrc); -+ AuDebugOn(!h_src_dentry); -+ } else if (IS_ERR(h_src_dentry)) { -+ err = PTR_ERR(h_src_dentry); -+ goto out_parent; -+ } -+ -+ /* -+ * aufs doesn't touch the credential so -+ * security_dentry_create_files_as() is unnecessary. -+ */ -+ if (au_opt_test(au_mntflags(sb), PLINK)) { -+ if (a->bdst < a->bsrc -+ /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */) -+ err = au_cpup_or_link(src_dentry, dentry, a); -+ else { -+ delegated = NULL; -+ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin), -+ &a->h_path, &delegated); -+ if (unlikely(err == -EWOULDBLOCK)) { -+ pr_warn("cannot retry for NFSv4 delegation" -+ " for an internal link\n"); -+ iput(delegated); -+ } -+ } -+ dput(h_src_dentry); -+ } else { -+ /* -+ * copyup src_dentry to the branch we process, -+ * and then link(2) to it. -+ */ -+ dput(h_src_dentry); -+ if (a->bdst < a->bsrc -+ /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */) { -+ au_unpin(&a->pin); -+ di_write_unlock(a->parent); -+ err = au_cpup_before_link(src_dentry, a); -+ di_write_lock_parent(a->parent); -+ if (!err) -+ err = au_pin(&a->pin, dentry, a->bdst, -+ au_opt_udba(sb), -+ AuPin_DI_LOCKED | AuPin_MNT_WRITE); -+ if (unlikely(err)) -+ goto out_wh; -+ } -+ if (!err) { -+ h_src_dentry = au_h_dptr(src_dentry, a->bdst); -+ err = -ENOENT; -+ if (h_src_dentry && d_is_positive(h_src_dentry)) { -+ delegated = NULL; -+ err = vfsub_link(h_src_dentry, -+ au_pinned_h_dir(&a->pin), -+ &a->h_path, &delegated); -+ if (unlikely(err == -EWOULDBLOCK)) { -+ pr_warn("cannot retry" -+ " for NFSv4 delegation" -+ " for an internal link\n"); -+ iput(delegated); -+ } -+ } -+ } -+ } -+ if (unlikely(err)) -+ goto out_unpin; -+ -+ if (wh_dentry) { -+ a->h_path.dentry = wh_dentry; -+ err = au_wh_unlink_dentry(au_pinned_h_dir(&a->pin), &a->h_path, -+ dentry); -+ if (unlikely(err)) -+ goto out_revert; -+ } -+ -+ au_dir_ts(dir, a->bdst); -+ inode_inc_iversion(dir); -+ inc_nlink(inode); -+ inode->i_ctime = dir->i_ctime; -+ d_instantiate(dentry, au_igrab(inode)); -+ if (d_unhashed(a->h_path.dentry)) -+ /* some filesystem calls d_drop() */ -+ d_drop(dentry); -+ /* some filesystems consume an inode even hardlink */ -+ au_fhsm_wrote(sb, a->bdst, /*force*/0); -+ goto out_unpin; /* success */ -+ -+out_revert: -+ /* no delegation since it is just created */ -+ rerr = vfsub_unlink(au_pinned_h_dir(&a->pin), &a->h_path, -+ /*delegated*/NULL, /*force*/0); -+ if (unlikely(rerr)) { -+ AuIOErr("%pd reverting failed(%d, %d)\n", dentry, err, rerr); -+ err = -EIO; -+ } -+ au_dtime_revert(&dt); -+out_unpin: -+ au_unpin(&a->pin); -+out_wh: -+ dput(wh_dentry); -+out_parent: -+ di_write_unlock(a->parent); -+ dput(a->src_parent); -+out_unlock: -+ if (unlikely(err)) { -+ au_update_dbtop(dentry); -+ d_drop(dentry); -+ } -+ aufs_read_and_write_unlock2(dentry, src_dentry); -+out_kfree: -+ au_kfree_rcu(a); -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+int aufs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) -+{ -+ int err, rerr; -+ aufs_bindex_t bindex; -+ unsigned char diropq; -+ struct path h_path; -+ struct dentry *wh_dentry, *parent, *opq_dentry; -+ struct inode *h_inode; -+ struct super_block *sb; -+ struct { -+ struct au_pin pin; -+ struct au_dtime dt; -+ } *a; /* reduce the stack usage */ -+ struct au_wr_dir_args wr_dir_args = { -+ .force_btgt = -1, -+ .flags = AuWrDir_ADD_ENTRY | AuWrDir_ISDIR -+ }; -+ -+ IMustLock(dir); -+ -+ err = -ENOMEM; -+ a = kmalloc(sizeof(*a), GFP_NOFS); -+ if (unlikely(!a)) -+ goto out; -+ -+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN); -+ if (unlikely(err)) -+ goto out_free; -+ err = au_d_may_add(dentry); -+ if (unlikely(err)) -+ goto out_unlock; -+ -+ parent = dentry->d_parent; /* dir inode is locked */ -+ di_write_lock_parent(parent); -+ wh_dentry = lock_hdir_lkup_wh(dentry, &a->dt, /*src_dentry*/NULL, -+ &a->pin, &wr_dir_args); -+ err = PTR_ERR(wh_dentry); -+ if (IS_ERR(wh_dentry)) -+ goto out_parent; -+ -+ sb = dentry->d_sb; -+ bindex = au_dbtop(dentry); -+ h_path.dentry = au_h_dptr(dentry, bindex); -+ h_path.mnt = au_sbr_mnt(sb, bindex); -+ err = vfsub_mkdir(au_pinned_h_dir(&a->pin), &h_path, mode); -+ if (unlikely(err)) -+ goto out_unpin; -+ -+ /* make the dir opaque */ -+ diropq = 0; -+ h_inode = d_inode(h_path.dentry); -+ if (wh_dentry -+ || au_opt_test(au_mntflags(sb), ALWAYS_DIROPQ)) { -+ inode_lock_nested(h_inode, AuLsc_I_CHILD); -+ opq_dentry = au_diropq_create(dentry, bindex); -+ inode_unlock(h_inode); -+ err = PTR_ERR(opq_dentry); -+ if (IS_ERR(opq_dentry)) -+ goto out_dir; -+ dput(opq_dentry); -+ diropq = 1; -+ } -+ -+ err = epilog(dir, bindex, wh_dentry, dentry); -+ if (!err) { -+ inc_nlink(dir); -+ goto out_unpin; /* success */ -+ } -+ -+ /* revert */ -+ if (diropq) { -+ AuLabel(revert opq); -+ inode_lock_nested(h_inode, AuLsc_I_CHILD); -+ rerr = au_diropq_remove(dentry, bindex); -+ inode_unlock(h_inode); -+ if (rerr) { -+ AuIOErr("%pd reverting diropq failed(%d, %d)\n", -+ dentry, err, rerr); -+ err = -EIO; -+ } -+ } -+ -+out_dir: -+ AuLabel(revert dir); -+ rerr = vfsub_rmdir(au_pinned_h_dir(&a->pin), &h_path); -+ if (rerr) { -+ AuIOErr("%pd reverting dir failed(%d, %d)\n", -+ dentry, err, rerr); -+ err = -EIO; -+ } -+ au_dtime_revert(&a->dt); -+out_unpin: -+ au_unpin(&a->pin); -+ dput(wh_dentry); -+out_parent: -+ di_write_unlock(parent); -+out_unlock: -+ if (unlikely(err)) { -+ au_update_dbtop(dentry); -+ d_drop(dentry); -+ } -+ aufs_read_unlock(dentry, AuLock_DW); -+out_free: -+ au_kfree_rcu(a); -+out: -+ return err; -+} -diff --git a/fs/aufs/i_op_del.c b/fs/aufs/i_op_del.c -new file mode 100644 -index 000000000000..05f5d4219b41 ---- /dev/null -+++ b/fs/aufs/i_op_del.c -@@ -0,0 +1,500 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * inode operations (del entry) -+ */ -+ -+#include -+#include "aufs.h" -+ -+/* -+ * decide if a new whiteout for @dentry is necessary or not. -+ * when it is necessary, prepare the parent dir for the upper branch whose -+ * branch index is @bcpup for creation. the actual creation of the whiteout will -+ * be done by caller. -+ * return value: -+ * 0: wh is unnecessary -+ * plus: wh is necessary -+ * minus: error -+ */ -+int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup) -+{ -+ int need_wh, err; -+ aufs_bindex_t btop; -+ struct super_block *sb; -+ -+ sb = dentry->d_sb; -+ btop = au_dbtop(dentry); -+ if (*bcpup < 0) { -+ *bcpup = btop; -+ if (au_test_ro(sb, btop, d_inode(dentry))) { -+ err = AuWbrCopyup(au_sbi(sb), dentry); -+ *bcpup = err; -+ if (unlikely(err < 0)) -+ goto out; -+ } -+ } else -+ AuDebugOn(btop < *bcpup -+ || au_test_ro(sb, *bcpup, d_inode(dentry))); -+ AuDbg("bcpup %d, btop %d\n", *bcpup, btop); -+ -+ if (*bcpup != btop) { -+ err = au_cpup_dirs(dentry, *bcpup); -+ if (unlikely(err)) -+ goto out; -+ need_wh = 1; -+ } else { -+ struct au_dinfo *dinfo, *tmp; -+ -+ need_wh = -ENOMEM; -+ dinfo = au_di(dentry); -+ tmp = au_di_alloc(sb, AuLsc_DI_TMP); -+ if (tmp) { -+ au_di_cp(tmp, dinfo); -+ au_di_swap(tmp, dinfo); -+ /* returns the number of positive dentries */ -+ need_wh = au_lkup_dentry(dentry, btop + 1, -+ /* AuLkup_IGNORE_PERM */ 0); -+ au_di_swap(tmp, dinfo); -+ au_rw_write_unlock(&tmp->di_rwsem); -+ au_di_free(tmp); -+ } -+ } -+ AuDbg("need_wh %d\n", need_wh); -+ err = need_wh; -+ -+out: -+ return err; -+} -+ -+/* -+ * simple tests for the del-entry operations. -+ * following the checks in vfs, plus the parent-child relationship. -+ */ -+int au_may_del(struct dentry *dentry, aufs_bindex_t bindex, -+ struct dentry *h_parent, int isdir) -+{ -+ int err; -+ umode_t h_mode; -+ struct dentry *h_dentry, *h_latest; -+ struct inode *h_inode; -+ -+ h_dentry = au_h_dptr(dentry, bindex); -+ if (d_really_is_positive(dentry)) { -+ err = -ENOENT; -+ if (unlikely(d_is_negative(h_dentry))) -+ goto out; -+ h_inode = d_inode(h_dentry); -+ if (unlikely(!h_inode->i_nlink)) -+ goto out; -+ -+ h_mode = h_inode->i_mode; -+ if (!isdir) { -+ err = -EISDIR; -+ if (unlikely(S_ISDIR(h_mode))) -+ goto out; -+ } else if (unlikely(!S_ISDIR(h_mode))) { -+ err = -ENOTDIR; -+ goto out; -+ } -+ } else { -+ /* rename(2) case */ -+ err = -EIO; -+ if (unlikely(d_is_positive(h_dentry))) -+ goto out; -+ } -+ -+ err = -ENOENT; -+ /* expected parent dir is locked */ -+ if (unlikely(h_parent != h_dentry->d_parent)) -+ goto out; -+ err = 0; -+ -+ /* -+ * rmdir a dir may break the consistency on some filesystem. -+ * let's try heavy test. -+ */ -+ err = -EACCES; -+ if (unlikely(!au_opt_test(au_mntflags(dentry->d_sb), DIRPERM1) -+ && au_test_h_perm(d_inode(h_parent), -+ MAY_EXEC | MAY_WRITE))) -+ goto out; -+ -+ h_latest = au_sio_lkup_one(&dentry->d_name, h_parent); -+ err = -EIO; -+ if (IS_ERR(h_latest)) -+ goto out; -+ if (h_latest == h_dentry) -+ err = 0; -+ dput(h_latest); -+ -+out: -+ return err; -+} -+ -+/* -+ * decide the branch where we operate for @dentry. the branch index will be set -+ * @rbcpup. after deciding it, 'pin' it and store the timestamps of the parent -+ * dir for reverting. -+ * when a new whiteout is necessary, create it. -+ */ -+static struct dentry* -+lock_hdir_create_wh(struct dentry *dentry, int isdir, aufs_bindex_t *rbcpup, -+ struct au_dtime *dt, struct au_pin *pin) -+{ -+ struct dentry *wh_dentry; -+ struct super_block *sb; -+ struct path h_path; -+ int err, need_wh; -+ unsigned int udba; -+ aufs_bindex_t bcpup; -+ -+ need_wh = au_wr_dir_need_wh(dentry, isdir, rbcpup); -+ wh_dentry = ERR_PTR(need_wh); -+ if (unlikely(need_wh < 0)) -+ goto out; -+ -+ sb = dentry->d_sb; -+ udba = au_opt_udba(sb); -+ bcpup = *rbcpup; -+ err = au_pin(pin, dentry, bcpup, udba, -+ AuPin_DI_LOCKED | AuPin_MNT_WRITE); -+ wh_dentry = ERR_PTR(err); -+ if (unlikely(err)) -+ goto out; -+ -+ h_path.dentry = au_pinned_h_parent(pin); -+ if (udba != AuOpt_UDBA_NONE -+ && au_dbtop(dentry) == bcpup) { -+ err = au_may_del(dentry, bcpup, h_path.dentry, isdir); -+ wh_dentry = ERR_PTR(err); -+ if (unlikely(err)) -+ goto out_unpin; -+ } -+ -+ h_path.mnt = au_sbr_mnt(sb, bcpup); -+ au_dtime_store(dt, au_pinned_parent(pin), &h_path); -+ wh_dentry = NULL; -+ if (!need_wh) -+ goto out; /* success, no need to create whiteout */ -+ -+ wh_dentry = au_wh_create(dentry, bcpup, h_path.dentry); -+ if (IS_ERR(wh_dentry)) -+ goto out_unpin; -+ -+ /* returns with the parent is locked and wh_dentry is dget-ed */ -+ goto out; /* success */ -+ -+out_unpin: -+ au_unpin(pin); -+out: -+ return wh_dentry; -+} -+ -+/* -+ * when removing a dir, rename it to a unique temporary whiteout-ed name first -+ * in order to be revertible and save time for removing many child whiteouts -+ * under the dir. -+ * returns 1 when there are too many child whiteout and caller should remove -+ * them asynchronously. returns 0 when the number of children is enough small to -+ * remove now or the branch fs is a remote fs. -+ * otherwise return an error. -+ */ -+static int renwh_and_rmdir(struct dentry *dentry, aufs_bindex_t bindex, -+ struct au_nhash *whlist, struct inode *dir) -+{ -+ int rmdir_later, err, dirwh; -+ struct dentry *h_dentry; -+ struct super_block *sb; -+ struct inode *inode; -+ -+ sb = dentry->d_sb; -+ SiMustAnyLock(sb); -+ h_dentry = au_h_dptr(dentry, bindex); -+ err = au_whtmp_ren(h_dentry, au_sbr(sb, bindex)); -+ if (unlikely(err)) -+ goto out; -+ -+ /* stop monitoring */ -+ inode = d_inode(dentry); -+ au_hn_free(au_hi(inode, bindex)); -+ -+ if (!au_test_fs_remote(h_dentry->d_sb)) { -+ dirwh = au_sbi(sb)->si_dirwh; -+ rmdir_later = (dirwh <= 1); -+ if (!rmdir_later) -+ rmdir_later = au_nhash_test_longer_wh(whlist, bindex, -+ dirwh); -+ if (rmdir_later) -+ return rmdir_later; -+ } -+ -+ err = au_whtmp_rmdir(dir, bindex, h_dentry, whlist); -+ if (unlikely(err)) { -+ AuIOErr("rmdir %pd, b%d failed, %d. ignored\n", -+ h_dentry, bindex, err); -+ err = 0; -+ } -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+/* -+ * final procedure for deleting a entry. -+ * maintain dentry and iattr. -+ */ -+static void epilog(struct inode *dir, struct dentry *dentry, -+ aufs_bindex_t bindex) -+{ -+ struct inode *inode; -+ -+ inode = d_inode(dentry); -+ d_drop(dentry); -+ inode->i_ctime = dir->i_ctime; -+ -+ au_dir_ts(dir, bindex); -+ inode_inc_iversion(dir); -+} -+ -+/* -+ * when an error happened, remove the created whiteout and revert everything. -+ */ -+static int do_revert(int err, struct inode *dir, aufs_bindex_t bindex, -+ aufs_bindex_t bwh, struct dentry *wh_dentry, -+ struct dentry *dentry, struct au_dtime *dt) -+{ -+ int rerr; -+ struct path h_path = { -+ .dentry = wh_dentry, -+ .mnt = au_sbr_mnt(dir->i_sb, bindex) -+ }; -+ -+ rerr = au_wh_unlink_dentry(au_h_iptr(dir, bindex), &h_path, dentry); -+ if (!rerr) { -+ au_set_dbwh(dentry, bwh); -+ au_dtime_revert(dt); -+ return 0; -+ } -+ -+ AuIOErr("%pd reverting whiteout failed(%d, %d)\n", dentry, err, rerr); -+ return -EIO; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+int aufs_unlink(struct inode *dir, struct dentry *dentry) -+{ -+ int err; -+ aufs_bindex_t bwh, bindex, btop; -+ struct inode *inode, *h_dir, *delegated; -+ struct dentry *parent, *wh_dentry; -+ /* to reduce stack size */ -+ struct { -+ struct au_dtime dt; -+ struct au_pin pin; -+ struct path h_path; -+ } *a; -+ -+ IMustLock(dir); -+ -+ err = -ENOMEM; -+ a = kmalloc(sizeof(*a), GFP_NOFS); -+ if (unlikely(!a)) -+ goto out; -+ -+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN); -+ if (unlikely(err)) -+ goto out_free; -+ err = au_d_hashed_positive(dentry); -+ if (unlikely(err)) -+ goto out_unlock; -+ inode = d_inode(dentry); -+ IMustLock(inode); -+ err = -EISDIR; -+ if (unlikely(d_is_dir(dentry))) -+ goto out_unlock; /* possible? */ -+ -+ btop = au_dbtop(dentry); -+ bwh = au_dbwh(dentry); -+ bindex = -1; -+ parent = dentry->d_parent; /* dir inode is locked */ -+ di_write_lock_parent(parent); -+ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/0, &bindex, &a->dt, -+ &a->pin); -+ err = PTR_ERR(wh_dentry); -+ if (IS_ERR(wh_dentry)) -+ goto out_parent; -+ -+ a->h_path.mnt = au_sbr_mnt(dentry->d_sb, btop); -+ a->h_path.dentry = au_h_dptr(dentry, btop); -+ dget(a->h_path.dentry); -+ if (bindex == btop) { -+ h_dir = au_pinned_h_dir(&a->pin); -+ delegated = NULL; -+ err = vfsub_unlink(h_dir, &a->h_path, &delegated, /*force*/0); -+ if (unlikely(err == -EWOULDBLOCK)) { -+ pr_warn("cannot retry for NFSv4 delegation" -+ " for an internal unlink\n"); -+ iput(delegated); -+ } -+ } else { -+ /* dir inode is locked */ -+ h_dir = d_inode(wh_dentry->d_parent); -+ IMustLock(h_dir); -+ err = 0; -+ } -+ -+ if (!err) { -+ vfsub_drop_nlink(inode); -+ epilog(dir, dentry, bindex); -+ -+ /* update target timestamps */ -+ if (bindex == btop) { -+ vfsub_update_h_iattr(&a->h_path, /*did*/NULL); -+ /*ignore*/ -+ inode->i_ctime = d_inode(a->h_path.dentry)->i_ctime; -+ } else -+ /* todo: this timestamp may be reverted later */ -+ inode->i_ctime = h_dir->i_ctime; -+ goto out_unpin; /* success */ -+ } -+ -+ /* revert */ -+ if (wh_dentry) { -+ int rerr; -+ -+ rerr = do_revert(err, dir, bindex, bwh, wh_dentry, dentry, -+ &a->dt); -+ if (rerr) -+ err = rerr; -+ } -+ -+out_unpin: -+ au_unpin(&a->pin); -+ dput(wh_dentry); -+ dput(a->h_path.dentry); -+out_parent: -+ di_write_unlock(parent); -+out_unlock: -+ aufs_read_unlock(dentry, AuLock_DW); -+out_free: -+ au_kfree_rcu(a); -+out: -+ return err; -+} -+ -+int aufs_rmdir(struct inode *dir, struct dentry *dentry) -+{ -+ int err, rmdir_later; -+ aufs_bindex_t bwh, bindex, btop; -+ struct inode *inode; -+ struct dentry *parent, *wh_dentry, *h_dentry; -+ struct au_whtmp_rmdir *args; -+ /* to reduce stack size */ -+ struct { -+ struct au_dtime dt; -+ struct au_pin pin; -+ } *a; -+ -+ IMustLock(dir); -+ -+ err = -ENOMEM; -+ a = kmalloc(sizeof(*a), GFP_NOFS); -+ if (unlikely(!a)) -+ goto out; -+ -+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH | AuLock_GEN); -+ if (unlikely(err)) -+ goto out_free; -+ err = au_alive_dir(dentry); -+ if (unlikely(err)) -+ goto out_unlock; -+ inode = d_inode(dentry); -+ IMustLock(inode); -+ err = -ENOTDIR; -+ if (unlikely(!d_is_dir(dentry))) -+ goto out_unlock; /* possible? */ -+ -+ err = -ENOMEM; -+ args = au_whtmp_rmdir_alloc(dir->i_sb, GFP_NOFS); -+ if (unlikely(!args)) -+ goto out_unlock; -+ -+ parent = dentry->d_parent; /* dir inode is locked */ -+ di_write_lock_parent(parent); -+ err = au_test_empty(dentry, &args->whlist); -+ if (unlikely(err)) -+ goto out_parent; -+ -+ btop = au_dbtop(dentry); -+ bwh = au_dbwh(dentry); -+ bindex = -1; -+ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/1, &bindex, &a->dt, -+ &a->pin); -+ err = PTR_ERR(wh_dentry); -+ if (IS_ERR(wh_dentry)) -+ goto out_parent; -+ -+ h_dentry = au_h_dptr(dentry, btop); -+ dget(h_dentry); -+ rmdir_later = 0; -+ if (bindex == btop) { -+ err = renwh_and_rmdir(dentry, btop, &args->whlist, dir); -+ if (err > 0) { -+ rmdir_later = err; -+ err = 0; -+ } -+ } else { -+ /* stop monitoring */ -+ au_hn_free(au_hi(inode, btop)); -+ -+ /* dir inode is locked */ -+ IMustLock(d_inode(wh_dentry->d_parent)); -+ err = 0; -+ } -+ -+ if (!err) { -+ vfsub_dead_dir(inode); -+ au_set_dbdiropq(dentry, -1); -+ epilog(dir, dentry, bindex); -+ -+ if (rmdir_later) { -+ au_whtmp_kick_rmdir(dir, btop, h_dentry, args); -+ args = NULL; -+ } -+ -+ goto out_unpin; /* success */ -+ } -+ -+ /* revert */ -+ AuLabel(revert); -+ if (wh_dentry) { -+ int rerr; -+ -+ rerr = do_revert(err, dir, bindex, bwh, wh_dentry, dentry, -+ &a->dt); -+ if (rerr) -+ err = rerr; -+ } -+ -+out_unpin: -+ au_unpin(&a->pin); -+ dput(wh_dentry); -+ dput(h_dentry); -+out_parent: -+ di_write_unlock(parent); -+ if (args) -+ au_whtmp_rmdir_free(args); -+out_unlock: -+ aufs_read_unlock(dentry, AuLock_DW); -+out_free: -+ au_kfree_rcu(a); -+out: -+ AuTraceErr(err); -+ return err; -+} -diff --git a/fs/aufs/i_op_ren.c b/fs/aufs/i_op_ren.c -new file mode 100644 -index 000000000000..37c52390034a ---- /dev/null -+++ b/fs/aufs/i_op_ren.c -@@ -0,0 +1,1237 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * inode operation (rename entry) -+ * todo: this is crazy monster -+ */ -+ -+#include -+#include "aufs.h" -+ -+enum { AuSRC, AuDST, AuSrcDst }; -+enum { AuPARENT, AuCHILD, AuParentChild }; -+ -+#define AuRen_ISDIR_SRC 1 -+#define AuRen_ISDIR_DST (1 << 1) -+#define AuRen_ISSAMEDIR (1 << 2) -+#define AuRen_WHSRC (1 << 3) -+#define AuRen_WHDST (1 << 4) -+#define AuRen_MNT_WRITE (1 << 5) -+#define AuRen_DT_DSTDIR (1 << 6) -+#define AuRen_DIROPQ_SRC (1 << 7) -+#define AuRen_DIROPQ_DST (1 << 8) -+#define AuRen_DIRREN (1 << 9) -+#define AuRen_DROPPED_SRC (1 << 10) -+#define AuRen_DROPPED_DST (1 << 11) -+#define au_ftest_ren(flags, name) ((flags) & AuRen_##name) -+#define au_fset_ren(flags, name) \ -+ do { (flags) |= AuRen_##name; } while (0) -+#define au_fclr_ren(flags, name) \ -+ do { (flags) &= ~AuRen_##name; } while (0) -+ -+#ifndef CONFIG_AUFS_DIRREN -+#undef AuRen_DIRREN -+#define AuRen_DIRREN 0 -+#endif -+ -+struct au_ren_args { -+ struct { -+ struct dentry *dentry, *h_dentry, *parent, *h_parent, -+ *wh_dentry; -+ struct inode *dir, *inode; -+ struct au_hinode *hdir, *hinode; -+ struct au_dtime dt[AuParentChild]; -+ aufs_bindex_t btop, bdiropq; -+ } sd[AuSrcDst]; -+ -+#define src_dentry sd[AuSRC].dentry -+#define src_dir sd[AuSRC].dir -+#define src_inode sd[AuSRC].inode -+#define src_h_dentry sd[AuSRC].h_dentry -+#define src_parent sd[AuSRC].parent -+#define src_h_parent sd[AuSRC].h_parent -+#define src_wh_dentry sd[AuSRC].wh_dentry -+#define src_hdir sd[AuSRC].hdir -+#define src_hinode sd[AuSRC].hinode -+#define src_h_dir sd[AuSRC].hdir->hi_inode -+#define src_dt sd[AuSRC].dt -+#define src_btop sd[AuSRC].btop -+#define src_bdiropq sd[AuSRC].bdiropq -+ -+#define dst_dentry sd[AuDST].dentry -+#define dst_dir sd[AuDST].dir -+#define dst_inode sd[AuDST].inode -+#define dst_h_dentry sd[AuDST].h_dentry -+#define dst_parent sd[AuDST].parent -+#define dst_h_parent sd[AuDST].h_parent -+#define dst_wh_dentry sd[AuDST].wh_dentry -+#define dst_hdir sd[AuDST].hdir -+#define dst_hinode sd[AuDST].hinode -+#define dst_h_dir sd[AuDST].hdir->hi_inode -+#define dst_dt sd[AuDST].dt -+#define dst_btop sd[AuDST].btop -+#define dst_bdiropq sd[AuDST].bdiropq -+ -+ struct dentry *h_trap; -+ struct au_branch *br; -+ struct path h_path; -+ struct au_nhash whlist; -+ aufs_bindex_t btgt, src_bwh; -+ -+ struct { -+ unsigned short auren_flags; -+ unsigned char flags; /* syscall parameter */ -+ unsigned char exchange; -+ } __packed; -+ -+ struct au_whtmp_rmdir *thargs; -+ struct dentry *h_dst; -+ struct au_hinode *h_root; -+}; -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * functions for reverting. -+ * when an error happened in a single rename systemcall, we should revert -+ * everything as if nothing happened. -+ * we don't need to revert the copied-up/down the parent dir since they are -+ * harmless. -+ */ -+ -+#define RevertFailure(fmt, ...) do { \ -+ AuIOErr("revert failure: " fmt " (%d, %d)\n", \ -+ ##__VA_ARGS__, err, rerr); \ -+ err = -EIO; \ -+} while (0) -+ -+static void au_ren_do_rev_diropq(int err, struct au_ren_args *a, int idx) -+{ -+ int rerr; -+ struct dentry *d; -+#define src_or_dst(member) a->sd[idx].member -+ -+ d = src_or_dst(dentry); /* {src,dst}_dentry */ -+ au_hn_inode_lock_nested(src_or_dst(hinode), AuLsc_I_CHILD); -+ rerr = au_diropq_remove(d, a->btgt); -+ au_hn_inode_unlock(src_or_dst(hinode)); -+ au_set_dbdiropq(d, src_or_dst(bdiropq)); -+ if (rerr) -+ RevertFailure("remove diropq %pd", d); -+ -+#undef src_or_dst_ -+} -+ -+static void au_ren_rev_diropq(int err, struct au_ren_args *a) -+{ -+ if (au_ftest_ren(a->auren_flags, DIROPQ_SRC)) -+ au_ren_do_rev_diropq(err, a, AuSRC); -+ if (au_ftest_ren(a->auren_flags, DIROPQ_DST)) -+ au_ren_do_rev_diropq(err, a, AuDST); -+} -+ -+static void au_ren_rev_rename(int err, struct au_ren_args *a) -+{ -+ int rerr; -+ struct inode *delegated; -+ -+ a->h_path.dentry = vfsub_lkup_one(&a->src_dentry->d_name, -+ a->src_h_parent); -+ rerr = PTR_ERR(a->h_path.dentry); -+ if (IS_ERR(a->h_path.dentry)) { -+ RevertFailure("lkup one %pd", a->src_dentry); -+ return; -+ } -+ -+ delegated = NULL; -+ rerr = vfsub_rename(a->dst_h_dir, -+ au_h_dptr(a->src_dentry, a->btgt), -+ a->src_h_dir, &a->h_path, &delegated, a->flags); -+ if (unlikely(rerr == -EWOULDBLOCK)) { -+ pr_warn("cannot retry for NFSv4 delegation" -+ " for an internal rename\n"); -+ iput(delegated); -+ } -+ d_drop(a->h_path.dentry); -+ dput(a->h_path.dentry); -+ /* au_set_h_dptr(a->src_dentry, a->btgt, NULL); */ -+ if (rerr) -+ RevertFailure("rename %pd", a->src_dentry); -+} -+ -+static void au_ren_rev_whtmp(int err, struct au_ren_args *a) -+{ -+ int rerr; -+ struct inode *delegated; -+ -+ a->h_path.dentry = vfsub_lkup_one(&a->dst_dentry->d_name, -+ a->dst_h_parent); -+ rerr = PTR_ERR(a->h_path.dentry); -+ if (IS_ERR(a->h_path.dentry)) { -+ RevertFailure("lkup one %pd", a->dst_dentry); -+ return; -+ } -+ if (d_is_positive(a->h_path.dentry)) { -+ d_drop(a->h_path.dentry); -+ dput(a->h_path.dentry); -+ return; -+ } -+ -+ delegated = NULL; -+ rerr = vfsub_rename(a->dst_h_dir, a->h_dst, a->dst_h_dir, &a->h_path, -+ &delegated, a->flags); -+ if (unlikely(rerr == -EWOULDBLOCK)) { -+ pr_warn("cannot retry for NFSv4 delegation" -+ " for an internal rename\n"); -+ iput(delegated); -+ } -+ d_drop(a->h_path.dentry); -+ dput(a->h_path.dentry); -+ if (!rerr) -+ au_set_h_dptr(a->dst_dentry, a->btgt, dget(a->h_dst)); -+ else -+ RevertFailure("rename %pd", a->h_dst); -+} -+ -+static void au_ren_rev_whsrc(int err, struct au_ren_args *a) -+{ -+ int rerr; -+ -+ a->h_path.dentry = a->src_wh_dentry; -+ rerr = au_wh_unlink_dentry(a->src_h_dir, &a->h_path, a->src_dentry); -+ au_set_dbwh(a->src_dentry, a->src_bwh); -+ if (rerr) -+ RevertFailure("unlink %pd", a->src_wh_dentry); -+} -+#undef RevertFailure -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * when we have to copyup the renaming entry, do it with the rename-target name -+ * in order to minimize the cost (the later actual rename is unnecessary). -+ * otherwise rename it on the target branch. -+ */ -+static int au_ren_or_cpup(struct au_ren_args *a) -+{ -+ int err; -+ struct dentry *d; -+ struct inode *delegated; -+ -+ d = a->src_dentry; -+ if (au_dbtop(d) == a->btgt) { -+ a->h_path.dentry = a->dst_h_dentry; -+ AuDebugOn(au_dbtop(d) != a->btgt); -+ delegated = NULL; -+ err = vfsub_rename(a->src_h_dir, au_h_dptr(d, a->btgt), -+ a->dst_h_dir, &a->h_path, &delegated, -+ a->flags); -+ if (unlikely(err == -EWOULDBLOCK)) { -+ pr_warn("cannot retry for NFSv4 delegation" -+ " for an internal rename\n"); -+ iput(delegated); -+ } -+ } else -+ BUG(); -+ -+ if (!err && a->h_dst) -+ /* it will be set to dinfo later */ -+ dget(a->h_dst); -+ -+ return err; -+} -+ -+/* cf. aufs_rmdir() */ -+static int au_ren_del_whtmp(struct au_ren_args *a) -+{ -+ int err; -+ struct inode *dir; -+ -+ dir = a->dst_dir; -+ SiMustAnyLock(dir->i_sb); -+ if (!au_nhash_test_longer_wh(&a->whlist, a->btgt, -+ au_sbi(dir->i_sb)->si_dirwh) -+ || au_test_fs_remote(a->h_dst->d_sb)) { -+ err = au_whtmp_rmdir(dir, a->btgt, a->h_dst, &a->whlist); -+ if (unlikely(err)) -+ pr_warn("failed removing whtmp dir %pd (%d), " -+ "ignored.\n", a->h_dst, err); -+ } else { -+ au_nhash_wh_free(&a->thargs->whlist); -+ a->thargs->whlist = a->whlist; -+ a->whlist.nh_num = 0; -+ au_whtmp_kick_rmdir(dir, a->btgt, a->h_dst, a->thargs); -+ dput(a->h_dst); -+ a->thargs = NULL; -+ } -+ -+ return 0; -+} -+ -+/* make it 'opaque' dir. */ -+static int au_ren_do_diropq(struct au_ren_args *a, int idx) -+{ -+ int err; -+ struct dentry *d, *diropq; -+#define src_or_dst(member) a->sd[idx].member -+ -+ err = 0; -+ d = src_or_dst(dentry); /* {src,dst}_dentry */ -+ src_or_dst(bdiropq) = au_dbdiropq(d); -+ src_or_dst(hinode) = au_hi(src_or_dst(inode), a->btgt); -+ au_hn_inode_lock_nested(src_or_dst(hinode), AuLsc_I_CHILD); -+ diropq = au_diropq_create(d, a->btgt); -+ au_hn_inode_unlock(src_or_dst(hinode)); -+ if (IS_ERR(diropq)) -+ err = PTR_ERR(diropq); -+ else -+ dput(diropq); -+ -+#undef src_or_dst_ -+ return err; -+} -+ -+static int au_ren_diropq(struct au_ren_args *a) -+{ -+ int err; -+ unsigned char always; -+ struct dentry *d; -+ -+ err = 0; -+ d = a->dst_dentry; /* already renamed on the branch */ -+ always = !!au_opt_test(au_mntflags(d->d_sb), ALWAYS_DIROPQ); -+ if (au_ftest_ren(a->auren_flags, ISDIR_SRC) -+ && !au_ftest_ren(a->auren_flags, DIRREN) -+ && a->btgt != au_dbdiropq(a->src_dentry) -+ && (a->dst_wh_dentry -+ || a->btgt <= au_dbdiropq(d) -+ /* hide the lower to keep xino */ -+ /* the lowers may not be a dir, but we hide them anyway */ -+ || a->btgt < au_dbbot(d) -+ || always)) { -+ AuDbg("here\n"); -+ err = au_ren_do_diropq(a, AuSRC); -+ if (unlikely(err)) -+ goto out; -+ au_fset_ren(a->auren_flags, DIROPQ_SRC); -+ } -+ if (!a->exchange) -+ goto out; /* success */ -+ -+ d = a->src_dentry; /* already renamed on the branch */ -+ if (au_ftest_ren(a->auren_flags, ISDIR_DST) -+ && a->btgt != au_dbdiropq(a->dst_dentry) -+ && (a->btgt < au_dbdiropq(d) -+ || a->btgt < au_dbbot(d) -+ || always)) { -+ AuDbgDentry(a->src_dentry); -+ AuDbgDentry(a->dst_dentry); -+ err = au_ren_do_diropq(a, AuDST); -+ if (unlikely(err)) -+ goto out_rev_src; -+ au_fset_ren(a->auren_flags, DIROPQ_DST); -+ } -+ goto out; /* success */ -+ -+out_rev_src: -+ AuDbg("err %d, reverting src\n", err); -+ au_ren_rev_diropq(err, a); -+out: -+ return err; -+} -+ -+static int do_rename(struct au_ren_args *a) -+{ -+ int err; -+ struct dentry *d, *h_d; -+ -+ if (!a->exchange) { -+ /* prepare workqueue args for asynchronous rmdir */ -+ h_d = a->dst_h_dentry; -+ if (au_ftest_ren(a->auren_flags, ISDIR_DST) -+ /* && !au_ftest_ren(a->auren_flags, DIRREN) */ -+ && d_is_positive(h_d)) { -+ err = -ENOMEM; -+ a->thargs = au_whtmp_rmdir_alloc(a->src_dentry->d_sb, -+ GFP_NOFS); -+ if (unlikely(!a->thargs)) -+ goto out; -+ a->h_dst = dget(h_d); -+ } -+ -+ /* create whiteout for src_dentry */ -+ if (au_ftest_ren(a->auren_flags, WHSRC)) { -+ a->src_bwh = au_dbwh(a->src_dentry); -+ AuDebugOn(a->src_bwh >= 0); -+ a->src_wh_dentry = au_wh_create(a->src_dentry, a->btgt, -+ a->src_h_parent); -+ err = PTR_ERR(a->src_wh_dentry); -+ if (IS_ERR(a->src_wh_dentry)) -+ goto out_thargs; -+ } -+ -+ /* lookup whiteout for dentry */ -+ if (au_ftest_ren(a->auren_flags, WHDST)) { -+ h_d = au_wh_lkup(a->dst_h_parent, -+ &a->dst_dentry->d_name, a->br); -+ err = PTR_ERR(h_d); -+ if (IS_ERR(h_d)) -+ goto out_whsrc; -+ if (d_is_negative(h_d)) -+ dput(h_d); -+ else -+ a->dst_wh_dentry = h_d; -+ } -+ -+ /* rename dentry to tmpwh */ -+ if (a->thargs) { -+ err = au_whtmp_ren(a->dst_h_dentry, a->br); -+ if (unlikely(err)) -+ goto out_whdst; -+ -+ d = a->dst_dentry; -+ au_set_h_dptr(d, a->btgt, NULL); -+ err = au_lkup_neg(d, a->btgt, /*wh*/0); -+ if (unlikely(err)) -+ goto out_whtmp; -+ a->dst_h_dentry = au_h_dptr(d, a->btgt); -+ } -+ } -+ -+ BUG_ON(d_is_positive(a->dst_h_dentry) && a->src_btop != a->btgt); -+#if 0 /* debugging */ -+ BUG_ON(!au_ftest_ren(a->auren_flags, DIRREN) -+ && d_is_positive(a->dst_h_dentry) -+ && a->src_btop != a->btgt); -+#endif -+ -+ /* rename by vfs_rename or cpup */ -+ err = au_ren_or_cpup(a); -+ if (unlikely(err)) -+ /* leave the copied-up one */ -+ goto out_whtmp; -+ -+ /* make dir opaque */ -+ err = au_ren_diropq(a); -+ if (unlikely(err)) -+ goto out_rename; -+ -+ /* update target timestamps */ -+ if (a->exchange) { -+ AuDebugOn(au_dbtop(a->dst_dentry) != a->btgt); -+ a->h_path.dentry = au_h_dptr(a->dst_dentry, a->btgt); -+ vfsub_update_h_iattr(&a->h_path, /*did*/NULL); /*ignore*/ -+ a->dst_inode->i_ctime = d_inode(a->h_path.dentry)->i_ctime; -+ } -+ AuDebugOn(au_dbtop(a->src_dentry) != a->btgt); -+ a->h_path.dentry = au_h_dptr(a->src_dentry, a->btgt); -+ vfsub_update_h_iattr(&a->h_path, /*did*/NULL); /*ignore*/ -+ a->src_inode->i_ctime = d_inode(a->h_path.dentry)->i_ctime; -+ -+ if (!a->exchange) { -+ /* remove whiteout for dentry */ -+ if (a->dst_wh_dentry) { -+ a->h_path.dentry = a->dst_wh_dentry; -+ err = au_wh_unlink_dentry(a->dst_h_dir, &a->h_path, -+ a->dst_dentry); -+ if (unlikely(err)) -+ goto out_diropq; -+ } -+ -+ /* remove whtmp */ -+ if (a->thargs) -+ au_ren_del_whtmp(a); /* ignore this error */ -+ -+ au_fhsm_wrote(a->src_dentry->d_sb, a->btgt, /*force*/0); -+ } -+ err = 0; -+ goto out_success; -+ -+out_diropq: -+ au_ren_rev_diropq(err, a); -+out_rename: -+ au_ren_rev_rename(err, a); -+ dput(a->h_dst); -+out_whtmp: -+ if (a->thargs) -+ au_ren_rev_whtmp(err, a); -+out_whdst: -+ dput(a->dst_wh_dentry); -+ a->dst_wh_dentry = NULL; -+out_whsrc: -+ if (a->src_wh_dentry) -+ au_ren_rev_whsrc(err, a); -+out_success: -+ dput(a->src_wh_dentry); -+ dput(a->dst_wh_dentry); -+out_thargs: -+ if (a->thargs) { -+ dput(a->h_dst); -+ au_whtmp_rmdir_free(a->thargs); -+ a->thargs = NULL; -+ } -+out: -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * test if @dentry dir can be rename destination or not. -+ * success means, it is a logically empty dir. -+ */ -+static int may_rename_dstdir(struct dentry *dentry, struct au_nhash *whlist) -+{ -+ return au_test_empty(dentry, whlist); -+} -+ -+/* -+ * test if @a->src_dentry dir can be rename source or not. -+ * if it can, return 0. -+ * success means, -+ * - it is a logically empty dir. -+ * - or, it exists on writable branch and has no children including whiteouts -+ * on the lower branch unless DIRREN is on. -+ */ -+static int may_rename_srcdir(struct au_ren_args *a) -+{ -+ int err; -+ unsigned int rdhash; -+ aufs_bindex_t btop, btgt; -+ struct dentry *dentry; -+ struct super_block *sb; -+ struct au_sbinfo *sbinfo; -+ -+ dentry = a->src_dentry; -+ sb = dentry->d_sb; -+ sbinfo = au_sbi(sb); -+ if (au_opt_test(sbinfo->si_mntflags, DIRREN)) -+ au_fset_ren(a->auren_flags, DIRREN); -+ -+ btgt = a->btgt; -+ btop = au_dbtop(dentry); -+ if (btop != btgt) { -+ struct au_nhash whlist; -+ -+ SiMustAnyLock(sb); -+ rdhash = sbinfo->si_rdhash; -+ if (!rdhash) -+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, -+ dentry)); -+ err = au_nhash_alloc(&whlist, rdhash, GFP_NOFS); -+ if (unlikely(err)) -+ goto out; -+ err = au_test_empty(dentry, &whlist); -+ au_nhash_wh_free(&whlist); -+ goto out; -+ } -+ -+ if (btop == au_dbtaildir(dentry)) -+ return 0; /* success */ -+ -+ err = au_test_empty_lower(dentry); -+ -+out: -+ if (err == -ENOTEMPTY) { -+ if (au_ftest_ren(a->auren_flags, DIRREN)) { -+ err = 0; -+ } else { -+ AuWarn1("renaming dir who has child(ren) on multiple " -+ "branches, is not supported\n"); -+ err = -EXDEV; -+ } -+ } -+ return err; -+} -+ -+/* side effect: sets whlist and h_dentry */ -+static int au_ren_may_dir(struct au_ren_args *a) -+{ -+ int err; -+ unsigned int rdhash; -+ struct dentry *d; -+ -+ d = a->dst_dentry; -+ SiMustAnyLock(d->d_sb); -+ -+ err = 0; -+ if (au_ftest_ren(a->auren_flags, ISDIR_DST) && a->dst_inode) { -+ rdhash = au_sbi(d->d_sb)->si_rdhash; -+ if (!rdhash) -+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, d)); -+ err = au_nhash_alloc(&a->whlist, rdhash, GFP_NOFS); -+ if (unlikely(err)) -+ goto out; -+ -+ if (!a->exchange) { -+ au_set_dbtop(d, a->dst_btop); -+ err = may_rename_dstdir(d, &a->whlist); -+ au_set_dbtop(d, a->btgt); -+ } else -+ err = may_rename_srcdir(a); -+ } -+ a->dst_h_dentry = au_h_dptr(d, au_dbtop(d)); -+ if (unlikely(err)) -+ goto out; -+ -+ d = a->src_dentry; -+ a->src_h_dentry = au_h_dptr(d, au_dbtop(d)); -+ if (au_ftest_ren(a->auren_flags, ISDIR_SRC)) { -+ err = may_rename_srcdir(a); -+ if (unlikely(err)) { -+ au_nhash_wh_free(&a->whlist); -+ a->whlist.nh_num = 0; -+ } -+ } -+out: -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * simple tests for rename. -+ * following the checks in vfs, plus the parent-child relationship. -+ */ -+static int au_may_ren(struct au_ren_args *a) -+{ -+ int err, isdir; -+ struct inode *h_inode; -+ -+ if (a->src_btop == a->btgt) { -+ err = au_may_del(a->src_dentry, a->btgt, a->src_h_parent, -+ au_ftest_ren(a->auren_flags, ISDIR_SRC)); -+ if (unlikely(err)) -+ goto out; -+ err = -EINVAL; -+ if (unlikely(a->src_h_dentry == a->h_trap)) -+ goto out; -+ } -+ -+ err = 0; -+ if (a->dst_btop != a->btgt) -+ goto out; -+ -+ err = -ENOTEMPTY; -+ if (unlikely(a->dst_h_dentry == a->h_trap)) -+ goto out; -+ -+ err = -EIO; -+ isdir = !!au_ftest_ren(a->auren_flags, ISDIR_DST); -+ if (d_really_is_negative(a->dst_dentry)) { -+ if (d_is_negative(a->dst_h_dentry)) -+ err = au_may_add(a->dst_dentry, a->btgt, -+ a->dst_h_parent, isdir); -+ } else { -+ if (unlikely(d_is_negative(a->dst_h_dentry))) -+ goto out; -+ h_inode = d_inode(a->dst_h_dentry); -+ if (h_inode->i_nlink) -+ err = au_may_del(a->dst_dentry, a->btgt, -+ a->dst_h_parent, isdir); -+ } -+ -+out: -+ if (unlikely(err == -ENOENT || err == -EEXIST)) -+ err = -EIO; -+ AuTraceErr(err); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * locking order -+ * (VFS) -+ * - src_dir and dir by lock_rename() -+ * - inode if exists -+ * (aufs) -+ * - lock all -+ * + src_dentry and dentry by aufs_read_and_write_lock2() which calls, -+ * + si_read_lock -+ * + di_write_lock2_child() -+ * + di_write_lock_child() -+ * + ii_write_lock_child() -+ * + di_write_lock_child2() -+ * + ii_write_lock_child2() -+ * + src_parent and parent -+ * + di_write_lock_parent() -+ * + ii_write_lock_parent() -+ * + di_write_lock_parent2() -+ * + ii_write_lock_parent2() -+ * + lower src_dir and dir by vfsub_lock_rename() -+ * + verify the every relationships between child and parent. if any -+ * of them failed, unlock all and return -EBUSY. -+ */ -+static void au_ren_unlock(struct au_ren_args *a) -+{ -+ vfsub_unlock_rename(a->src_h_parent, a->src_hdir, -+ a->dst_h_parent, a->dst_hdir); -+ if (au_ftest_ren(a->auren_flags, DIRREN) -+ && a->h_root) -+ au_hn_inode_unlock(a->h_root); -+ if (au_ftest_ren(a->auren_flags, MNT_WRITE)) -+ vfsub_mnt_drop_write(au_br_mnt(a->br)); -+} -+ -+static int au_ren_lock(struct au_ren_args *a) -+{ -+ int err; -+ unsigned int udba; -+ -+ err = 0; -+ a->src_h_parent = au_h_dptr(a->src_parent, a->btgt); -+ a->src_hdir = au_hi(a->src_dir, a->btgt); -+ a->dst_h_parent = au_h_dptr(a->dst_parent, a->btgt); -+ a->dst_hdir = au_hi(a->dst_dir, a->btgt); -+ -+ err = vfsub_mnt_want_write(au_br_mnt(a->br)); -+ if (unlikely(err)) -+ goto out; -+ au_fset_ren(a->auren_flags, MNT_WRITE); -+ if (au_ftest_ren(a->auren_flags, DIRREN)) { -+ struct dentry *root; -+ struct inode *dir; -+ -+ /* -+ * sbinfo is already locked, so this ii_read_lock is -+ * unnecessary. but our debugging feature checks it. -+ */ -+ root = a->src_inode->i_sb->s_root; -+ if (root != a->src_parent && root != a->dst_parent) { -+ dir = d_inode(root); -+ ii_read_lock_parent3(dir); -+ a->h_root = au_hi(dir, a->btgt); -+ ii_read_unlock(dir); -+ au_hn_inode_lock_nested(a->h_root, AuLsc_I_PARENT3); -+ } -+ } -+ a->h_trap = vfsub_lock_rename(a->src_h_parent, a->src_hdir, -+ a->dst_h_parent, a->dst_hdir); -+ udba = au_opt_udba(a->src_dentry->d_sb); -+ if (unlikely(a->src_hdir->hi_inode != d_inode(a->src_h_parent) -+ || a->dst_hdir->hi_inode != d_inode(a->dst_h_parent))) -+ err = au_busy_or_stale(); -+ if (!err && au_dbtop(a->src_dentry) == a->btgt) -+ err = au_h_verify(a->src_h_dentry, udba, -+ d_inode(a->src_h_parent), a->src_h_parent, -+ a->br); -+ if (!err && au_dbtop(a->dst_dentry) == a->btgt) -+ err = au_h_verify(a->dst_h_dentry, udba, -+ d_inode(a->dst_h_parent), a->dst_h_parent, -+ a->br); -+ if (!err) -+ goto out; /* success */ -+ -+ err = au_busy_or_stale(); -+ au_ren_unlock(a); -+ -+out: -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static void au_ren_refresh_dir(struct au_ren_args *a) -+{ -+ struct inode *dir; -+ -+ dir = a->dst_dir; -+ inode_inc_iversion(dir); -+ if (au_ftest_ren(a->auren_flags, ISDIR_SRC)) { -+ /* is this updating defined in POSIX? */ -+ au_cpup_attr_timesizes(a->src_inode); -+ au_cpup_attr_nlink(dir, /*force*/1); -+ } -+ au_dir_ts(dir, a->btgt); -+ -+ if (a->exchange) { -+ dir = a->src_dir; -+ inode_inc_iversion(dir); -+ if (au_ftest_ren(a->auren_flags, ISDIR_DST)) { -+ /* is this updating defined in POSIX? */ -+ au_cpup_attr_timesizes(a->dst_inode); -+ au_cpup_attr_nlink(dir, /*force*/1); -+ } -+ au_dir_ts(dir, a->btgt); -+ } -+ -+ if (au_ftest_ren(a->auren_flags, ISSAMEDIR)) -+ return; -+ -+ dir = a->src_dir; -+ inode_inc_iversion(dir); -+ if (au_ftest_ren(a->auren_flags, ISDIR_SRC)) -+ au_cpup_attr_nlink(dir, /*force*/1); -+ au_dir_ts(dir, a->btgt); -+} -+ -+static void au_ren_refresh(struct au_ren_args *a) -+{ -+ aufs_bindex_t bbot, bindex; -+ struct dentry *d, *h_d; -+ struct inode *i, *h_i; -+ struct super_block *sb; -+ -+ d = a->dst_dentry; -+ d_drop(d); -+ if (a->h_dst) -+ /* already dget-ed by au_ren_or_cpup() */ -+ au_set_h_dptr(d, a->btgt, a->h_dst); -+ -+ i = a->dst_inode; -+ if (i) { -+ if (!a->exchange) { -+ if (!au_ftest_ren(a->auren_flags, ISDIR_DST)) -+ vfsub_drop_nlink(i); -+ else { -+ vfsub_dead_dir(i); -+ au_cpup_attr_timesizes(i); -+ } -+ au_update_dbrange(d, /*do_put_zero*/1); -+ } else -+ au_cpup_attr_nlink(i, /*force*/1); -+ } else { -+ bbot = a->btgt; -+ for (bindex = au_dbtop(d); bindex < bbot; bindex++) -+ au_set_h_dptr(d, bindex, NULL); -+ bbot = au_dbbot(d); -+ for (bindex = a->btgt + 1; bindex <= bbot; bindex++) -+ au_set_h_dptr(d, bindex, NULL); -+ au_update_dbrange(d, /*do_put_zero*/0); -+ } -+ -+ if (a->exchange -+ || au_ftest_ren(a->auren_flags, DIRREN)) { -+ d_drop(a->src_dentry); -+ if (au_ftest_ren(a->auren_flags, DIRREN)) -+ au_set_dbwh(a->src_dentry, -1); -+ return; -+ } -+ -+ d = a->src_dentry; -+ au_set_dbwh(d, -1); -+ bbot = au_dbbot(d); -+ for (bindex = a->btgt + 1; bindex <= bbot; bindex++) { -+ h_d = au_h_dptr(d, bindex); -+ if (h_d) -+ au_set_h_dptr(d, bindex, NULL); -+ } -+ au_set_dbbot(d, a->btgt); -+ -+ sb = d->d_sb; -+ i = a->src_inode; -+ if (au_opt_test(au_mntflags(sb), PLINK) && au_plink_test(i)) -+ return; /* success */ -+ -+ bbot = au_ibbot(i); -+ for (bindex = a->btgt + 1; bindex <= bbot; bindex++) { -+ h_i = au_h_iptr(i, bindex); -+ if (h_i) { -+ au_xino_write(sb, bindex, h_i->i_ino, /*ino*/0); -+ /* ignore this error */ -+ au_set_h_iptr(i, bindex, NULL, 0); -+ } -+ } -+ au_set_ibbot(i, a->btgt); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* mainly for link(2) and rename(2) */ -+int au_wbr(struct dentry *dentry, aufs_bindex_t btgt) -+{ -+ aufs_bindex_t bdiropq, bwh; -+ struct dentry *parent; -+ struct au_branch *br; -+ -+ parent = dentry->d_parent; -+ IMustLock(d_inode(parent)); /* dir is locked */ -+ -+ bdiropq = au_dbdiropq(parent); -+ bwh = au_dbwh(dentry); -+ br = au_sbr(dentry->d_sb, btgt); -+ if (au_br_rdonly(br) -+ || (0 <= bdiropq && bdiropq < btgt) -+ || (0 <= bwh && bwh < btgt)) -+ btgt = -1; -+ -+ AuDbg("btgt %d\n", btgt); -+ return btgt; -+} -+ -+/* sets src_btop, dst_btop and btgt */ -+static int au_ren_wbr(struct au_ren_args *a) -+{ -+ int err; -+ struct au_wr_dir_args wr_dir_args = { -+ /* .force_btgt = -1, */ -+ .flags = AuWrDir_ADD_ENTRY -+ }; -+ -+ a->src_btop = au_dbtop(a->src_dentry); -+ a->dst_btop = au_dbtop(a->dst_dentry); -+ if (au_ftest_ren(a->auren_flags, ISDIR_SRC) -+ || au_ftest_ren(a->auren_flags, ISDIR_DST)) -+ au_fset_wrdir(wr_dir_args.flags, ISDIR); -+ wr_dir_args.force_btgt = a->src_btop; -+ if (a->dst_inode && a->dst_btop < a->src_btop) -+ wr_dir_args.force_btgt = a->dst_btop; -+ wr_dir_args.force_btgt = au_wbr(a->dst_dentry, wr_dir_args.force_btgt); -+ err = au_wr_dir(a->dst_dentry, a->src_dentry, &wr_dir_args); -+ a->btgt = err; -+ if (a->exchange) -+ au_update_dbtop(a->dst_dentry); -+ -+ return err; -+} -+ -+static void au_ren_dt(struct au_ren_args *a) -+{ -+ a->h_path.dentry = a->src_h_parent; -+ au_dtime_store(a->src_dt + AuPARENT, a->src_parent, &a->h_path); -+ if (!au_ftest_ren(a->auren_flags, ISSAMEDIR)) { -+ a->h_path.dentry = a->dst_h_parent; -+ au_dtime_store(a->dst_dt + AuPARENT, a->dst_parent, &a->h_path); -+ } -+ -+ au_fclr_ren(a->auren_flags, DT_DSTDIR); -+ if (!au_ftest_ren(a->auren_flags, ISDIR_SRC) -+ && !a->exchange) -+ return; -+ -+ a->h_path.dentry = a->src_h_dentry; -+ au_dtime_store(a->src_dt + AuCHILD, a->src_dentry, &a->h_path); -+ if (d_is_positive(a->dst_h_dentry)) { -+ au_fset_ren(a->auren_flags, DT_DSTDIR); -+ a->h_path.dentry = a->dst_h_dentry; -+ au_dtime_store(a->dst_dt + AuCHILD, a->dst_dentry, &a->h_path); -+ } -+} -+ -+static void au_ren_rev_dt(int err, struct au_ren_args *a) -+{ -+ struct dentry *h_d; -+ struct inode *h_inode; -+ -+ au_dtime_revert(a->src_dt + AuPARENT); -+ if (!au_ftest_ren(a->auren_flags, ISSAMEDIR)) -+ au_dtime_revert(a->dst_dt + AuPARENT); -+ -+ if (au_ftest_ren(a->auren_flags, ISDIR_SRC) && err != -EIO) { -+ h_d = a->src_dt[AuCHILD].dt_h_path.dentry; -+ h_inode = d_inode(h_d); -+ inode_lock_nested(h_inode, AuLsc_I_CHILD); -+ au_dtime_revert(a->src_dt + AuCHILD); -+ inode_unlock(h_inode); -+ -+ if (au_ftest_ren(a->auren_flags, DT_DSTDIR)) { -+ h_d = a->dst_dt[AuCHILD].dt_h_path.dentry; -+ h_inode = d_inode(h_d); -+ inode_lock_nested(h_inode, AuLsc_I_CHILD); -+ au_dtime_revert(a->dst_dt + AuCHILD); -+ inode_unlock(h_inode); -+ } -+ } -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+int aufs_rename(struct inode *_src_dir, struct dentry *_src_dentry, -+ struct inode *_dst_dir, struct dentry *_dst_dentry, -+ unsigned int _flags) -+{ -+ int err, lock_flags; -+ void *rev; -+ /* reduce stack space */ -+ struct au_ren_args *a; -+ struct au_pin pin; -+ -+ AuDbg("%pd, %pd, 0x%x\n", _src_dentry, _dst_dentry, _flags); -+ IMustLock(_src_dir); -+ IMustLock(_dst_dir); -+ -+ err = -EINVAL; -+ if (unlikely(_flags & RENAME_WHITEOUT)) -+ goto out; -+ -+ err = -ENOMEM; -+ BUILD_BUG_ON(sizeof(*a) > PAGE_SIZE); -+ a = kzalloc(sizeof(*a), GFP_NOFS); -+ if (unlikely(!a)) -+ goto out; -+ -+ a->flags = _flags; -+ BUILD_BUG_ON(sizeof(a->exchange) == sizeof(u8) -+ && RENAME_EXCHANGE > U8_MAX); -+ a->exchange = _flags & RENAME_EXCHANGE; -+ a->src_dir = _src_dir; -+ a->src_dentry = _src_dentry; -+ a->src_inode = NULL; -+ if (d_really_is_positive(a->src_dentry)) -+ a->src_inode = d_inode(a->src_dentry); -+ a->src_parent = a->src_dentry->d_parent; /* dir inode is locked */ -+ a->dst_dir = _dst_dir; -+ a->dst_dentry = _dst_dentry; -+ a->dst_inode = NULL; -+ if (d_really_is_positive(a->dst_dentry)) -+ a->dst_inode = d_inode(a->dst_dentry); -+ a->dst_parent = a->dst_dentry->d_parent; /* dir inode is locked */ -+ if (a->dst_inode) { -+ /* -+ * if EXCHANGE && src is non-dir && dst is dir, -+ * dst is not locked. -+ */ -+ /* IMustLock(a->dst_inode); */ -+ au_igrab(a->dst_inode); -+ } -+ -+ err = -ENOTDIR; -+ lock_flags = AuLock_FLUSH | AuLock_NOPLM | AuLock_GEN; -+ if (d_is_dir(a->src_dentry)) { -+ au_fset_ren(a->auren_flags, ISDIR_SRC); -+ if (unlikely(!a->exchange -+ && d_really_is_positive(a->dst_dentry) -+ && !d_is_dir(a->dst_dentry))) -+ goto out_free; -+ lock_flags |= AuLock_DIRS; -+ } -+ if (a->dst_inode && d_is_dir(a->dst_dentry)) { -+ au_fset_ren(a->auren_flags, ISDIR_DST); -+ if (unlikely(!a->exchange -+ && d_really_is_positive(a->src_dentry) -+ && !d_is_dir(a->src_dentry))) -+ goto out_free; -+ lock_flags |= AuLock_DIRS; -+ } -+ err = aufs_read_and_write_lock2(a->dst_dentry, a->src_dentry, -+ lock_flags); -+ if (unlikely(err)) -+ goto out_free; -+ -+ err = au_d_hashed_positive(a->src_dentry); -+ if (unlikely(err)) -+ goto out_unlock; -+ err = -ENOENT; -+ if (a->dst_inode) { -+ /* -+ * If it is a dir, VFS unhash it before this -+ * function. It means we cannot rely upon d_unhashed(). -+ */ -+ if (unlikely(!a->dst_inode->i_nlink)) -+ goto out_unlock; -+ if (!au_ftest_ren(a->auren_flags, ISDIR_DST)) { -+ err = au_d_hashed_positive(a->dst_dentry); -+ if (unlikely(err && !a->exchange)) -+ goto out_unlock; -+ } else if (unlikely(IS_DEADDIR(a->dst_inode))) -+ goto out_unlock; -+ } else if (unlikely(d_unhashed(a->dst_dentry))) -+ goto out_unlock; -+ -+ /* -+ * is it possible? -+ * yes, it happened (in linux-3.3-rcN) but I don't know why. -+ * there may exist a problem somewhere else. -+ */ -+ err = -EINVAL; -+ if (unlikely(d_inode(a->dst_parent) == d_inode(a->src_dentry))) -+ goto out_unlock; -+ -+ au_fset_ren(a->auren_flags, ISSAMEDIR); /* temporary */ -+ di_write_lock_parent(a->dst_parent); -+ -+ /* which branch we process */ -+ err = au_ren_wbr(a); -+ if (unlikely(err < 0)) -+ goto out_parent; -+ a->br = au_sbr(a->dst_dentry->d_sb, a->btgt); -+ a->h_path.mnt = au_br_mnt(a->br); -+ -+ /* are they available to be renamed */ -+ err = au_ren_may_dir(a); -+ if (unlikely(err)) -+ goto out_children; -+ -+ /* prepare the writable parent dir on the same branch */ -+ if (a->dst_btop == a->btgt) { -+ au_fset_ren(a->auren_flags, WHDST); -+ } else { -+ err = au_cpup_dirs(a->dst_dentry, a->btgt); -+ if (unlikely(err)) -+ goto out_children; -+ } -+ -+ err = 0; -+ if (!a->exchange) { -+ if (a->src_dir != a->dst_dir) { -+ /* -+ * this temporary unlock is safe, -+ * because both dir->i_mutex are locked. -+ */ -+ di_write_unlock(a->dst_parent); -+ di_write_lock_parent(a->src_parent); -+ err = au_wr_dir_need_wh(a->src_dentry, -+ au_ftest_ren(a->auren_flags, -+ ISDIR_SRC), -+ &a->btgt); -+ di_write_unlock(a->src_parent); -+ di_write_lock2_parent(a->src_parent, a->dst_parent, -+ /*isdir*/1); -+ au_fclr_ren(a->auren_flags, ISSAMEDIR); -+ } else -+ err = au_wr_dir_need_wh(a->src_dentry, -+ au_ftest_ren(a->auren_flags, -+ ISDIR_SRC), -+ &a->btgt); -+ } -+ if (unlikely(err < 0)) -+ goto out_children; -+ if (err) -+ au_fset_ren(a->auren_flags, WHSRC); -+ -+ /* cpup src */ -+ if (a->src_btop != a->btgt) { -+ err = au_pin(&pin, a->src_dentry, a->btgt, -+ au_opt_udba(a->src_dentry->d_sb), -+ AuPin_DI_LOCKED | AuPin_MNT_WRITE); -+ if (!err) { -+ struct au_cp_generic cpg = { -+ .dentry = a->src_dentry, -+ .bdst = a->btgt, -+ .bsrc = a->src_btop, -+ .len = -1, -+ .pin = &pin, -+ .flags = AuCpup_DTIME | AuCpup_HOPEN -+ }; -+ AuDebugOn(au_dbtop(a->src_dentry) != a->src_btop); -+ err = au_sio_cpup_simple(&cpg); -+ au_unpin(&pin); -+ } -+ if (unlikely(err)) -+ goto out_children; -+ a->src_btop = a->btgt; -+ a->src_h_dentry = au_h_dptr(a->src_dentry, a->btgt); -+ if (!a->exchange) -+ au_fset_ren(a->auren_flags, WHSRC); -+ } -+ -+ /* cpup dst */ -+ if (a->exchange && a->dst_inode -+ && a->dst_btop != a->btgt) { -+ err = au_pin(&pin, a->dst_dentry, a->btgt, -+ au_opt_udba(a->dst_dentry->d_sb), -+ AuPin_DI_LOCKED | AuPin_MNT_WRITE); -+ if (!err) { -+ struct au_cp_generic cpg = { -+ .dentry = a->dst_dentry, -+ .bdst = a->btgt, -+ .bsrc = a->dst_btop, -+ .len = -1, -+ .pin = &pin, -+ .flags = AuCpup_DTIME | AuCpup_HOPEN -+ }; -+ err = au_sio_cpup_simple(&cpg); -+ au_unpin(&pin); -+ } -+ if (unlikely(err)) -+ goto out_children; -+ a->dst_btop = a->btgt; -+ a->dst_h_dentry = au_h_dptr(a->dst_dentry, a->btgt); -+ } -+ -+ /* lock them all */ -+ err = au_ren_lock(a); -+ if (unlikely(err)) -+ /* leave the copied-up one */ -+ goto out_children; -+ -+ if (!a->exchange) { -+ if (!au_opt_test(au_mntflags(a->dst_dir->i_sb), UDBA_NONE)) -+ err = au_may_ren(a); -+ else if (unlikely(a->dst_dentry->d_name.len > AUFS_MAX_NAMELEN)) -+ err = -ENAMETOOLONG; -+ if (unlikely(err)) -+ goto out_hdir; -+ } -+ -+ /* store timestamps to be revertible */ -+ au_ren_dt(a); -+ -+ /* store dirren info */ -+ if (au_ftest_ren(a->auren_flags, DIRREN)) { -+ err = au_dr_rename(a->src_dentry, a->btgt, -+ &a->dst_dentry->d_name, &rev); -+ AuTraceErr(err); -+ if (unlikely(err)) -+ goto out_dt; -+ } -+ -+ /* here we go */ -+ err = do_rename(a); -+ if (unlikely(err)) -+ goto out_dirren; -+ -+ if (au_ftest_ren(a->auren_flags, DIRREN)) -+ au_dr_rename_fin(a->src_dentry, a->btgt, rev); -+ -+ /* update dir attributes */ -+ au_ren_refresh_dir(a); -+ -+ /* dput/iput all lower dentries */ -+ au_ren_refresh(a); -+ -+ goto out_hdir; /* success */ -+ -+out_dirren: -+ if (au_ftest_ren(a->auren_flags, DIRREN)) -+ au_dr_rename_rev(a->src_dentry, a->btgt, rev); -+out_dt: -+ au_ren_rev_dt(err, a); -+out_hdir: -+ au_ren_unlock(a); -+out_children: -+ au_nhash_wh_free(&a->whlist); -+ if (err && a->dst_inode && a->dst_btop != a->btgt) { -+ AuDbg("btop %d, btgt %d\n", a->dst_btop, a->btgt); -+ au_set_h_dptr(a->dst_dentry, a->btgt, NULL); -+ au_set_dbtop(a->dst_dentry, a->dst_btop); -+ } -+out_parent: -+ if (!err) { -+ if (d_unhashed(a->src_dentry)) -+ au_fset_ren(a->auren_flags, DROPPED_SRC); -+ if (d_unhashed(a->dst_dentry)) -+ au_fset_ren(a->auren_flags, DROPPED_DST); -+ if (!a->exchange) -+ d_move(a->src_dentry, a->dst_dentry); -+ else { -+ d_exchange(a->src_dentry, a->dst_dentry); -+ if (au_ftest_ren(a->auren_flags, DROPPED_DST)) -+ d_drop(a->dst_dentry); -+ } -+ if (au_ftest_ren(a->auren_flags, DROPPED_SRC)) -+ d_drop(a->src_dentry); -+ } else { -+ au_update_dbtop(a->dst_dentry); -+ if (!a->dst_inode) -+ d_drop(a->dst_dentry); -+ } -+ if (au_ftest_ren(a->auren_flags, ISSAMEDIR)) -+ di_write_unlock(a->dst_parent); -+ else -+ di_write_unlock2(a->src_parent, a->dst_parent); -+out_unlock: -+ aufs_read_and_write_unlock2(a->dst_dentry, a->src_dentry); -+out_free: -+ iput(a->dst_inode); -+ if (a->thargs) -+ au_whtmp_rmdir_free(a->thargs); -+ au_kfree_rcu(a); -+out: -+ AuTraceErr(err); -+ return err; -+} -diff --git a/fs/aufs/iinfo.c b/fs/aufs/iinfo.c -new file mode 100644 -index 000000000000..5a837d7d0a33 ---- /dev/null -+++ b/fs/aufs/iinfo.c -@@ -0,0 +1,273 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * inode private data -+ */ -+ -+#include "aufs.h" -+ -+struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex) -+{ -+ struct inode *h_inode; -+ struct au_hinode *hinode; -+ -+ IiMustAnyLock(inode); -+ -+ hinode = au_hinode(au_ii(inode), bindex); -+ h_inode = hinode->hi_inode; -+ AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0); -+ return h_inode; -+} -+ -+/* todo: hard/soft set? */ -+void au_hiput(struct au_hinode *hinode) -+{ -+ au_hn_free(hinode); -+ dput(hinode->hi_whdentry); -+ iput(hinode->hi_inode); -+} -+ -+unsigned int au_hi_flags(struct inode *inode, int isdir) -+{ -+ unsigned int flags; -+ const unsigned int mnt_flags = au_mntflags(inode->i_sb); -+ -+ flags = 0; -+ if (au_opt_test(mnt_flags, XINO)) -+ au_fset_hi(flags, XINO); -+ if (isdir && au_opt_test(mnt_flags, UDBA_HNOTIFY)) -+ au_fset_hi(flags, HNOTIFY); -+ return flags; -+} -+ -+void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex, -+ struct inode *h_inode, unsigned int flags) -+{ -+ struct au_hinode *hinode; -+ struct inode *hi; -+ struct au_iinfo *iinfo = au_ii(inode); -+ -+ IiMustWriteLock(inode); -+ -+ hinode = au_hinode(iinfo, bindex); -+ hi = hinode->hi_inode; -+ AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0); -+ -+ if (hi) -+ au_hiput(hinode); -+ hinode->hi_inode = h_inode; -+ if (h_inode) { -+ int err; -+ struct super_block *sb = inode->i_sb; -+ struct au_branch *br; -+ -+ AuDebugOn(inode->i_mode -+ && (h_inode->i_mode & S_IFMT) -+ != (inode->i_mode & S_IFMT)); -+ if (bindex == iinfo->ii_btop) -+ au_cpup_igen(inode, h_inode); -+ br = au_sbr(sb, bindex); -+ hinode->hi_id = br->br_id; -+ if (au_ftest_hi(flags, XINO)) { -+ err = au_xino_write(sb, bindex, h_inode->i_ino, -+ inode->i_ino); -+ if (unlikely(err)) -+ AuIOErr1("failed au_xino_write() %d\n", err); -+ } -+ -+ if (au_ftest_hi(flags, HNOTIFY) -+ && au_br_hnotifyable(br->br_perm)) { -+ err = au_hn_alloc(hinode, inode); -+ if (unlikely(err)) -+ AuIOErr1("au_hn_alloc() %d\n", err); -+ } -+ } -+} -+ -+void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex, -+ struct dentry *h_wh) -+{ -+ struct au_hinode *hinode; -+ -+ IiMustWriteLock(inode); -+ -+ hinode = au_hinode(au_ii(inode), bindex); -+ AuDebugOn(hinode->hi_whdentry); -+ hinode->hi_whdentry = h_wh; -+} -+ -+void au_update_iigen(struct inode *inode, int half) -+{ -+ struct au_iinfo *iinfo; -+ struct au_iigen *iigen; -+ unsigned int sigen; -+ -+ sigen = au_sigen(inode->i_sb); -+ iinfo = au_ii(inode); -+ iigen = &iinfo->ii_generation; -+ spin_lock(&iigen->ig_spin); -+ iigen->ig_generation = sigen; -+ if (half) -+ au_ig_fset(iigen->ig_flags, HALF_REFRESHED); -+ else -+ au_ig_fclr(iigen->ig_flags, HALF_REFRESHED); -+ spin_unlock(&iigen->ig_spin); -+} -+ -+/* it may be called at remount time, too */ -+void au_update_ibrange(struct inode *inode, int do_put_zero) -+{ -+ struct au_iinfo *iinfo; -+ aufs_bindex_t bindex, bbot; -+ -+ AuDebugOn(au_is_bad_inode(inode)); -+ IiMustWriteLock(inode); -+ -+ iinfo = au_ii(inode); -+ if (do_put_zero && iinfo->ii_btop >= 0) { -+ for (bindex = iinfo->ii_btop; bindex <= iinfo->ii_bbot; -+ bindex++) { -+ struct inode *h_i; -+ -+ h_i = au_hinode(iinfo, bindex)->hi_inode; -+ if (h_i -+ && !h_i->i_nlink -+ && !(h_i->i_state & I_LINKABLE)) -+ au_set_h_iptr(inode, bindex, NULL, 0); -+ } -+ } -+ -+ iinfo->ii_btop = -1; -+ iinfo->ii_bbot = -1; -+ bbot = au_sbbot(inode->i_sb); -+ for (bindex = 0; bindex <= bbot; bindex++) -+ if (au_hinode(iinfo, bindex)->hi_inode) { -+ iinfo->ii_btop = bindex; -+ break; -+ } -+ if (iinfo->ii_btop >= 0) -+ for (bindex = bbot; bindex >= iinfo->ii_btop; bindex--) -+ if (au_hinode(iinfo, bindex)->hi_inode) { -+ iinfo->ii_bbot = bindex; -+ break; -+ } -+ AuDebugOn(iinfo->ii_btop > iinfo->ii_bbot); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+void au_icntnr_init_once(void *_c) -+{ -+ struct au_icntnr *c = _c; -+ struct au_iinfo *iinfo = &c->iinfo; -+ -+ spin_lock_init(&iinfo->ii_generation.ig_spin); -+ au_rw_init(&iinfo->ii_rwsem); -+ inode_init_once(&c->vfs_inode); -+} -+ -+void au_hinode_init(struct au_hinode *hinode) -+{ -+ hinode->hi_inode = NULL; -+ hinode->hi_id = -1; -+ au_hn_init(hinode); -+ hinode->hi_whdentry = NULL; -+} -+ -+int au_iinfo_init(struct inode *inode) -+{ -+ struct au_iinfo *iinfo; -+ struct super_block *sb; -+ struct au_hinode *hi; -+ int nbr, i; -+ -+ sb = inode->i_sb; -+ iinfo = &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo); -+ nbr = au_sbbot(sb) + 1; -+ if (unlikely(nbr <= 0)) -+ nbr = 1; -+ hi = kmalloc_array(nbr, sizeof(*iinfo->ii_hinode), GFP_NOFS); -+ if (hi) { -+ au_lcnt_inc(&au_sbi(sb)->si_ninodes); -+ -+ iinfo->ii_hinode = hi; -+ for (i = 0; i < nbr; i++, hi++) -+ au_hinode_init(hi); -+ -+ iinfo->ii_generation.ig_generation = au_sigen(sb); -+ iinfo->ii_btop = -1; -+ iinfo->ii_bbot = -1; -+ iinfo->ii_vdir = NULL; -+ return 0; -+ } -+ return -ENOMEM; -+} -+ -+int au_hinode_realloc(struct au_iinfo *iinfo, int nbr, int may_shrink) -+{ -+ int err, i; -+ struct au_hinode *hip; -+ -+ AuRwMustWriteLock(&iinfo->ii_rwsem); -+ -+ err = -ENOMEM; -+ hip = au_krealloc(iinfo->ii_hinode, sizeof(*hip) * nbr, GFP_NOFS, -+ may_shrink); -+ if (hip) { -+ iinfo->ii_hinode = hip; -+ i = iinfo->ii_bbot + 1; -+ hip += i; -+ for (; i < nbr; i++, hip++) -+ au_hinode_init(hip); -+ err = 0; -+ } -+ -+ return err; -+} -+ -+void au_iinfo_fin(struct inode *inode) -+{ -+ struct au_iinfo *iinfo; -+ struct au_hinode *hi; -+ struct super_block *sb; -+ aufs_bindex_t bindex, bbot; -+ const unsigned char unlinked = !inode->i_nlink; -+ -+ AuDebugOn(au_is_bad_inode(inode)); -+ -+ sb = inode->i_sb; -+ au_lcnt_dec(&au_sbi(sb)->si_ninodes); -+ if (si_pid_test(sb)) -+ au_xino_delete_inode(inode, unlinked); -+ else { -+ /* -+ * it is safe to hide the dependency between sbinfo and -+ * sb->s_umount. -+ */ -+ lockdep_off(); -+ si_noflush_read_lock(sb); -+ au_xino_delete_inode(inode, unlinked); -+ si_read_unlock(sb); -+ lockdep_on(); -+ } -+ -+ iinfo = au_ii(inode); -+ if (iinfo->ii_vdir) -+ au_vdir_free(iinfo->ii_vdir); -+ -+ bindex = iinfo->ii_btop; -+ if (bindex >= 0) { -+ hi = au_hinode(iinfo, bindex); -+ bbot = iinfo->ii_bbot; -+ while (bindex++ <= bbot) { -+ if (hi->hi_inode) -+ au_hiput(hi); -+ hi++; -+ } -+ } -+ au_kfree_rcu(iinfo->ii_hinode); -+ AuRwDestroy(&iinfo->ii_rwsem); -+} -diff --git a/fs/aufs/inode.c b/fs/aufs/inode.c -new file mode 100644 -index 000000000000..c071e525f499 ---- /dev/null -+++ b/fs/aufs/inode.c -@@ -0,0 +1,516 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * inode functions -+ */ -+ -+#include -+#include "aufs.h" -+ -+struct inode *au_igrab(struct inode *inode) -+{ -+ if (inode) { -+ AuDebugOn(!atomic_read(&inode->i_count)); -+ ihold(inode); -+ } -+ return inode; -+} -+ -+static void au_refresh_hinode_attr(struct inode *inode, int do_version) -+{ -+ au_cpup_attr_all(inode, /*force*/0); -+ au_update_iigen(inode, /*half*/1); -+ if (do_version) -+ inode_inc_iversion(inode); -+} -+ -+static int au_ii_refresh(struct inode *inode, int *update) -+{ -+ int err, e, nbr; -+ umode_t type; -+ aufs_bindex_t bindex, new_bindex; -+ struct super_block *sb; -+ struct au_iinfo *iinfo; -+ struct au_hinode *p, *q, tmp; -+ -+ AuDebugOn(au_is_bad_inode(inode)); -+ IiMustWriteLock(inode); -+ -+ *update = 0; -+ sb = inode->i_sb; -+ nbr = au_sbbot(sb) + 1; -+ type = inode->i_mode & S_IFMT; -+ iinfo = au_ii(inode); -+ err = au_hinode_realloc(iinfo, nbr, /*may_shrink*/0); -+ if (unlikely(err)) -+ goto out; -+ -+ AuDebugOn(iinfo->ii_btop < 0); -+ p = au_hinode(iinfo, iinfo->ii_btop); -+ for (bindex = iinfo->ii_btop; bindex <= iinfo->ii_bbot; -+ bindex++, p++) { -+ if (!p->hi_inode) -+ continue; -+ -+ AuDebugOn(type != (p->hi_inode->i_mode & S_IFMT)); -+ new_bindex = au_br_index(sb, p->hi_id); -+ if (new_bindex == bindex) -+ continue; -+ -+ if (new_bindex < 0) { -+ *update = 1; -+ au_hiput(p); -+ p->hi_inode = NULL; -+ continue; -+ } -+ -+ if (new_bindex < iinfo->ii_btop) -+ iinfo->ii_btop = new_bindex; -+ if (iinfo->ii_bbot < new_bindex) -+ iinfo->ii_bbot = new_bindex; -+ /* swap two lower inode, and loop again */ -+ q = au_hinode(iinfo, new_bindex); -+ tmp = *q; -+ *q = *p; -+ *p = tmp; -+ if (tmp.hi_inode) { -+ bindex--; -+ p--; -+ } -+ } -+ au_update_ibrange(inode, /*do_put_zero*/0); -+ au_hinode_realloc(iinfo, nbr, /*may_shrink*/1); /* harmless if err */ -+ e = au_dy_irefresh(inode); -+ if (unlikely(e && !err)) -+ err = e; -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+void au_refresh_iop(struct inode *inode, int force_getattr) -+{ -+ int type; -+ struct au_sbinfo *sbi = au_sbi(inode->i_sb); -+ const struct inode_operations *iop -+ = force_getattr ? aufs_iop : sbi->si_iop_array; -+ -+ if (inode->i_op == iop) -+ return; -+ -+ switch (inode->i_mode & S_IFMT) { -+ case S_IFDIR: -+ type = AuIop_DIR; -+ break; -+ case S_IFLNK: -+ type = AuIop_SYMLINK; -+ break; -+ default: -+ type = AuIop_OTHER; -+ break; -+ } -+ -+ inode->i_op = iop + type; -+ /* unnecessary smp_wmb() */ -+} -+ -+int au_refresh_hinode_self(struct inode *inode) -+{ -+ int err, update; -+ -+ err = au_ii_refresh(inode, &update); -+ if (!err) -+ au_refresh_hinode_attr(inode, update && S_ISDIR(inode->i_mode)); -+ -+ AuTraceErr(err); -+ return err; -+} -+ -+int au_refresh_hinode(struct inode *inode, struct dentry *dentry) -+{ -+ int err, e, update; -+ unsigned int flags; -+ umode_t mode; -+ aufs_bindex_t bindex, bbot; -+ unsigned char isdir; -+ struct au_hinode *p; -+ struct au_iinfo *iinfo; -+ -+ err = au_ii_refresh(inode, &update); -+ if (unlikely(err)) -+ goto out; -+ -+ update = 0; -+ iinfo = au_ii(inode); -+ p = au_hinode(iinfo, iinfo->ii_btop); -+ mode = (inode->i_mode & S_IFMT); -+ isdir = S_ISDIR(mode); -+ flags = au_hi_flags(inode, isdir); -+ bbot = au_dbbot(dentry); -+ for (bindex = au_dbtop(dentry); bindex <= bbot; bindex++) { -+ struct inode *h_i, *h_inode; -+ struct dentry *h_d; -+ -+ h_d = au_h_dptr(dentry, bindex); -+ if (!h_d || d_is_negative(h_d)) -+ continue; -+ -+ h_inode = d_inode(h_d); -+ AuDebugOn(mode != (h_inode->i_mode & S_IFMT)); -+ if (iinfo->ii_btop <= bindex && bindex <= iinfo->ii_bbot) { -+ h_i = au_h_iptr(inode, bindex); -+ if (h_i) { -+ if (h_i == h_inode) -+ continue; -+ err = -EIO; -+ break; -+ } -+ } -+ if (bindex < iinfo->ii_btop) -+ iinfo->ii_btop = bindex; -+ if (iinfo->ii_bbot < bindex) -+ iinfo->ii_bbot = bindex; -+ au_set_h_iptr(inode, bindex, au_igrab(h_inode), flags); -+ update = 1; -+ } -+ au_update_ibrange(inode, /*do_put_zero*/0); -+ e = au_dy_irefresh(inode); -+ if (unlikely(e && !err)) -+ err = e; -+ if (!err) -+ au_refresh_hinode_attr(inode, update && isdir); -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+static int set_inode(struct inode *inode, struct dentry *dentry) -+{ -+ int err; -+ unsigned int flags; -+ umode_t mode; -+ aufs_bindex_t bindex, btop, btail; -+ unsigned char isdir; -+ struct dentry *h_dentry; -+ struct inode *h_inode; -+ struct au_iinfo *iinfo; -+ const struct inode_operations *iop; -+ -+ IiMustWriteLock(inode); -+ -+ err = 0; -+ isdir = 0; -+ iop = au_sbi(inode->i_sb)->si_iop_array; -+ btop = au_dbtop(dentry); -+ h_dentry = au_h_dptr(dentry, btop); -+ h_inode = d_inode(h_dentry); -+ mode = h_inode->i_mode; -+ switch (mode & S_IFMT) { -+ case S_IFREG: -+ btail = au_dbtail(dentry); -+ inode->i_op = iop + AuIop_OTHER; -+ inode->i_fop = &aufs_file_fop; -+ err = au_dy_iaop(inode, btop, h_inode); -+ if (unlikely(err)) -+ goto out; -+ break; -+ case S_IFDIR: -+ isdir = 1; -+ btail = au_dbtaildir(dentry); -+ inode->i_op = iop + AuIop_DIR; -+ inode->i_fop = &aufs_dir_fop; -+ break; -+ case S_IFLNK: -+ btail = au_dbtail(dentry); -+ inode->i_op = iop + AuIop_SYMLINK; -+ break; -+ case S_IFBLK: -+ case S_IFCHR: -+ case S_IFIFO: -+ case S_IFSOCK: -+ btail = au_dbtail(dentry); -+ inode->i_op = iop + AuIop_OTHER; -+ init_special_inode(inode, mode, h_inode->i_rdev); -+ break; -+ default: -+ AuIOErr("Unknown file type 0%o\n", mode); -+ err = -EIO; -+ goto out; -+ } -+ -+ /* do not set hnotify for whiteouted dirs (SHWH mode) */ -+ flags = au_hi_flags(inode, isdir); -+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH) -+ && au_ftest_hi(flags, HNOTIFY) -+ && dentry->d_name.len > AUFS_WH_PFX_LEN -+ && !memcmp(dentry->d_name.name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) -+ au_fclr_hi(flags, HNOTIFY); -+ iinfo = au_ii(inode); -+ iinfo->ii_btop = btop; -+ iinfo->ii_bbot = btail; -+ for (bindex = btop; bindex <= btail; bindex++) { -+ h_dentry = au_h_dptr(dentry, bindex); -+ if (h_dentry) -+ au_set_h_iptr(inode, bindex, -+ au_igrab(d_inode(h_dentry)), flags); -+ } -+ au_cpup_attr_all(inode, /*force*/1); -+ /* -+ * to force calling aufs_get_acl() every time, -+ * do not call cache_no_acl() for aufs inode. -+ */ -+ -+out: -+ return err; -+} -+ -+/* -+ * successful returns with iinfo write_locked -+ * minus: errno -+ * zero: success, matched -+ * plus: no error, but unmatched -+ */ -+static int reval_inode(struct inode *inode, struct dentry *dentry) -+{ -+ int err; -+ unsigned int gen, igflags; -+ aufs_bindex_t bindex, bbot; -+ struct inode *h_inode, *h_dinode; -+ struct dentry *h_dentry; -+ -+ /* -+ * before this function, if aufs got any iinfo lock, it must be only -+ * one, the parent dir. -+ * it can happen by UDBA and the obsoleted inode number. -+ */ -+ err = -EIO; -+ if (unlikely(inode->i_ino == parent_ino(dentry))) -+ goto out; -+ -+ err = 1; -+ ii_write_lock_new_child(inode); -+ h_dentry = au_h_dptr(dentry, au_dbtop(dentry)); -+ h_dinode = d_inode(h_dentry); -+ bbot = au_ibbot(inode); -+ for (bindex = au_ibtop(inode); bindex <= bbot; bindex++) { -+ h_inode = au_h_iptr(inode, bindex); -+ if (!h_inode || h_inode != h_dinode) -+ continue; -+ -+ err = 0; -+ gen = au_iigen(inode, &igflags); -+ if (gen == au_digen(dentry) -+ && !au_ig_ftest(igflags, HALF_REFRESHED)) -+ break; -+ -+ /* fully refresh inode using dentry */ -+ err = au_refresh_hinode(inode, dentry); -+ if (!err) -+ au_update_iigen(inode, /*half*/0); -+ break; -+ } -+ -+ if (unlikely(err)) -+ ii_write_unlock(inode); -+out: -+ return err; -+} -+ -+int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, -+ unsigned int d_type, ino_t *ino) -+{ -+ int err, idx; -+ const int isnondir = d_type != DT_DIR; -+ -+ /* prevent hardlinked inode number from race condition */ -+ if (isnondir) { -+ err = au_xinondir_enter(sb, bindex, h_ino, &idx); -+ if (unlikely(err)) -+ goto out; -+ } -+ -+ err = au_xino_read(sb, bindex, h_ino, ino); -+ if (unlikely(err)) -+ goto out_xinondir; -+ -+ if (!*ino) { -+ err = -EIO; -+ *ino = au_xino_new_ino(sb); -+ if (unlikely(!*ino)) -+ goto out_xinondir; -+ err = au_xino_write(sb, bindex, h_ino, *ino); -+ if (unlikely(err)) -+ goto out_xinondir; -+ } -+ -+out_xinondir: -+ if (isnondir && idx >= 0) -+ au_xinondir_leave(sb, bindex, h_ino, idx); -+out: -+ return err; -+} -+ -+/* successful returns with iinfo write_locked */ -+/* todo: return with unlocked? */ -+struct inode *au_new_inode(struct dentry *dentry, int must_new) -+{ -+ struct inode *inode, *h_inode; -+ struct dentry *h_dentry; -+ struct super_block *sb; -+ ino_t h_ino, ino; -+ int err, idx, hlinked; -+ aufs_bindex_t btop; -+ -+ sb = dentry->d_sb; -+ btop = au_dbtop(dentry); -+ h_dentry = au_h_dptr(dentry, btop); -+ h_inode = d_inode(h_dentry); -+ h_ino = h_inode->i_ino; -+ hlinked = !d_is_dir(h_dentry) && h_inode->i_nlink > 1; -+ -+new_ino: -+ /* -+ * stop 'race'-ing between hardlinks under different -+ * parents. -+ */ -+ if (hlinked) { -+ err = au_xinondir_enter(sb, btop, h_ino, &idx); -+ inode = ERR_PTR(err); -+ if (unlikely(err)) -+ goto out; -+ } -+ -+ err = au_xino_read(sb, btop, h_ino, &ino); -+ inode = ERR_PTR(err); -+ if (unlikely(err)) -+ goto out_xinondir; -+ -+ if (!ino) { -+ ino = au_xino_new_ino(sb); -+ if (unlikely(!ino)) { -+ inode = ERR_PTR(-EIO); -+ goto out_xinondir; -+ } -+ } -+ -+ AuDbg("i%lu\n", (unsigned long)ino); -+ inode = au_iget_locked(sb, ino); -+ err = PTR_ERR(inode); -+ if (IS_ERR(inode)) -+ goto out_xinondir; -+ -+ AuDbg("%lx, new %d\n", inode->i_state, !!(inode->i_state & I_NEW)); -+ if (inode->i_state & I_NEW) { -+ ii_write_lock_new_child(inode); -+ err = set_inode(inode, dentry); -+ if (!err) { -+ unlock_new_inode(inode); -+ goto out_xinondir; /* success */ -+ } -+ -+ /* -+ * iget_failed() calls iput(), but we need to call -+ * ii_write_unlock() after iget_failed(). so dirty hack for -+ * i_count. -+ */ -+ atomic_inc(&inode->i_count); -+ iget_failed(inode); -+ ii_write_unlock(inode); -+ au_xino_write(sb, btop, h_ino, /*ino*/0); -+ /* ignore this error */ -+ goto out_iput; -+ } else if (!must_new && !IS_DEADDIR(inode) && inode->i_nlink) { -+ /* -+ * horrible race condition between lookup, readdir and copyup -+ * (or something). -+ */ -+ if (hlinked && idx >= 0) -+ au_xinondir_leave(sb, btop, h_ino, idx); -+ err = reval_inode(inode, dentry); -+ if (unlikely(err < 0)) { -+ hlinked = 0; -+ goto out_iput; -+ } -+ if (!err) -+ goto out; /* success */ -+ else if (hlinked && idx >= 0) { -+ err = au_xinondir_enter(sb, btop, h_ino, &idx); -+ if (unlikely(err)) { -+ iput(inode); -+ inode = ERR_PTR(err); -+ goto out; -+ } -+ } -+ } -+ -+ if (unlikely(au_test_fs_unique_ino(h_inode))) -+ AuWarn1("Warning: Un-notified UDBA or repeatedly renamed dir," -+ " b%d, %s, %pd, hi%lu, i%lu.\n", -+ btop, au_sbtype(h_dentry->d_sb), dentry, -+ (unsigned long)h_ino, (unsigned long)ino); -+ ino = 0; -+ err = au_xino_write(sb, btop, h_ino, /*ino*/0); -+ if (!err) { -+ iput(inode); -+ if (hlinked && idx >= 0) -+ au_xinondir_leave(sb, btop, h_ino, idx); -+ goto new_ino; -+ } -+ -+out_iput: -+ iput(inode); -+ inode = ERR_PTR(err); -+out_xinondir: -+ if (hlinked && idx >= 0) -+ au_xinondir_leave(sb, btop, h_ino, idx); -+out: -+ return inode; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+int au_test_ro(struct super_block *sb, aufs_bindex_t bindex, -+ struct inode *inode) -+{ -+ int err; -+ struct inode *hi; -+ -+ err = au_br_rdonly(au_sbr(sb, bindex)); -+ -+ /* pseudo-link after flushed may happen out of bounds */ -+ if (!err -+ && inode -+ && au_ibtop(inode) <= bindex -+ && bindex <= au_ibbot(inode)) { -+ /* -+ * permission check is unnecessary since vfsub routine -+ * will be called later -+ */ -+ hi = au_h_iptr(inode, bindex); -+ if (hi) -+ err = IS_IMMUTABLE(hi) ? -EROFS : 0; -+ } -+ -+ return err; -+} -+ -+int au_test_h_perm(struct inode *h_inode, int mask) -+{ -+ if (uid_eq(current_fsuid(), GLOBAL_ROOT_UID)) -+ return 0; -+ return inode_permission(h_inode, mask); -+} -+ -+int au_test_h_perm_sio(struct inode *h_inode, int mask) -+{ -+ if (au_test_nfs(h_inode->i_sb) -+ && (mask & MAY_WRITE) -+ && S_ISDIR(h_inode->i_mode)) -+ mask |= MAY_READ; /* force permission check */ -+ return au_test_h_perm(h_inode, mask); -+} -diff --git a/fs/aufs/inode.h b/fs/aufs/inode.h -new file mode 100644 -index 000000000000..833d2ce64e81 ---- /dev/null -+++ b/fs/aufs/inode.h -@@ -0,0 +1,685 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * inode operations -+ */ -+ -+#ifndef __AUFS_INODE_H__ -+#define __AUFS_INODE_H__ -+ -+#ifdef __KERNEL__ -+ -+#include -+#include "rwsem.h" -+ -+struct vfsmount; -+ -+struct au_hnotify { -+#ifdef CONFIG_AUFS_HNOTIFY -+#ifdef CONFIG_AUFS_HFSNOTIFY -+ /* never use fsnotify_add_vfsmount_mark() */ -+ struct fsnotify_mark hn_mark; -+#endif -+ struct inode *hn_aufs_inode; /* no get/put */ -+ struct rcu_head rcu; -+#endif -+} ____cacheline_aligned_in_smp; -+ -+struct au_hinode { -+ struct inode *hi_inode; -+ aufs_bindex_t hi_id; -+#ifdef CONFIG_AUFS_HNOTIFY -+ struct au_hnotify *hi_notify; -+#endif -+ -+ /* reference to the copied-up whiteout with get/put */ -+ struct dentry *hi_whdentry; -+}; -+ -+/* ig_flags */ -+#define AuIG_HALF_REFRESHED 1 -+#define au_ig_ftest(flags, name) ((flags) & AuIG_##name) -+#define au_ig_fset(flags, name) \ -+ do { (flags) |= AuIG_##name; } while (0) -+#define au_ig_fclr(flags, name) \ -+ do { (flags) &= ~AuIG_##name; } while (0) -+ -+struct au_iigen { -+ spinlock_t ig_spin; -+ __u32 ig_generation, ig_flags; -+}; -+ -+struct au_vdir; -+struct au_iinfo { -+ struct au_iigen ii_generation; -+ struct super_block *ii_hsb1; /* no get/put */ -+ -+ struct au_rwsem ii_rwsem; -+ aufs_bindex_t ii_btop, ii_bbot; -+ __u32 ii_higen; -+ struct au_hinode *ii_hinode; -+ struct au_vdir *ii_vdir; -+}; -+ -+struct au_icntnr { -+ struct au_iinfo iinfo; -+ struct inode vfs_inode; -+ struct hlist_bl_node plink; -+ struct rcu_head rcu; -+} ____cacheline_aligned_in_smp; -+ -+/* au_pin flags */ -+#define AuPin_DI_LOCKED 1 -+#define AuPin_MNT_WRITE (1 << 1) -+#define au_ftest_pin(flags, name) ((flags) & AuPin_##name) -+#define au_fset_pin(flags, name) \ -+ do { (flags) |= AuPin_##name; } while (0) -+#define au_fclr_pin(flags, name) \ -+ do { (flags) &= ~AuPin_##name; } while (0) -+ -+struct au_pin { -+ /* input */ -+ struct dentry *dentry; -+ unsigned int udba; -+ unsigned char lsc_di, lsc_hi, flags; -+ aufs_bindex_t bindex; -+ -+ /* output */ -+ struct dentry *parent; -+ struct au_hinode *hdir; -+ struct vfsmount *h_mnt; -+ -+ /* temporary unlock/relock for copyup */ -+ struct dentry *h_dentry, *h_parent; -+ struct au_branch *br; -+ struct task_struct *task; -+}; -+ -+void au_pin_hdir_unlock(struct au_pin *p); -+int au_pin_hdir_lock(struct au_pin *p); -+int au_pin_hdir_relock(struct au_pin *p); -+void au_pin_hdir_acquire_nest(struct au_pin *p); -+void au_pin_hdir_release(struct au_pin *p); -+ -+/* ---------------------------------------------------------------------- */ -+ -+static inline struct au_iinfo *au_ii(struct inode *inode) -+{ -+ BUG_ON(is_bad_inode(inode)); -+ return &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* inode.c */ -+struct inode *au_igrab(struct inode *inode); -+void au_refresh_iop(struct inode *inode, int force_getattr); -+int au_refresh_hinode_self(struct inode *inode); -+int au_refresh_hinode(struct inode *inode, struct dentry *dentry); -+int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, -+ unsigned int d_type, ino_t *ino); -+struct inode *au_new_inode(struct dentry *dentry, int must_new); -+int au_test_ro(struct super_block *sb, aufs_bindex_t bindex, -+ struct inode *inode); -+int au_test_h_perm(struct inode *h_inode, int mask); -+int au_test_h_perm_sio(struct inode *h_inode, int mask); -+ -+static inline int au_wh_ino(struct super_block *sb, aufs_bindex_t bindex, -+ ino_t h_ino, unsigned int d_type, ino_t *ino) -+{ -+#ifdef CONFIG_AUFS_SHWH -+ return au_ino(sb, bindex, h_ino, d_type, ino); -+#else -+ return 0; -+#endif -+} -+ -+/* i_op.c */ -+enum { -+ AuIop_SYMLINK, -+ AuIop_DIR, -+ AuIop_OTHER, -+ AuIop_Last -+}; -+extern struct inode_operations aufs_iop[AuIop_Last], /* not const */ -+ aufs_iop_nogetattr[AuIop_Last]; -+ -+/* au_wr_dir flags */ -+#define AuWrDir_ADD_ENTRY 1 -+#define AuWrDir_ISDIR (1 << 1) -+#define AuWrDir_TMPFILE (1 << 2) -+#define au_ftest_wrdir(flags, name) ((flags) & AuWrDir_##name) -+#define au_fset_wrdir(flags, name) \ -+ do { (flags) |= AuWrDir_##name; } while (0) -+#define au_fclr_wrdir(flags, name) \ -+ do { (flags) &= ~AuWrDir_##name; } while (0) -+ -+struct au_wr_dir_args { -+ aufs_bindex_t force_btgt; -+ unsigned char flags; -+}; -+int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry, -+ struct au_wr_dir_args *args); -+ -+struct dentry *au_pinned_h_parent(struct au_pin *pin); -+void au_pin_init(struct au_pin *pin, struct dentry *dentry, -+ aufs_bindex_t bindex, int lsc_di, int lsc_hi, -+ unsigned int udba, unsigned char flags); -+int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex, -+ unsigned int udba, unsigned char flags) __must_check; -+int au_do_pin(struct au_pin *pin) __must_check; -+void au_unpin(struct au_pin *pin); -+int au_reval_for_attr(struct dentry *dentry, unsigned int sigen); -+ -+#define AuIcpup_DID_CPUP 1 -+#define au_ftest_icpup(flags, name) ((flags) & AuIcpup_##name) -+#define au_fset_icpup(flags, name) \ -+ do { (flags) |= AuIcpup_##name; } while (0) -+#define au_fclr_icpup(flags, name) \ -+ do { (flags) &= ~AuIcpup_##name; } while (0) -+ -+struct au_icpup_args { -+ unsigned char flags; -+ unsigned char pin_flags; -+ aufs_bindex_t btgt; -+ unsigned int udba; -+ struct au_pin pin; -+ struct path h_path; -+ struct inode *h_inode; -+}; -+ -+int au_pin_and_icpup(struct dentry *dentry, struct iattr *ia, -+ struct au_icpup_args *a); -+ -+int au_h_path_getattr(struct dentry *dentry, struct inode *inode, int force, -+ struct path *h_path, int locked); -+ -+/* i_op_add.c */ -+int au_may_add(struct dentry *dentry, aufs_bindex_t bindex, -+ struct dentry *h_parent, int isdir); -+int aufs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, -+ dev_t dev); -+int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname); -+int aufs_create(struct inode *dir, struct dentry *dentry, umode_t mode, -+ bool want_excl); -+struct vfsub_aopen_args; -+int au_aopen_or_create(struct inode *dir, struct dentry *dentry, -+ struct vfsub_aopen_args *args); -+int aufs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode); -+int aufs_link(struct dentry *src_dentry, struct inode *dir, -+ struct dentry *dentry); -+int aufs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode); -+ -+/* i_op_del.c */ -+int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup); -+int au_may_del(struct dentry *dentry, aufs_bindex_t bindex, -+ struct dentry *h_parent, int isdir); -+int aufs_unlink(struct inode *dir, struct dentry *dentry); -+int aufs_rmdir(struct inode *dir, struct dentry *dentry); -+ -+/* i_op_ren.c */ -+int au_wbr(struct dentry *dentry, aufs_bindex_t btgt); -+int aufs_rename(struct inode *src_dir, struct dentry *src_dentry, -+ struct inode *dir, struct dentry *dentry, -+ unsigned int flags); -+ -+/* iinfo.c */ -+struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex); -+void au_hiput(struct au_hinode *hinode); -+void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex, -+ struct dentry *h_wh); -+unsigned int au_hi_flags(struct inode *inode, int isdir); -+ -+/* hinode flags */ -+#define AuHi_XINO 1 -+#define AuHi_HNOTIFY (1 << 1) -+#define au_ftest_hi(flags, name) ((flags) & AuHi_##name) -+#define au_fset_hi(flags, name) \ -+ do { (flags) |= AuHi_##name; } while (0) -+#define au_fclr_hi(flags, name) \ -+ do { (flags) &= ~AuHi_##name; } while (0) -+ -+#ifndef CONFIG_AUFS_HNOTIFY -+#undef AuHi_HNOTIFY -+#define AuHi_HNOTIFY 0 -+#endif -+ -+void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex, -+ struct inode *h_inode, unsigned int flags); -+ -+void au_update_iigen(struct inode *inode, int half); -+void au_update_ibrange(struct inode *inode, int do_put_zero); -+ -+void au_icntnr_init_once(void *_c); -+void au_hinode_init(struct au_hinode *hinode); -+int au_iinfo_init(struct inode *inode); -+void au_iinfo_fin(struct inode *inode); -+int au_hinode_realloc(struct au_iinfo *iinfo, int nbr, int may_shrink); -+ -+#ifdef CONFIG_PROC_FS -+/* plink.c */ -+int au_plink_maint(struct super_block *sb, int flags); -+struct au_sbinfo; -+void au_plink_maint_leave(struct au_sbinfo *sbinfo); -+int au_plink_maint_enter(struct super_block *sb); -+#ifdef CONFIG_AUFS_DEBUG -+void au_plink_list(struct super_block *sb); -+#else -+AuStubVoid(au_plink_list, struct super_block *sb) -+#endif -+int au_plink_test(struct inode *inode); -+struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex); -+void au_plink_append(struct inode *inode, aufs_bindex_t bindex, -+ struct dentry *h_dentry); -+void au_plink_put(struct super_block *sb, int verbose); -+void au_plink_clean(struct super_block *sb, int verbose); -+void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id); -+#else -+AuStubInt0(au_plink_maint, struct super_block *sb, int flags); -+AuStubVoid(au_plink_maint_leave, struct au_sbinfo *sbinfo); -+AuStubInt0(au_plink_maint_enter, struct super_block *sb); -+AuStubVoid(au_plink_list, struct super_block *sb); -+AuStubInt0(au_plink_test, struct inode *inode); -+AuStub(struct dentry *, au_plink_lkup, return NULL, -+ struct inode *inode, aufs_bindex_t bindex); -+AuStubVoid(au_plink_append, struct inode *inode, aufs_bindex_t bindex, -+ struct dentry *h_dentry); -+AuStubVoid(au_plink_put, struct super_block *sb, int verbose); -+AuStubVoid(au_plink_clean, struct super_block *sb, int verbose); -+AuStubVoid(au_plink_half_refresh, struct super_block *sb, aufs_bindex_t br_id); -+#endif /* CONFIG_PROC_FS */ -+ -+#ifdef CONFIG_AUFS_XATTR -+/* xattr.c */ -+int au_cpup_xattr(struct dentry *h_dst, struct dentry *h_src, int ignore_flags, -+ unsigned int verbose); -+ssize_t aufs_listxattr(struct dentry *dentry, char *list, size_t size); -+void au_xattr_init(struct super_block *sb); -+#else -+AuStubInt0(au_cpup_xattr, struct dentry *h_dst, struct dentry *h_src, -+ int ignore_flags, unsigned int verbose); -+AuStubVoid(au_xattr_init, struct super_block *sb); -+#endif -+ -+#ifdef CONFIG_FS_POSIX_ACL -+struct posix_acl *aufs_get_acl(struct inode *inode, int type); -+int aufs_set_acl(struct inode *inode, struct posix_acl *acl, int type); -+#endif -+ -+#if IS_ENABLED(CONFIG_AUFS_XATTR) || IS_ENABLED(CONFIG_FS_POSIX_ACL) -+enum { -+ AU_XATTR_SET, -+ AU_ACL_SET -+}; -+ -+struct au_sxattr { -+ int type; -+ union { -+ struct { -+ const char *name; -+ const void *value; -+ size_t size; -+ int flags; -+ } set; -+ struct { -+ struct posix_acl *acl; -+ int type; -+ } acl_set; -+ } u; -+}; -+ssize_t au_sxattr(struct dentry *dentry, struct inode *inode, -+ struct au_sxattr *arg); -+#endif -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* lock subclass for iinfo */ -+enum { -+ AuLsc_II_CHILD, /* child first */ -+ AuLsc_II_CHILD2, /* rename(2), link(2), and cpup at hnotify */ -+ AuLsc_II_CHILD3, /* copyup dirs */ -+ AuLsc_II_PARENT, /* see AuLsc_I_PARENT in vfsub.h */ -+ AuLsc_II_PARENT2, -+ AuLsc_II_PARENT3, /* copyup dirs */ -+ AuLsc_II_NEW_CHILD -+}; -+ -+/* -+ * ii_read_lock_child, ii_write_lock_child, -+ * ii_read_lock_child2, ii_write_lock_child2, -+ * ii_read_lock_child3, ii_write_lock_child3, -+ * ii_read_lock_parent, ii_write_lock_parent, -+ * ii_read_lock_parent2, ii_write_lock_parent2, -+ * ii_read_lock_parent3, ii_write_lock_parent3, -+ * ii_read_lock_new_child, ii_write_lock_new_child, -+ */ -+#define AuReadLockFunc(name, lsc) \ -+static inline void ii_read_lock_##name(struct inode *i) \ -+{ \ -+ au_rw_read_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \ -+} -+ -+#define AuWriteLockFunc(name, lsc) \ -+static inline void ii_write_lock_##name(struct inode *i) \ -+{ \ -+ au_rw_write_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \ -+} -+ -+#define AuRWLockFuncs(name, lsc) \ -+ AuReadLockFunc(name, lsc) \ -+ AuWriteLockFunc(name, lsc) -+ -+AuRWLockFuncs(child, CHILD); -+AuRWLockFuncs(child2, CHILD2); -+AuRWLockFuncs(child3, CHILD3); -+AuRWLockFuncs(parent, PARENT); -+AuRWLockFuncs(parent2, PARENT2); -+AuRWLockFuncs(parent3, PARENT3); -+AuRWLockFuncs(new_child, NEW_CHILD); -+ -+#undef AuReadLockFunc -+#undef AuWriteLockFunc -+#undef AuRWLockFuncs -+ -+#define ii_read_unlock(i) au_rw_read_unlock(&au_ii(i)->ii_rwsem) -+#define ii_write_unlock(i) au_rw_write_unlock(&au_ii(i)->ii_rwsem) -+#define ii_downgrade_lock(i) au_rw_dgrade_lock(&au_ii(i)->ii_rwsem) -+ -+#define IiMustNoWaiters(i) AuRwMustNoWaiters(&au_ii(i)->ii_rwsem) -+#define IiMustAnyLock(i) AuRwMustAnyLock(&au_ii(i)->ii_rwsem) -+#define IiMustWriteLock(i) AuRwMustWriteLock(&au_ii(i)->ii_rwsem) -+ -+/* ---------------------------------------------------------------------- */ -+ -+static inline void au_icntnr_init(struct au_icntnr *c) -+{ -+#ifdef CONFIG_AUFS_DEBUG -+ c->vfs_inode.i_mode = 0; -+#endif -+} -+ -+static inline unsigned int au_iigen(struct inode *inode, unsigned int *igflags) -+{ -+ unsigned int gen; -+ struct au_iinfo *iinfo; -+ struct au_iigen *iigen; -+ -+ iinfo = au_ii(inode); -+ iigen = &iinfo->ii_generation; -+ spin_lock(&iigen->ig_spin); -+ if (igflags) -+ *igflags = iigen->ig_flags; -+ gen = iigen->ig_generation; -+ spin_unlock(&iigen->ig_spin); -+ -+ return gen; -+} -+ -+/* tiny test for inode number */ -+/* tmpfs generation is too rough */ -+static inline int au_test_higen(struct inode *inode, struct inode *h_inode) -+{ -+ struct au_iinfo *iinfo; -+ -+ iinfo = au_ii(inode); -+ AuRwMustAnyLock(&iinfo->ii_rwsem); -+ return !(iinfo->ii_hsb1 == h_inode->i_sb -+ && iinfo->ii_higen == h_inode->i_generation); -+} -+ -+static inline void au_iigen_dec(struct inode *inode) -+{ -+ struct au_iinfo *iinfo; -+ struct au_iigen *iigen; -+ -+ iinfo = au_ii(inode); -+ iigen = &iinfo->ii_generation; -+ spin_lock(&iigen->ig_spin); -+ iigen->ig_generation--; -+ spin_unlock(&iigen->ig_spin); -+} -+ -+static inline int au_iigen_test(struct inode *inode, unsigned int sigen) -+{ -+ int err; -+ -+ err = 0; -+ if (unlikely(inode && au_iigen(inode, NULL) != sigen)) -+ err = -EIO; -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static inline struct au_hinode *au_hinode(struct au_iinfo *iinfo, -+ aufs_bindex_t bindex) -+{ -+ return iinfo->ii_hinode + bindex; -+} -+ -+static inline int au_is_bad_inode(struct inode *inode) -+{ -+ return !!(is_bad_inode(inode) || !au_hinode(au_ii(inode), 0)); -+} -+ -+static inline aufs_bindex_t au_ii_br_id(struct inode *inode, -+ aufs_bindex_t bindex) -+{ -+ IiMustAnyLock(inode); -+ return au_hinode(au_ii(inode), bindex)->hi_id; -+} -+ -+static inline aufs_bindex_t au_ibtop(struct inode *inode) -+{ -+ IiMustAnyLock(inode); -+ return au_ii(inode)->ii_btop; -+} -+ -+static inline aufs_bindex_t au_ibbot(struct inode *inode) -+{ -+ IiMustAnyLock(inode); -+ return au_ii(inode)->ii_bbot; -+} -+ -+static inline struct au_vdir *au_ivdir(struct inode *inode) -+{ -+ IiMustAnyLock(inode); -+ return au_ii(inode)->ii_vdir; -+} -+ -+static inline struct dentry *au_hi_wh(struct inode *inode, aufs_bindex_t bindex) -+{ -+ IiMustAnyLock(inode); -+ return au_hinode(au_ii(inode), bindex)->hi_whdentry; -+} -+ -+static inline void au_set_ibtop(struct inode *inode, aufs_bindex_t bindex) -+{ -+ IiMustWriteLock(inode); -+ au_ii(inode)->ii_btop = bindex; -+} -+ -+static inline void au_set_ibbot(struct inode *inode, aufs_bindex_t bindex) -+{ -+ IiMustWriteLock(inode); -+ au_ii(inode)->ii_bbot = bindex; -+} -+ -+static inline void au_set_ivdir(struct inode *inode, struct au_vdir *vdir) -+{ -+ IiMustWriteLock(inode); -+ au_ii(inode)->ii_vdir = vdir; -+} -+ -+static inline struct au_hinode *au_hi(struct inode *inode, aufs_bindex_t bindex) -+{ -+ IiMustAnyLock(inode); -+ return au_hinode(au_ii(inode), bindex); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static inline struct dentry *au_pinned_parent(struct au_pin *pin) -+{ -+ if (pin) -+ return pin->parent; -+ return NULL; -+} -+ -+static inline struct inode *au_pinned_h_dir(struct au_pin *pin) -+{ -+ if (pin && pin->hdir) -+ return pin->hdir->hi_inode; -+ return NULL; -+} -+ -+static inline struct au_hinode *au_pinned_hdir(struct au_pin *pin) -+{ -+ if (pin) -+ return pin->hdir; -+ return NULL; -+} -+ -+static inline void au_pin_set_dentry(struct au_pin *pin, struct dentry *dentry) -+{ -+ if (pin) -+ pin->dentry = dentry; -+} -+ -+static inline void au_pin_set_parent_lflag(struct au_pin *pin, -+ unsigned char lflag) -+{ -+ if (pin) { -+ if (lflag) -+ au_fset_pin(pin->flags, DI_LOCKED); -+ else -+ au_fclr_pin(pin->flags, DI_LOCKED); -+ } -+} -+ -+#if 0 /* reserved */ -+static inline void au_pin_set_parent(struct au_pin *pin, struct dentry *parent) -+{ -+ if (pin) { -+ dput(pin->parent); -+ pin->parent = dget(parent); -+ } -+} -+#endif -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct au_branch; -+#ifdef CONFIG_AUFS_HNOTIFY -+struct au_hnotify_op { -+ void (*ctl)(struct au_hinode *hinode, int do_set); -+ int (*alloc)(struct au_hinode *hinode); -+ -+ /* -+ * if it returns true, the the caller should free hinode->hi_notify, -+ * otherwise ->free() frees it. -+ */ -+ int (*free)(struct au_hinode *hinode, -+ struct au_hnotify *hn) __must_check; -+ -+ void (*fin)(void); -+ int (*init)(void); -+ -+ int (*reset_br)(unsigned int udba, struct au_branch *br, int perm); -+ void (*fin_br)(struct au_branch *br); -+ int (*init_br)(struct au_branch *br, int perm); -+}; -+ -+/* hnotify.c */ -+int au_hn_alloc(struct au_hinode *hinode, struct inode *inode); -+void au_hn_free(struct au_hinode *hinode); -+void au_hn_ctl(struct au_hinode *hinode, int do_set); -+void au_hn_reset(struct inode *inode, unsigned int flags); -+int au_hnotify(struct inode *h_dir, struct au_hnotify *hnotify, u32 mask, -+ const struct qstr *h_child_qstr, struct inode *h_child_inode); -+int au_hnotify_reset_br(unsigned int udba, struct au_branch *br, int perm); -+int au_hnotify_init_br(struct au_branch *br, int perm); -+void au_hnotify_fin_br(struct au_branch *br); -+int __init au_hnotify_init(void); -+void au_hnotify_fin(void); -+ -+/* hfsnotify.c */ -+extern const struct au_hnotify_op au_hnotify_op; -+ -+static inline -+void au_hn_init(struct au_hinode *hinode) -+{ -+ hinode->hi_notify = NULL; -+} -+ -+static inline struct au_hnotify *au_hn(struct au_hinode *hinode) -+{ -+ return hinode->hi_notify; -+} -+ -+#else -+AuStub(int, au_hn_alloc, return -EOPNOTSUPP, -+ struct au_hinode *hinode __maybe_unused, -+ struct inode *inode __maybe_unused) -+AuStub(struct au_hnotify *, au_hn, return NULL, struct au_hinode *hinode) -+AuStubVoid(au_hn_free, struct au_hinode *hinode __maybe_unused) -+AuStubVoid(au_hn_ctl, struct au_hinode *hinode __maybe_unused, -+ int do_set __maybe_unused) -+AuStubVoid(au_hn_reset, struct inode *inode __maybe_unused, -+ unsigned int flags __maybe_unused) -+AuStubInt0(au_hnotify_reset_br, unsigned int udba __maybe_unused, -+ struct au_branch *br __maybe_unused, -+ int perm __maybe_unused) -+AuStubInt0(au_hnotify_init_br, struct au_branch *br __maybe_unused, -+ int perm __maybe_unused) -+AuStubVoid(au_hnotify_fin_br, struct au_branch *br __maybe_unused) -+AuStubInt0(__init au_hnotify_init, void) -+AuStubVoid(au_hnotify_fin, void) -+AuStubVoid(au_hn_init, struct au_hinode *hinode __maybe_unused) -+#endif /* CONFIG_AUFS_HNOTIFY */ -+ -+static inline void au_hn_suspend(struct au_hinode *hdir) -+{ -+ au_hn_ctl(hdir, /*do_set*/0); -+} -+ -+static inline void au_hn_resume(struct au_hinode *hdir) -+{ -+ au_hn_ctl(hdir, /*do_set*/1); -+} -+ -+static inline void au_hn_inode_lock(struct au_hinode *hdir) -+{ -+ inode_lock(hdir->hi_inode); -+ au_hn_suspend(hdir); -+} -+ -+static inline void au_hn_inode_lock_nested(struct au_hinode *hdir, -+ unsigned int sc __maybe_unused) -+{ -+ inode_lock_nested(hdir->hi_inode, sc); -+ au_hn_suspend(hdir); -+} -+ -+#if 0 /* unused */ -+#include "vfsub.h" -+static inline void au_hn_inode_lock_shared_nested(struct au_hinode *hdir, -+ unsigned int sc) -+{ -+ inode_lock_shared_nested(hdir->hi_inode, sc); -+ au_hn_suspend(hdir); -+} -+#endif -+ -+static inline void au_hn_inode_unlock(struct au_hinode *hdir) -+{ -+ au_hn_resume(hdir); -+ inode_unlock(hdir->hi_inode); -+} -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_INODE_H__ */ -diff --git a/fs/aufs/ioctl.c b/fs/aufs/ioctl.c -new file mode 100644 -index 000000000000..9d0e969217a9 ---- /dev/null -+++ b/fs/aufs/ioctl.c -@@ -0,0 +1,207 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * ioctl -+ * plink-management and readdir in userspace. -+ * assist the pathconf(3) wrapper library. -+ * move-down -+ * File-based Hierarchical Storage Management. -+ */ -+ -+#include -+#include -+#include "aufs.h" -+ -+static int au_wbr_fd(struct path *path, struct aufs_wbr_fd __user *arg) -+{ -+ int err, fd; -+ aufs_bindex_t wbi, bindex, bbot; -+ struct file *h_file; -+ struct super_block *sb; -+ struct dentry *root; -+ struct au_branch *br; -+ struct aufs_wbr_fd wbrfd = { -+ .oflags = au_dir_roflags, -+ .brid = -1 -+ }; -+ const int valid = O_RDONLY | O_NONBLOCK | O_LARGEFILE | O_DIRECTORY -+ | O_NOATIME | O_CLOEXEC; -+ -+ AuDebugOn(wbrfd.oflags & ~valid); -+ -+ if (arg) { -+ err = copy_from_user(&wbrfd, arg, sizeof(wbrfd)); -+ if (unlikely(err)) { -+ err = -EFAULT; -+ goto out; -+ } -+ -+ err = -EINVAL; -+ AuDbg("wbrfd{0%o, %d}\n", wbrfd.oflags, wbrfd.brid); -+ wbrfd.oflags |= au_dir_roflags; -+ AuDbg("0%o\n", wbrfd.oflags); -+ if (unlikely(wbrfd.oflags & ~valid)) -+ goto out; -+ } -+ -+ fd = get_unused_fd_flags(0); -+ err = fd; -+ if (unlikely(fd < 0)) -+ goto out; -+ -+ h_file = ERR_PTR(-EINVAL); -+ wbi = 0; -+ br = NULL; -+ sb = path->dentry->d_sb; -+ root = sb->s_root; -+ aufs_read_lock(root, AuLock_IR); -+ bbot = au_sbbot(sb); -+ if (wbrfd.brid >= 0) { -+ wbi = au_br_index(sb, wbrfd.brid); -+ if (unlikely(wbi < 0 || wbi > bbot)) -+ goto out_unlock; -+ } -+ -+ h_file = ERR_PTR(-ENOENT); -+ br = au_sbr(sb, wbi); -+ if (!au_br_writable(br->br_perm)) { -+ if (arg) -+ goto out_unlock; -+ -+ bindex = wbi + 1; -+ wbi = -1; -+ for (; bindex <= bbot; bindex++) { -+ br = au_sbr(sb, bindex); -+ if (au_br_writable(br->br_perm)) { -+ wbi = bindex; -+ br = au_sbr(sb, wbi); -+ break; -+ } -+ } -+ } -+ AuDbg("wbi %d\n", wbi); -+ if (wbi >= 0) -+ h_file = au_h_open(root, wbi, wbrfd.oflags, NULL, -+ /*force_wr*/0); -+ -+out_unlock: -+ aufs_read_unlock(root, AuLock_IR); -+ err = PTR_ERR(h_file); -+ if (IS_ERR(h_file)) -+ goto out_fd; -+ -+ au_lcnt_dec(&br->br_nfiles); /* cf. au_h_open() */ -+ fd_install(fd, h_file); -+ err = fd; -+ goto out; /* success */ -+ -+out_fd: -+ put_unused_fd(fd); -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg) -+{ -+ long err; -+ struct dentry *dentry; -+ -+ switch (cmd) { -+ case AUFS_CTL_RDU: -+ case AUFS_CTL_RDU_INO: -+ err = au_rdu_ioctl(file, cmd, arg); -+ break; -+ -+ case AUFS_CTL_WBR_FD: -+ err = au_wbr_fd(&file->f_path, (void __user *)arg); -+ break; -+ -+ case AUFS_CTL_IBUSY: -+ err = au_ibusy_ioctl(file, arg); -+ break; -+ -+ case AUFS_CTL_BRINFO: -+ err = au_brinfo_ioctl(file, arg); -+ break; -+ -+ case AUFS_CTL_FHSM_FD: -+ dentry = file->f_path.dentry; -+ if (IS_ROOT(dentry)) -+ err = au_fhsm_fd(dentry->d_sb, arg); -+ else -+ err = -ENOTTY; -+ break; -+ -+ default: -+ /* do not call the lower */ -+ AuDbg("0x%x\n", cmd); -+ err = -ENOTTY; -+ } -+ -+ AuTraceErr(err); -+ return err; -+} -+ -+long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg) -+{ -+ long err; -+ -+ switch (cmd) { -+ case AUFS_CTL_MVDOWN: -+ err = au_mvdown(file->f_path.dentry, (void __user *)arg); -+ break; -+ -+ case AUFS_CTL_WBR_FD: -+ err = au_wbr_fd(&file->f_path, (void __user *)arg); -+ break; -+ -+ default: -+ /* do not call the lower */ -+ AuDbg("0x%x\n", cmd); -+ err = -ENOTTY; -+ } -+ -+ AuTraceErr(err); -+ return err; -+} -+ -+#ifdef CONFIG_COMPAT -+long aufs_compat_ioctl_dir(struct file *file, unsigned int cmd, -+ unsigned long arg) -+{ -+ long err; -+ -+ switch (cmd) { -+ case AUFS_CTL_RDU: -+ case AUFS_CTL_RDU_INO: -+ err = au_rdu_compat_ioctl(file, cmd, arg); -+ break; -+ -+ case AUFS_CTL_IBUSY: -+ err = au_ibusy_compat_ioctl(file, arg); -+ break; -+ -+ case AUFS_CTL_BRINFO: -+ err = au_brinfo_compat_ioctl(file, arg); -+ break; -+ -+ default: -+ err = aufs_ioctl_dir(file, cmd, arg); -+ } -+ -+ AuTraceErr(err); -+ return err; -+} -+ -+long aufs_compat_ioctl_nondir(struct file *file, unsigned int cmd, -+ unsigned long arg) -+{ -+ return aufs_ioctl_nondir(file, cmd, (unsigned long)compat_ptr(arg)); -+} -+#endif -diff --git a/fs/aufs/lcnt.h b/fs/aufs/lcnt.h -new file mode 100644 -index 000000000000..c7db43d9e260 ---- /dev/null -+++ b/fs/aufs/lcnt.h -@@ -0,0 +1,173 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2018-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * simple long counter wrapper -+ */ -+ -+#ifndef __AUFS_LCNT_H__ -+#define __AUFS_LCNT_H__ -+ -+#ifdef __KERNEL__ -+ -+#include "debug.h" -+ -+#define AuLCntATOMIC 1 -+#define AuLCntPCPUCNT 2 -+/* -+ * why does percpu_refcount require extra synchronize_rcu()s in -+ * au_br_do_free() -+ */ -+#define AuLCntPCPUREF 3 -+ -+/* #define AuLCntChosen AuLCntATOMIC */ -+#define AuLCntChosen AuLCntPCPUCNT -+/* #define AuLCntChosen AuLCntPCPUREF */ -+ -+#if AuLCntChosen == AuLCntATOMIC -+#include -+ -+typedef atomic_long_t au_lcnt_t; -+ -+static inline int au_lcnt_init(au_lcnt_t *cnt, void *release __maybe_unused) -+{ -+ atomic_long_set(cnt, 0); -+ return 0; -+} -+ -+static inline void au_lcnt_wait_for_fin(au_lcnt_t *cnt __maybe_unused) -+{ -+ /* empty */ -+} -+ -+static inline void au_lcnt_fin(au_lcnt_t *cnt __maybe_unused, -+ int do_sync __maybe_unused) -+{ -+ /* empty */ -+} -+ -+static inline void au_lcnt_inc(au_lcnt_t *cnt) -+{ -+ atomic_long_inc(cnt); -+} -+ -+static inline void au_lcnt_dec(au_lcnt_t *cnt) -+{ -+ atomic_long_dec(cnt); -+} -+ -+static inline long au_lcnt_read(au_lcnt_t *cnt, int do_rev __maybe_unused) -+{ -+ return atomic_long_read(cnt); -+} -+#endif -+ -+#if AuLCntChosen == AuLCntPCPUCNT -+#include -+ -+typedef struct percpu_counter au_lcnt_t; -+ -+static inline int au_lcnt_init(au_lcnt_t *cnt, void *release __maybe_unused) -+{ -+ return percpu_counter_init(cnt, 0, GFP_NOFS); -+} -+ -+static inline void au_lcnt_wait_for_fin(au_lcnt_t *cnt __maybe_unused) -+{ -+ /* empty */ -+} -+ -+static inline void au_lcnt_fin(au_lcnt_t *cnt, int do_sync __maybe_unused) -+{ -+ percpu_counter_destroy(cnt); -+} -+ -+static inline void au_lcnt_inc(au_lcnt_t *cnt) -+{ -+ percpu_counter_inc(cnt); -+} -+ -+static inline void au_lcnt_dec(au_lcnt_t *cnt) -+{ -+ percpu_counter_dec(cnt); -+} -+ -+static inline long au_lcnt_read(au_lcnt_t *cnt, int do_rev __maybe_unused) -+{ -+ s64 n; -+ -+ n = percpu_counter_sum(cnt); -+ BUG_ON(n < 0); -+ if (LONG_MAX != LLONG_MAX -+ && n > LONG_MAX) -+ AuWarn1("%s\n", "wrap-around"); -+ -+ return n; -+} -+#endif -+ -+#if AuLCntChosen == AuLCntPCPUREF -+#include -+ -+typedef struct percpu_ref au_lcnt_t; -+ -+static inline int au_lcnt_init(au_lcnt_t *cnt, percpu_ref_func_t *release) -+{ -+ if (!release) -+ release = percpu_ref_exit; -+ return percpu_ref_init(cnt, release, /*percpu mode*/0, GFP_NOFS); -+} -+ -+static inline void au_lcnt_wait_for_fin(au_lcnt_t *cnt __maybe_unused) -+{ -+ synchronize_rcu(); -+} -+ -+static inline void au_lcnt_fin(au_lcnt_t *cnt, int do_sync) -+{ -+ percpu_ref_kill(cnt); -+ if (do_sync) -+ au_lcnt_wait_for_fin(cnt); -+} -+ -+static inline void au_lcnt_inc(au_lcnt_t *cnt) -+{ -+ percpu_ref_get(cnt); -+} -+ -+static inline void au_lcnt_dec(au_lcnt_t *cnt) -+{ -+ percpu_ref_put(cnt); -+} -+ -+/* -+ * avoid calling this func as possible. -+ */ -+static inline long au_lcnt_read(au_lcnt_t *cnt, int do_rev) -+{ -+ long l; -+ -+ percpu_ref_switch_to_atomic_sync(cnt); -+ l = atomic_long_read(&cnt->count); -+ if (do_rev) -+ percpu_ref_switch_to_percpu(cnt); -+ -+ /* percpu_ref is initialized by 1 instead of 0 */ -+ return l - 1; -+} -+#endif -+ -+#ifdef CONFIG_AUFS_DEBUG -+#define AuLCntZero(val) do { \ -+ long l = val; \ -+ if (l) \ -+ AuDbg("%s = %ld\n", #val, l); \ -+} while (0) -+#else -+#define AuLCntZero(val) do {} while (0) -+#endif -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_LCNT_H__ */ -diff --git a/fs/aufs/loop.c b/fs/aufs/loop.c -new file mode 100644 -index 000000000000..a8b63acc6204 ---- /dev/null -+++ b/fs/aufs/loop.c -@@ -0,0 +1,135 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * support for loopback block device as a branch -+ */ -+ -+#include "aufs.h" -+ -+/* added into drivers/block/loop.c */ -+static struct file *(*backing_file_func)(struct super_block *sb); -+ -+/* -+ * test if two lower dentries have overlapping branches. -+ */ -+int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_adding) -+{ -+ struct super_block *h_sb; -+ struct file *backing_file; -+ -+ if (unlikely(!backing_file_func)) { -+ /* don't load "loop" module here */ -+ backing_file_func = symbol_get(loop_backing_file); -+ if (unlikely(!backing_file_func)) -+ /* "loop" module is not loaded */ -+ return 0; -+ } -+ -+ h_sb = h_adding->d_sb; -+ backing_file = backing_file_func(h_sb); -+ if (!backing_file) -+ return 0; -+ -+ h_adding = backing_file->f_path.dentry; -+ /* -+ * h_adding can be local NFS. -+ * in this case aufs cannot detect the loop. -+ */ -+ if (unlikely(h_adding->d_sb == sb)) -+ return 1; -+ return !!au_test_subdir(h_adding, sb->s_root); -+} -+ -+/* true if a kernel thread named 'loop[0-9].*' accesses a file */ -+int au_test_loopback_kthread(void) -+{ -+ int ret; -+ struct task_struct *tsk = current; -+ char c, comm[sizeof(tsk->comm)]; -+ -+ ret = 0; -+ if (tsk->flags & PF_KTHREAD) { -+ get_task_comm(comm, tsk); -+ c = comm[4]; -+ ret = ('0' <= c && c <= '9' -+ && !strncmp(comm, "loop", 4)); -+ } -+ -+ return ret; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+#define au_warn_loopback_step 16 -+static int au_warn_loopback_nelem = au_warn_loopback_step; -+static unsigned long *au_warn_loopback_array; -+ -+void au_warn_loopback(struct super_block *h_sb) -+{ -+ int i, new_nelem; -+ unsigned long *a, magic; -+ static DEFINE_SPINLOCK(spin); -+ -+ magic = h_sb->s_magic; -+ spin_lock(&spin); -+ a = au_warn_loopback_array; -+ for (i = 0; i < au_warn_loopback_nelem && *a; i++) -+ if (a[i] == magic) { -+ spin_unlock(&spin); -+ return; -+ } -+ -+ /* h_sb is new to us, print it */ -+ if (i < au_warn_loopback_nelem) { -+ a[i] = magic; -+ goto pr; -+ } -+ -+ /* expand the array */ -+ new_nelem = au_warn_loopback_nelem + au_warn_loopback_step; -+ a = au_kzrealloc(au_warn_loopback_array, -+ au_warn_loopback_nelem * sizeof(unsigned long), -+ new_nelem * sizeof(unsigned long), GFP_ATOMIC, -+ /*may_shrink*/0); -+ if (a) { -+ au_warn_loopback_nelem = new_nelem; -+ au_warn_loopback_array = a; -+ a[i] = magic; -+ goto pr; -+ } -+ -+ spin_unlock(&spin); -+ AuWarn1("realloc failed, ignored\n"); -+ return; -+ -+pr: -+ spin_unlock(&spin); -+ pr_warn("you may want to try another patch for loopback file " -+ "on %s(0x%lx) branch\n", au_sbtype(h_sb), magic); -+} -+ -+int au_loopback_init(void) -+{ -+ int err; -+ struct super_block *sb __maybe_unused; -+ -+ BUILD_BUG_ON(sizeof(sb->s_magic) != sizeof(*au_warn_loopback_array)); -+ -+ err = 0; -+ au_warn_loopback_array = kcalloc(au_warn_loopback_step, -+ sizeof(unsigned long), GFP_NOFS); -+ if (unlikely(!au_warn_loopback_array)) -+ err = -ENOMEM; -+ -+ return err; -+} -+ -+void au_loopback_fin(void) -+{ -+ if (backing_file_func) -+ symbol_put(loop_backing_file); -+ au_kfree_try_rcu(au_warn_loopback_array); -+} -diff --git a/fs/aufs/loop.h b/fs/aufs/loop.h -new file mode 100644 -index 000000000000..94f4f80ae33b ---- /dev/null -+++ b/fs/aufs/loop.h -@@ -0,0 +1,42 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * support for loopback mount as a branch -+ */ -+ -+#ifndef __AUFS_LOOP_H__ -+#define __AUFS_LOOP_H__ -+ -+#ifdef __KERNEL__ -+ -+struct dentry; -+struct super_block; -+ -+#ifdef CONFIG_AUFS_BDEV_LOOP -+/* drivers/block/loop.c */ -+struct file *loop_backing_file(struct super_block *sb); -+ -+/* loop.c */ -+int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_adding); -+int au_test_loopback_kthread(void); -+void au_warn_loopback(struct super_block *h_sb); -+ -+int au_loopback_init(void); -+void au_loopback_fin(void); -+#else -+AuStub(struct file *, loop_backing_file, return NULL, struct super_block *sb) -+ -+AuStubInt0(au_test_loopback_overlap, struct super_block *sb, -+ struct dentry *h_adding) -+AuStubInt0(au_test_loopback_kthread, void) -+AuStubVoid(au_warn_loopback, struct super_block *h_sb) -+ -+AuStubInt0(au_loopback_init, void) -+AuStubVoid(au_loopback_fin, void) -+#endif /* BLK_DEV_LOOP */ -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_LOOP_H__ */ -diff --git a/fs/aufs/magic.mk b/fs/aufs/magic.mk -new file mode 100644 -index 000000000000..7bc9eef3ffec ---- /dev/null -+++ b/fs/aufs/magic.mk -@@ -0,0 +1,31 @@ -+# SPDX-License-Identifier: GPL-2.0 -+ -+# defined in ${srctree}/fs/fuse/inode.c -+# tristate -+ifdef CONFIG_FUSE_FS -+ccflags-y += -DFUSE_SUPER_MAGIC=0x65735546 -+endif -+ -+# defined in ${srctree}/fs/xfs/xfs_sb.h -+# tristate -+ifdef CONFIG_XFS_FS -+ccflags-y += -DXFS_SB_MAGIC=0x58465342 -+endif -+ -+# defined in ${srctree}/fs/configfs/mount.c -+# tristate -+ifdef CONFIG_CONFIGFS_FS -+ccflags-y += -DCONFIGFS_MAGIC=0x62656570 -+endif -+ -+# defined in ${srctree}/fs/ubifs/ubifs.h -+# tristate -+ifdef CONFIG_UBIFS_FS -+ccflags-y += -DUBIFS_SUPER_MAGIC=0x24051905 -+endif -+ -+# defined in ${srctree}/fs/hfsplus/hfsplus_raw.h -+# tristate -+ifdef CONFIG_HFSPLUS_FS -+ccflags-y += -DHFSPLUS_SUPER_MAGIC=0x482b -+endif -diff --git a/fs/aufs/module.c b/fs/aufs/module.c -new file mode 100644 -index 000000000000..18039801580f ---- /dev/null -+++ b/fs/aufs/module.c -@@ -0,0 +1,259 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * module global variables and operations -+ */ -+ -+#include -+#include -+#include "aufs.h" -+ -+/* shrinkable realloc */ -+void *au_krealloc(void *p, unsigned int new_sz, gfp_t gfp, int may_shrink) -+{ -+ size_t sz; -+ int diff; -+ -+ sz = 0; -+ diff = -1; -+ if (p) { -+#if 0 /* unused */ -+ if (!new_sz) { -+ au_kfree_rcu(p); -+ p = NULL; -+ goto out; -+ } -+#else -+ AuDebugOn(!new_sz); -+#endif -+ sz = ksize(p); -+ diff = au_kmidx_sub(sz, new_sz); -+ } -+ if (sz && !diff) -+ goto out; -+ -+ if (sz < new_sz) -+ /* expand or SLOB */ -+ p = krealloc(p, new_sz, gfp); -+ else if (new_sz < sz && may_shrink) { -+ /* shrink */ -+ void *q; -+ -+ q = kmalloc(new_sz, gfp); -+ if (q) { -+ if (p) { -+ memcpy(q, p, new_sz); -+ au_kfree_try_rcu(p); -+ } -+ p = q; -+ } else -+ p = NULL; -+ } -+ -+out: -+ return p; -+} -+ -+void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp, -+ int may_shrink) -+{ -+ p = au_krealloc(p, new_sz, gfp, may_shrink); -+ if (p && new_sz > nused) -+ memset(p + nused, 0, new_sz - nused); -+ return p; -+} -+ -+/* ---------------------------------------------------------------------- */ -+/* -+ * aufs caches -+ */ -+struct kmem_cache *au_cache[AuCache_Last]; -+ -+static void au_cache_fin(void) -+{ -+ int i; -+ -+ /* -+ * Make sure all delayed rcu free inodes are flushed before we -+ * destroy cache. -+ */ -+ rcu_barrier(); -+ -+ /* excluding AuCache_HNOTIFY */ -+ BUILD_BUG_ON(AuCache_HNOTIFY + 1 != AuCache_Last); -+ for (i = 0; i < AuCache_HNOTIFY; i++) { -+ kmem_cache_destroy(au_cache[i]); -+ au_cache[i] = NULL; -+ } -+} -+ -+static int __init au_cache_init(void) -+{ -+ au_cache[AuCache_DINFO] = AuCacheCtor(au_dinfo, au_di_init_once); -+ if (au_cache[AuCache_DINFO]) -+ /* SLAB_DESTROY_BY_RCU */ -+ au_cache[AuCache_ICNTNR] = AuCacheCtor(au_icntnr, -+ au_icntnr_init_once); -+ if (au_cache[AuCache_ICNTNR]) -+ au_cache[AuCache_FINFO] = AuCacheCtor(au_finfo, -+ au_fi_init_once); -+ if (au_cache[AuCache_FINFO]) -+ au_cache[AuCache_VDIR] = AuCache(au_vdir); -+ if (au_cache[AuCache_VDIR]) -+ au_cache[AuCache_DEHSTR] = AuCache(au_vdir_dehstr); -+ if (au_cache[AuCache_DEHSTR]) -+ return 0; -+ -+ au_cache_fin(); -+ return -ENOMEM; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+int au_dir_roflags; -+ -+#ifdef CONFIG_AUFS_SBILIST -+/* -+ * iterate_supers_type() doesn't protect us from -+ * remounting (branch management) -+ */ -+struct hlist_bl_head au_sbilist; -+#endif -+ -+/* -+ * functions for module interface. -+ */ -+MODULE_LICENSE("GPL"); -+/* MODULE_LICENSE("GPL v2"); */ -+MODULE_AUTHOR("Junjiro R. Okajima "); -+MODULE_DESCRIPTION(AUFS_NAME -+ " -- Advanced multi layered unification filesystem"); -+MODULE_VERSION(AUFS_VERSION); -+ -+/* this module parameter has no meaning when SYSFS is disabled */ -+int sysaufs_brs = 1; -+MODULE_PARM_DESC(brs, "use /fs/aufs/si_*/brN"); -+module_param_named(brs, sysaufs_brs, int, 0444); -+ -+/* this module parameter has no meaning when USER_NS is disabled */ -+bool au_userns; -+MODULE_PARM_DESC(allow_userns, "allow unprivileged to mount under userns"); -+module_param_named(allow_userns, au_userns, bool, 0444); -+ -+/* ---------------------------------------------------------------------- */ -+ -+static char au_esc_chars[0x20 + 3]; /* 0x01-0x20, backslash, del, and NULL */ -+ -+int au_seq_path(struct seq_file *seq, struct path *path) -+{ -+ int err; -+ -+ err = seq_path(seq, path, au_esc_chars); -+ if (err >= 0) -+ err = 0; -+ else -+ err = -ENOMEM; -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int __init aufs_init(void) -+{ -+ int err, i; -+ char *p; -+ -+ p = au_esc_chars; -+ for (i = 1; i <= ' '; i++) -+ *p++ = i; -+ *p++ = '\\'; -+ *p++ = '\x7f'; -+ *p = 0; -+ -+ au_dir_roflags = au_file_roflags(O_DIRECTORY | O_LARGEFILE); -+ -+ memcpy(aufs_iop_nogetattr, aufs_iop, sizeof(aufs_iop)); -+ for (i = 0; i < AuIop_Last; i++) -+ aufs_iop_nogetattr[i].getattr = NULL; -+ -+ memset(au_cache, 0, sizeof(au_cache)); /* including hnotify */ -+ -+ au_sbilist_init(); -+ sysaufs_brs_init(); -+ au_debug_init(); -+ au_dy_init(); -+ err = sysaufs_init(); -+ if (unlikely(err)) -+ goto out; -+ err = dbgaufs_init(); -+ if (unlikely(err)) -+ goto out_sysaufs; -+ err = au_procfs_init(); -+ if (unlikely(err)) -+ goto out_dbgaufs; -+ err = au_wkq_init(); -+ if (unlikely(err)) -+ goto out_procfs; -+ err = au_loopback_init(); -+ if (unlikely(err)) -+ goto out_wkq; -+ err = au_hnotify_init(); -+ if (unlikely(err)) -+ goto out_loopback; -+ err = au_sysrq_init(); -+ if (unlikely(err)) -+ goto out_hin; -+ err = au_cache_init(); -+ if (unlikely(err)) -+ goto out_sysrq; -+ -+ aufs_fs_type.fs_flags |= au_userns ? FS_USERNS_MOUNT : 0; -+ err = register_filesystem(&aufs_fs_type); -+ if (unlikely(err)) -+ goto out_cache; -+ -+ /* since we define pr_fmt, call printk directly */ -+ printk(KERN_INFO AUFS_NAME " " AUFS_VERSION "\n"); -+ goto out; /* success */ -+ -+out_cache: -+ au_cache_fin(); -+out_sysrq: -+ au_sysrq_fin(); -+out_hin: -+ au_hnotify_fin(); -+out_loopback: -+ au_loopback_fin(); -+out_wkq: -+ au_wkq_fin(); -+out_procfs: -+ au_procfs_fin(); -+out_dbgaufs: -+ dbgaufs_fin(); -+out_sysaufs: -+ sysaufs_fin(); -+ au_dy_fin(); -+out: -+ return err; -+} -+ -+static void __exit aufs_exit(void) -+{ -+ unregister_filesystem(&aufs_fs_type); -+ au_cache_fin(); -+ au_sysrq_fin(); -+ au_hnotify_fin(); -+ au_loopback_fin(); -+ au_wkq_fin(); -+ au_procfs_fin(); -+ dbgaufs_fin(); -+ sysaufs_fin(); -+ au_dy_fin(); -+} -+ -+module_init(aufs_init); -+module_exit(aufs_exit); -diff --git a/fs/aufs/module.h b/fs/aufs/module.h -new file mode 100644 -index 000000000000..cf4679c65542 ---- /dev/null -+++ b/fs/aufs/module.h -@@ -0,0 +1,153 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * module initialization and module-global -+ */ -+ -+#ifndef __AUFS_MODULE_H__ -+#define __AUFS_MODULE_H__ -+ -+#ifdef __KERNEL__ -+ -+#include -+#include "debug.h" -+#include "dentry.h" -+#include "dir.h" -+#include "file.h" -+#include "inode.h" -+ -+struct path; -+struct seq_file; -+ -+/* module parameters */ -+extern int sysaufs_brs; -+extern bool au_userns; -+ -+/* ---------------------------------------------------------------------- */ -+ -+extern int au_dir_roflags; -+ -+void *au_krealloc(void *p, unsigned int new_sz, gfp_t gfp, int may_shrink); -+void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp, -+ int may_shrink); -+ -+/* -+ * Comparing the size of the object with sizeof(struct rcu_head) -+ * case 1: object is always larger -+ * --> au_kfree_rcu() or au_kfree_do_rcu() -+ * case 2: object is always smaller -+ * --> au_kfree_small() -+ * case 3: object can be any size -+ * --> au_kfree_try_rcu() -+ */ -+ -+static inline void au_kfree_do_rcu(const void *p) -+{ -+ struct { -+ struct rcu_head rcu; -+ } *a = (void *)p; -+ -+ kfree_rcu(a, rcu); -+} -+ -+#define au_kfree_rcu(_p) do { \ -+ typeof(_p) p = (_p); \ -+ BUILD_BUG_ON(sizeof(*p) < sizeof(struct rcu_head)); \ -+ if (p) \ -+ au_kfree_do_rcu(p); \ -+ } while (0) -+ -+#define au_kfree_do_sz_test(sz) (sz >= sizeof(struct rcu_head)) -+#define au_kfree_sz_test(p) (p && au_kfree_do_sz_test(ksize(p))) -+ -+static inline void au_kfree_try_rcu(const void *p) -+{ -+ if (!p) -+ return; -+ if (au_kfree_sz_test(p)) -+ au_kfree_do_rcu(p); -+ else -+ kfree(p); -+} -+ -+static inline void au_kfree_small(const void *p) -+{ -+ if (!p) -+ return; -+ AuDebugOn(au_kfree_sz_test(p)); -+ kfree(p); -+} -+ -+static inline int au_kmidx_sub(size_t sz, size_t new_sz) -+{ -+#ifndef CONFIG_SLOB -+ return kmalloc_index(sz) - kmalloc_index(new_sz); -+#else -+ return -1; /* SLOB is untested */ -+#endif -+} -+ -+int au_seq_path(struct seq_file *seq, struct path *path); -+ -+#ifdef CONFIG_PROC_FS -+/* procfs.c */ -+int __init au_procfs_init(void); -+void au_procfs_fin(void); -+#else -+AuStubInt0(au_procfs_init, void); -+AuStubVoid(au_procfs_fin, void); -+#endif -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* kmem cache */ -+enum { -+ AuCache_DINFO, -+ AuCache_ICNTNR, -+ AuCache_FINFO, -+ AuCache_VDIR, -+ AuCache_DEHSTR, -+ AuCache_HNOTIFY, /* must be last */ -+ AuCache_Last -+}; -+ -+extern struct kmem_cache *au_cache[AuCache_Last]; -+ -+#define AuCacheFlags (SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD) -+#define AuCache(type) KMEM_CACHE(type, AuCacheFlags) -+#define AuCacheCtor(type, ctor) \ -+ kmem_cache_create(#type, sizeof(struct type), \ -+ __alignof__(struct type), AuCacheFlags, ctor) -+ -+#define AuCacheFuncs(name, index) \ -+ static inline struct au_##name *au_cache_alloc_##name(void) \ -+ { return kmem_cache_alloc(au_cache[AuCache_##index], GFP_NOFS); } \ -+ static inline void au_cache_free_##name##_norcu(struct au_##name *p) \ -+ { kmem_cache_free(au_cache[AuCache_##index], p); } \ -+ \ -+ static inline void au_cache_free_##name##_rcu_cb(struct rcu_head *rcu) \ -+ { void *p = rcu; \ -+ p -= offsetof(struct au_##name, rcu); \ -+ kmem_cache_free(au_cache[AuCache_##index], p); } \ -+ static inline void au_cache_free_##name##_rcu(struct au_##name *p) \ -+ { BUILD_BUG_ON(sizeof(struct au_##name) < sizeof(struct rcu_head)); \ -+ call_rcu(&p->rcu, au_cache_free_##name##_rcu_cb); } \ -+ \ -+ static inline void au_cache_free_##name(struct au_##name *p) \ -+ { /* au_cache_free_##name##_norcu(p); */ \ -+ au_cache_free_##name##_rcu(p); } -+ -+AuCacheFuncs(dinfo, DINFO); -+AuCacheFuncs(icntnr, ICNTNR); -+AuCacheFuncs(finfo, FINFO); -+AuCacheFuncs(vdir, VDIR); -+AuCacheFuncs(vdir_dehstr, DEHSTR); -+#ifdef CONFIG_AUFS_HNOTIFY -+AuCacheFuncs(hnotify, HNOTIFY); -+#endif -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_MODULE_H__ */ -diff --git a/fs/aufs/mvdown.c b/fs/aufs/mvdown.c -new file mode 100644 -index 000000000000..d28a33f4a944 ---- /dev/null -+++ b/fs/aufs/mvdown.c -@@ -0,0 +1,693 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2011-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * move-down, opposite of copy-up -+ */ -+ -+#include "aufs.h" -+ -+struct au_mvd_args { -+ struct { -+ struct super_block *h_sb; -+ struct dentry *h_parent; -+ struct au_hinode *hdir; -+ struct inode *h_dir, *h_inode; -+ struct au_pin pin; -+ } info[AUFS_MVDOWN_NARRAY]; -+ -+ struct aufs_mvdown mvdown; -+ struct dentry *dentry, *parent; -+ struct inode *inode, *dir; -+ struct super_block *sb; -+ aufs_bindex_t bopq, bwh, bfound; -+ unsigned char rename_lock; -+}; -+ -+#define mvd_errno mvdown.au_errno -+#define mvd_bsrc mvdown.stbr[AUFS_MVDOWN_UPPER].bindex -+#define mvd_src_brid mvdown.stbr[AUFS_MVDOWN_UPPER].brid -+#define mvd_bdst mvdown.stbr[AUFS_MVDOWN_LOWER].bindex -+#define mvd_dst_brid mvdown.stbr[AUFS_MVDOWN_LOWER].brid -+ -+#define mvd_h_src_sb info[AUFS_MVDOWN_UPPER].h_sb -+#define mvd_h_src_parent info[AUFS_MVDOWN_UPPER].h_parent -+#define mvd_hdir_src info[AUFS_MVDOWN_UPPER].hdir -+#define mvd_h_src_dir info[AUFS_MVDOWN_UPPER].h_dir -+#define mvd_h_src_inode info[AUFS_MVDOWN_UPPER].h_inode -+#define mvd_pin_src info[AUFS_MVDOWN_UPPER].pin -+ -+#define mvd_h_dst_sb info[AUFS_MVDOWN_LOWER].h_sb -+#define mvd_h_dst_parent info[AUFS_MVDOWN_LOWER].h_parent -+#define mvd_hdir_dst info[AUFS_MVDOWN_LOWER].hdir -+#define mvd_h_dst_dir info[AUFS_MVDOWN_LOWER].h_dir -+#define mvd_h_dst_inode info[AUFS_MVDOWN_LOWER].h_inode -+#define mvd_pin_dst info[AUFS_MVDOWN_LOWER].pin -+ -+#define AU_MVD_PR(flag, ...) do { \ -+ if (flag) \ -+ pr_err(__VA_ARGS__); \ -+ } while (0) -+ -+static int find_lower_writable(struct au_mvd_args *a) -+{ -+ struct super_block *sb; -+ aufs_bindex_t bindex, bbot; -+ struct au_branch *br; -+ -+ sb = a->sb; -+ bindex = a->mvd_bsrc; -+ bbot = au_sbbot(sb); -+ if (a->mvdown.flags & AUFS_MVDOWN_FHSM_LOWER) -+ for (bindex++; bindex <= bbot; bindex++) { -+ br = au_sbr(sb, bindex); -+ if (au_br_fhsm(br->br_perm) -+ && !sb_rdonly(au_br_sb(br))) -+ return bindex; -+ } -+ else if (!(a->mvdown.flags & AUFS_MVDOWN_ROLOWER)) -+ for (bindex++; bindex <= bbot; bindex++) { -+ br = au_sbr(sb, bindex); -+ if (!au_br_rdonly(br)) -+ return bindex; -+ } -+ else -+ for (bindex++; bindex <= bbot; bindex++) { -+ br = au_sbr(sb, bindex); -+ if (!sb_rdonly(au_br_sb(br))) { -+ if (au_br_rdonly(br)) -+ a->mvdown.flags -+ |= AUFS_MVDOWN_ROLOWER_R; -+ return bindex; -+ } -+ } -+ -+ return -1; -+} -+ -+/* make the parent dir on bdst */ -+static int au_do_mkdir(const unsigned char dmsg, struct au_mvd_args *a) -+{ -+ int err; -+ -+ err = 0; -+ a->mvd_hdir_src = au_hi(a->dir, a->mvd_bsrc); -+ a->mvd_hdir_dst = au_hi(a->dir, a->mvd_bdst); -+ a->mvd_h_src_parent = au_h_dptr(a->parent, a->mvd_bsrc); -+ a->mvd_h_dst_parent = NULL; -+ if (au_dbbot(a->parent) >= a->mvd_bdst) -+ a->mvd_h_dst_parent = au_h_dptr(a->parent, a->mvd_bdst); -+ if (!a->mvd_h_dst_parent) { -+ err = au_cpdown_dirs(a->dentry, a->mvd_bdst); -+ if (unlikely(err)) { -+ AU_MVD_PR(dmsg, "cpdown_dirs failed\n"); -+ goto out; -+ } -+ a->mvd_h_dst_parent = au_h_dptr(a->parent, a->mvd_bdst); -+ } -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+/* lock them all */ -+static int au_do_lock(const unsigned char dmsg, struct au_mvd_args *a) -+{ -+ int err; -+ struct dentry *h_trap; -+ -+ a->mvd_h_src_sb = au_sbr_sb(a->sb, a->mvd_bsrc); -+ a->mvd_h_dst_sb = au_sbr_sb(a->sb, a->mvd_bdst); -+ err = au_pin(&a->mvd_pin_dst, a->dentry, a->mvd_bdst, -+ au_opt_udba(a->sb), -+ AuPin_MNT_WRITE | AuPin_DI_LOCKED); -+ AuTraceErr(err); -+ if (unlikely(err)) { -+ AU_MVD_PR(dmsg, "pin_dst failed\n"); -+ goto out; -+ } -+ -+ if (a->mvd_h_src_sb != a->mvd_h_dst_sb) { -+ a->rename_lock = 0; -+ au_pin_init(&a->mvd_pin_src, a->dentry, a->mvd_bsrc, -+ AuLsc_DI_PARENT, AuLsc_I_PARENT3, -+ au_opt_udba(a->sb), -+ AuPin_MNT_WRITE | AuPin_DI_LOCKED); -+ err = au_do_pin(&a->mvd_pin_src); -+ AuTraceErr(err); -+ a->mvd_h_src_dir = d_inode(a->mvd_h_src_parent); -+ if (unlikely(err)) { -+ AU_MVD_PR(dmsg, "pin_src failed\n"); -+ goto out_dst; -+ } -+ goto out; /* success */ -+ } -+ -+ a->rename_lock = 1; -+ au_pin_hdir_unlock(&a->mvd_pin_dst); -+ err = au_pin(&a->mvd_pin_src, a->dentry, a->mvd_bsrc, -+ au_opt_udba(a->sb), -+ AuPin_MNT_WRITE | AuPin_DI_LOCKED); -+ AuTraceErr(err); -+ a->mvd_h_src_dir = d_inode(a->mvd_h_src_parent); -+ if (unlikely(err)) { -+ AU_MVD_PR(dmsg, "pin_src failed\n"); -+ au_pin_hdir_lock(&a->mvd_pin_dst); -+ goto out_dst; -+ } -+ au_pin_hdir_unlock(&a->mvd_pin_src); -+ h_trap = vfsub_lock_rename(a->mvd_h_src_parent, a->mvd_hdir_src, -+ a->mvd_h_dst_parent, a->mvd_hdir_dst); -+ if (h_trap) { -+ err = (h_trap != a->mvd_h_src_parent); -+ if (err) -+ err = (h_trap != a->mvd_h_dst_parent); -+ } -+ BUG_ON(err); /* it should never happen */ -+ if (unlikely(a->mvd_h_src_dir != au_pinned_h_dir(&a->mvd_pin_src))) { -+ err = -EBUSY; -+ AuTraceErr(err); -+ vfsub_unlock_rename(a->mvd_h_src_parent, a->mvd_hdir_src, -+ a->mvd_h_dst_parent, a->mvd_hdir_dst); -+ au_pin_hdir_lock(&a->mvd_pin_src); -+ au_unpin(&a->mvd_pin_src); -+ au_pin_hdir_lock(&a->mvd_pin_dst); -+ goto out_dst; -+ } -+ goto out; /* success */ -+ -+out_dst: -+ au_unpin(&a->mvd_pin_dst); -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+static void au_do_unlock(const unsigned char dmsg, struct au_mvd_args *a) -+{ -+ if (!a->rename_lock) -+ au_unpin(&a->mvd_pin_src); -+ else { -+ vfsub_unlock_rename(a->mvd_h_src_parent, a->mvd_hdir_src, -+ a->mvd_h_dst_parent, a->mvd_hdir_dst); -+ au_pin_hdir_lock(&a->mvd_pin_src); -+ au_unpin(&a->mvd_pin_src); -+ au_pin_hdir_lock(&a->mvd_pin_dst); -+ } -+ au_unpin(&a->mvd_pin_dst); -+} -+ -+/* copy-down the file */ -+static int au_do_cpdown(const unsigned char dmsg, struct au_mvd_args *a) -+{ -+ int err; -+ struct au_cp_generic cpg = { -+ .dentry = a->dentry, -+ .bdst = a->mvd_bdst, -+ .bsrc = a->mvd_bsrc, -+ .len = -1, -+ .pin = &a->mvd_pin_dst, -+ .flags = AuCpup_DTIME | AuCpup_HOPEN -+ }; -+ -+ AuDbg("b%d, b%d\n", cpg.bsrc, cpg.bdst); -+ if (a->mvdown.flags & AUFS_MVDOWN_OWLOWER) -+ au_fset_cpup(cpg.flags, OVERWRITE); -+ if (a->mvdown.flags & AUFS_MVDOWN_ROLOWER) -+ au_fset_cpup(cpg.flags, RWDST); -+ err = au_sio_cpdown_simple(&cpg); -+ if (unlikely(err)) -+ AU_MVD_PR(dmsg, "cpdown failed\n"); -+ -+ AuTraceErr(err); -+ return err; -+} -+ -+/* -+ * unlink the whiteout on bdst if exist which may be created by UDBA while we -+ * were sleeping -+ */ -+static int au_do_unlink_wh(const unsigned char dmsg, struct au_mvd_args *a) -+{ -+ int err; -+ struct path h_path; -+ struct au_branch *br; -+ struct inode *delegated; -+ -+ br = au_sbr(a->sb, a->mvd_bdst); -+ h_path.dentry = au_wh_lkup(a->mvd_h_dst_parent, &a->dentry->d_name, br); -+ err = PTR_ERR(h_path.dentry); -+ if (IS_ERR(h_path.dentry)) { -+ AU_MVD_PR(dmsg, "wh_lkup failed\n"); -+ goto out; -+ } -+ -+ err = 0; -+ if (d_is_positive(h_path.dentry)) { -+ h_path.mnt = au_br_mnt(br); -+ delegated = NULL; -+ err = vfsub_unlink(d_inode(a->mvd_h_dst_parent), &h_path, -+ &delegated, /*force*/0); -+ if (unlikely(err == -EWOULDBLOCK)) { -+ pr_warn("cannot retry for NFSv4 delegation" -+ " for an internal unlink\n"); -+ iput(delegated); -+ } -+ if (unlikely(err)) -+ AU_MVD_PR(dmsg, "wh_unlink failed\n"); -+ } -+ dput(h_path.dentry); -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+/* -+ * unlink the topmost h_dentry -+ */ -+static int au_do_unlink(const unsigned char dmsg, struct au_mvd_args *a) -+{ -+ int err; -+ struct path h_path; -+ struct inode *delegated; -+ -+ h_path.mnt = au_sbr_mnt(a->sb, a->mvd_bsrc); -+ h_path.dentry = au_h_dptr(a->dentry, a->mvd_bsrc); -+ delegated = NULL; -+ err = vfsub_unlink(a->mvd_h_src_dir, &h_path, &delegated, /*force*/0); -+ if (unlikely(err == -EWOULDBLOCK)) { -+ pr_warn("cannot retry for NFSv4 delegation" -+ " for an internal unlink\n"); -+ iput(delegated); -+ } -+ if (unlikely(err)) -+ AU_MVD_PR(dmsg, "unlink failed\n"); -+ -+ AuTraceErr(err); -+ return err; -+} -+ -+/* Since mvdown succeeded, we ignore an error of this function */ -+static void au_do_stfs(const unsigned char dmsg, struct au_mvd_args *a) -+{ -+ int err; -+ struct au_branch *br; -+ -+ a->mvdown.flags |= AUFS_MVDOWN_STFS_FAILED; -+ br = au_sbr(a->sb, a->mvd_bsrc); -+ err = au_br_stfs(br, &a->mvdown.stbr[AUFS_MVDOWN_UPPER].stfs); -+ if (!err) { -+ br = au_sbr(a->sb, a->mvd_bdst); -+ a->mvdown.stbr[AUFS_MVDOWN_LOWER].brid = br->br_id; -+ err = au_br_stfs(br, &a->mvdown.stbr[AUFS_MVDOWN_LOWER].stfs); -+ } -+ if (!err) -+ a->mvdown.flags &= ~AUFS_MVDOWN_STFS_FAILED; -+ else -+ AU_MVD_PR(dmsg, "statfs failed (%d), ignored\n", err); -+} -+ -+/* -+ * copy-down the file and unlink the bsrc file. -+ * - unlink the bdst whout if exist -+ * - copy-down the file (with whtmp name and rename) -+ * - unlink the bsrc file -+ */ -+static int au_do_mvdown(const unsigned char dmsg, struct au_mvd_args *a) -+{ -+ int err; -+ -+ err = au_do_mkdir(dmsg, a); -+ if (!err) -+ err = au_do_lock(dmsg, a); -+ if (unlikely(err)) -+ goto out; -+ -+ /* -+ * do not revert the activities we made on bdst since they should be -+ * harmless in aufs. -+ */ -+ -+ err = au_do_cpdown(dmsg, a); -+ if (!err) -+ err = au_do_unlink_wh(dmsg, a); -+ if (!err && !(a->mvdown.flags & AUFS_MVDOWN_KUPPER)) -+ err = au_do_unlink(dmsg, a); -+ if (unlikely(err)) -+ goto out_unlock; -+ -+ AuDbg("%pd2, 0x%x, %d --> %d\n", -+ a->dentry, a->mvdown.flags, a->mvd_bsrc, a->mvd_bdst); -+ if (find_lower_writable(a) < 0) -+ a->mvdown.flags |= AUFS_MVDOWN_BOTTOM; -+ -+ if (a->mvdown.flags & AUFS_MVDOWN_STFS) -+ au_do_stfs(dmsg, a); -+ -+ /* maintain internal array */ -+ if (!(a->mvdown.flags & AUFS_MVDOWN_KUPPER)) { -+ au_set_h_dptr(a->dentry, a->mvd_bsrc, NULL); -+ au_set_dbtop(a->dentry, a->mvd_bdst); -+ au_set_h_iptr(a->inode, a->mvd_bsrc, NULL, /*flags*/0); -+ au_set_ibtop(a->inode, a->mvd_bdst); -+ } else { -+ /* hide the lower */ -+ au_set_h_dptr(a->dentry, a->mvd_bdst, NULL); -+ au_set_dbbot(a->dentry, a->mvd_bsrc); -+ au_set_h_iptr(a->inode, a->mvd_bdst, NULL, /*flags*/0); -+ au_set_ibbot(a->inode, a->mvd_bsrc); -+ } -+ if (au_dbbot(a->dentry) < a->mvd_bdst) -+ au_set_dbbot(a->dentry, a->mvd_bdst); -+ if (au_ibbot(a->inode) < a->mvd_bdst) -+ au_set_ibbot(a->inode, a->mvd_bdst); -+ -+out_unlock: -+ au_do_unlock(dmsg, a); -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* make sure the file is idle */ -+static int au_mvd_args_busy(const unsigned char dmsg, struct au_mvd_args *a) -+{ -+ int err, plinked; -+ -+ err = 0; -+ plinked = !!au_opt_test(au_mntflags(a->sb), PLINK); -+ if (au_dbtop(a->dentry) == a->mvd_bsrc -+ && au_dcount(a->dentry) == 1 -+ && atomic_read(&a->inode->i_count) == 1 -+ /* && a->mvd_h_src_inode->i_nlink == 1 */ -+ && (!plinked || !au_plink_test(a->inode)) -+ && a->inode->i_nlink == 1) -+ goto out; -+ -+ err = -EBUSY; -+ AU_MVD_PR(dmsg, -+ "b%d, d{b%d, c%d?}, i{c%d?, l%u}, hi{l%u}, p{%d, %d}\n", -+ a->mvd_bsrc, au_dbtop(a->dentry), au_dcount(a->dentry), -+ atomic_read(&a->inode->i_count), a->inode->i_nlink, -+ a->mvd_h_src_inode->i_nlink, -+ plinked, plinked ? au_plink_test(a->inode) : 0); -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+/* make sure the parent dir is fine */ -+static int au_mvd_args_parent(const unsigned char dmsg, -+ struct au_mvd_args *a) -+{ -+ int err; -+ aufs_bindex_t bindex; -+ -+ err = 0; -+ if (unlikely(au_alive_dir(a->parent))) { -+ err = -ENOENT; -+ AU_MVD_PR(dmsg, "parent dir is dead\n"); -+ goto out; -+ } -+ -+ a->bopq = au_dbdiropq(a->parent); -+ bindex = au_wbr_nonopq(a->dentry, a->mvd_bdst); -+ AuDbg("b%d\n", bindex); -+ if (unlikely((bindex >= 0 && bindex < a->mvd_bdst) -+ || (a->bopq != -1 && a->bopq < a->mvd_bdst))) { -+ err = -EINVAL; -+ a->mvd_errno = EAU_MVDOWN_OPAQUE; -+ AU_MVD_PR(dmsg, "ancestor is opaque b%d, b%d\n", -+ a->bopq, a->mvd_bdst); -+ } -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+static int au_mvd_args_intermediate(const unsigned char dmsg, -+ struct au_mvd_args *a) -+{ -+ int err; -+ struct au_dinfo *dinfo, *tmp; -+ -+ /* lookup the next lower positive entry */ -+ err = -ENOMEM; -+ tmp = au_di_alloc(a->sb, AuLsc_DI_TMP); -+ if (unlikely(!tmp)) -+ goto out; -+ -+ a->bfound = -1; -+ a->bwh = -1; -+ dinfo = au_di(a->dentry); -+ au_di_cp(tmp, dinfo); -+ au_di_swap(tmp, dinfo); -+ -+ /* returns the number of positive dentries */ -+ err = au_lkup_dentry(a->dentry, a->mvd_bsrc + 1, -+ /* AuLkup_IGNORE_PERM */ 0); -+ if (!err) -+ a->bwh = au_dbwh(a->dentry); -+ else if (err > 0) -+ a->bfound = au_dbtop(a->dentry); -+ -+ au_di_swap(tmp, dinfo); -+ au_rw_write_unlock(&tmp->di_rwsem); -+ au_di_free(tmp); -+ if (unlikely(err < 0)) -+ AU_MVD_PR(dmsg, "failed look-up lower\n"); -+ -+ /* -+ * here, we have these cases. -+ * bfound == -1 -+ * no positive dentry under bsrc. there are more sub-cases. -+ * bwh < 0 -+ * there no whiteout, we can safely move-down. -+ * bwh <= bsrc -+ * impossible -+ * bsrc < bwh && bwh < bdst -+ * there is a whiteout on RO branch. cannot proceed. -+ * bwh == bdst -+ * there is a whiteout on the RW target branch. it should -+ * be removed. -+ * bdst < bwh -+ * there is a whiteout somewhere unrelated branch. -+ * -1 < bfound && bfound <= bsrc -+ * impossible. -+ * bfound < bdst -+ * found, but it is on RO branch between bsrc and bdst. cannot -+ * proceed. -+ * bfound == bdst -+ * found, replace it if AUFS_MVDOWN_FORCE is set. otherwise return -+ * error. -+ * bdst < bfound -+ * found, after we create the file on bdst, it will be hidden. -+ */ -+ -+ AuDebugOn(a->bfound == -1 -+ && a->bwh != -1 -+ && a->bwh <= a->mvd_bsrc); -+ AuDebugOn(-1 < a->bfound -+ && a->bfound <= a->mvd_bsrc); -+ -+ err = -EINVAL; -+ if (a->bfound == -1 -+ && a->mvd_bsrc < a->bwh -+ && a->bwh != -1 -+ && a->bwh < a->mvd_bdst) { -+ a->mvd_errno = EAU_MVDOWN_WHITEOUT; -+ AU_MVD_PR(dmsg, "bsrc %d, bdst %d, bfound %d, bwh %d\n", -+ a->mvd_bsrc, a->mvd_bdst, a->bfound, a->bwh); -+ goto out; -+ } else if (a->bfound != -1 && a->bfound < a->mvd_bdst) { -+ a->mvd_errno = EAU_MVDOWN_UPPER; -+ AU_MVD_PR(dmsg, "bdst %d, bfound %d\n", -+ a->mvd_bdst, a->bfound); -+ goto out; -+ } -+ -+ err = 0; /* success */ -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+static int au_mvd_args_exist(const unsigned char dmsg, struct au_mvd_args *a) -+{ -+ int err; -+ -+ err = 0; -+ if (!(a->mvdown.flags & AUFS_MVDOWN_OWLOWER) -+ && a->bfound == a->mvd_bdst) -+ err = -EEXIST; -+ AuTraceErr(err); -+ return err; -+} -+ -+static int au_mvd_args(const unsigned char dmsg, struct au_mvd_args *a) -+{ -+ int err; -+ struct au_branch *br; -+ -+ err = -EISDIR; -+ if (unlikely(S_ISDIR(a->inode->i_mode))) -+ goto out; -+ -+ err = -EINVAL; -+ if (!(a->mvdown.flags & AUFS_MVDOWN_BRID_UPPER)) -+ a->mvd_bsrc = au_ibtop(a->inode); -+ else { -+ a->mvd_bsrc = au_br_index(a->sb, a->mvd_src_brid); -+ if (unlikely(a->mvd_bsrc < 0 -+ || (a->mvd_bsrc < au_dbtop(a->dentry) -+ || au_dbbot(a->dentry) < a->mvd_bsrc -+ || !au_h_dptr(a->dentry, a->mvd_bsrc)) -+ || (a->mvd_bsrc < au_ibtop(a->inode) -+ || au_ibbot(a->inode) < a->mvd_bsrc -+ || !au_h_iptr(a->inode, a->mvd_bsrc)))) { -+ a->mvd_errno = EAU_MVDOWN_NOUPPER; -+ AU_MVD_PR(dmsg, "no upper\n"); -+ goto out; -+ } -+ } -+ if (unlikely(a->mvd_bsrc == au_sbbot(a->sb))) { -+ a->mvd_errno = EAU_MVDOWN_BOTTOM; -+ AU_MVD_PR(dmsg, "on the bottom\n"); -+ goto out; -+ } -+ a->mvd_h_src_inode = au_h_iptr(a->inode, a->mvd_bsrc); -+ br = au_sbr(a->sb, a->mvd_bsrc); -+ err = au_br_rdonly(br); -+ if (!(a->mvdown.flags & AUFS_MVDOWN_ROUPPER)) { -+ if (unlikely(err)) -+ goto out; -+ } else if (!(vfsub_native_ro(a->mvd_h_src_inode) -+ || IS_APPEND(a->mvd_h_src_inode))) { -+ if (err) -+ a->mvdown.flags |= AUFS_MVDOWN_ROUPPER_R; -+ /* go on */ -+ } else -+ goto out; -+ -+ err = -EINVAL; -+ if (!(a->mvdown.flags & AUFS_MVDOWN_BRID_LOWER)) { -+ a->mvd_bdst = find_lower_writable(a); -+ if (unlikely(a->mvd_bdst < 0)) { -+ a->mvd_errno = EAU_MVDOWN_BOTTOM; -+ AU_MVD_PR(dmsg, "no writable lower branch\n"); -+ goto out; -+ } -+ } else { -+ a->mvd_bdst = au_br_index(a->sb, a->mvd_dst_brid); -+ if (unlikely(a->mvd_bdst < 0 -+ || au_sbbot(a->sb) < a->mvd_bdst)) { -+ a->mvd_errno = EAU_MVDOWN_NOLOWERBR; -+ AU_MVD_PR(dmsg, "no lower brid\n"); -+ goto out; -+ } -+ } -+ -+ err = au_mvd_args_busy(dmsg, a); -+ if (!err) -+ err = au_mvd_args_parent(dmsg, a); -+ if (!err) -+ err = au_mvd_args_intermediate(dmsg, a); -+ if (!err) -+ err = au_mvd_args_exist(dmsg, a); -+ if (!err) -+ AuDbg("b%d, b%d\n", a->mvd_bsrc, a->mvd_bdst); -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+int au_mvdown(struct dentry *dentry, struct aufs_mvdown __user *uarg) -+{ -+ int err, e; -+ unsigned char dmsg; -+ struct au_mvd_args *args; -+ struct inode *inode; -+ -+ inode = d_inode(dentry); -+ err = -EPERM; -+ if (unlikely(!capable(CAP_SYS_ADMIN))) -+ goto out; -+ -+ err = -ENOMEM; -+ args = kmalloc(sizeof(*args), GFP_NOFS); -+ if (unlikely(!args)) -+ goto out; -+ -+ err = copy_from_user(&args->mvdown, uarg, sizeof(args->mvdown)); -+ if (!err) -+ /* VERIFY_WRITE */ -+ err = !access_ok(uarg, sizeof(*uarg)); -+ if (unlikely(err)) { -+ err = -EFAULT; -+ AuTraceErr(err); -+ goto out_free; -+ } -+ AuDbg("flags 0x%x\n", args->mvdown.flags); -+ args->mvdown.flags &= ~(AUFS_MVDOWN_ROLOWER_R | AUFS_MVDOWN_ROUPPER_R); -+ args->mvdown.au_errno = 0; -+ args->dentry = dentry; -+ args->inode = inode; -+ args->sb = dentry->d_sb; -+ -+ err = -ENOENT; -+ dmsg = !!(args->mvdown.flags & AUFS_MVDOWN_DMSG); -+ args->parent = dget_parent(dentry); -+ args->dir = d_inode(args->parent); -+ inode_lock_nested(args->dir, I_MUTEX_PARENT); -+ dput(args->parent); -+ if (unlikely(args->parent != dentry->d_parent)) { -+ AU_MVD_PR(dmsg, "parent dir is moved\n"); -+ goto out_dir; -+ } -+ -+ inode_lock_nested(inode, I_MUTEX_CHILD); -+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH | AuLock_NOPLMW); -+ if (unlikely(err)) -+ goto out_inode; -+ -+ di_write_lock_parent(args->parent); -+ err = au_mvd_args(dmsg, args); -+ if (unlikely(err)) -+ goto out_parent; -+ -+ err = au_do_mvdown(dmsg, args); -+ if (unlikely(err)) -+ goto out_parent; -+ -+ au_cpup_attr_timesizes(args->dir); -+ au_cpup_attr_timesizes(inode); -+ if (!(args->mvdown.flags & AUFS_MVDOWN_KUPPER)) -+ au_cpup_igen(inode, au_h_iptr(inode, args->mvd_bdst)); -+ /* au_digen_dec(dentry); */ -+ -+out_parent: -+ di_write_unlock(args->parent); -+ aufs_read_unlock(dentry, AuLock_DW); -+out_inode: -+ inode_unlock(inode); -+out_dir: -+ inode_unlock(args->dir); -+out_free: -+ e = copy_to_user(uarg, &args->mvdown, sizeof(args->mvdown)); -+ if (unlikely(e)) -+ err = -EFAULT; -+ au_kfree_rcu(args); -+out: -+ AuTraceErr(err); -+ return err; -+} -diff --git a/fs/aufs/opts.c b/fs/aufs/opts.c -new file mode 100644 -index 000000000000..7448ed020e38 ---- /dev/null -+++ b/fs/aufs/opts.c -@@ -0,0 +1,1867 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * mount options/flags -+ */ -+ -+#include -+#include /* a distribution requires */ -+#include -+#include "aufs.h" -+ -+/* ---------------------------------------------------------------------- */ -+ -+enum { -+ Opt_br, -+ Opt_add, Opt_del, Opt_mod, Opt_append, Opt_prepend, -+ Opt_idel, Opt_imod, -+ Opt_dirwh, Opt_rdcache, Opt_rdblk, Opt_rdhash, -+ Opt_rdblk_def, Opt_rdhash_def, -+ Opt_xino, Opt_noxino, -+ Opt_trunc_xino, Opt_trunc_xino_v, Opt_notrunc_xino, -+ Opt_trunc_xino_path, Opt_itrunc_xino, -+ Opt_trunc_xib, Opt_notrunc_xib, -+ Opt_shwh, Opt_noshwh, -+ Opt_plink, Opt_noplink, Opt_list_plink, -+ Opt_udba, -+ Opt_dio, Opt_nodio, -+ Opt_diropq_a, Opt_diropq_w, -+ Opt_warn_perm, Opt_nowarn_perm, -+ Opt_wbr_copyup, Opt_wbr_create, -+ Opt_fhsm_sec, -+ Opt_verbose, Opt_noverbose, -+ Opt_sum, Opt_nosum, Opt_wsum, -+ Opt_dirperm1, Opt_nodirperm1, -+ Opt_dirren, Opt_nodirren, -+ Opt_acl, Opt_noacl, -+ Opt_tail, Opt_ignore, Opt_ignore_silent, Opt_err -+}; -+ -+static match_table_t options = { -+ {Opt_br, "br=%s"}, -+ {Opt_br, "br:%s"}, -+ -+ {Opt_add, "add=%d:%s"}, -+ {Opt_add, "add:%d:%s"}, -+ {Opt_add, "ins=%d:%s"}, -+ {Opt_add, "ins:%d:%s"}, -+ {Opt_append, "append=%s"}, -+ {Opt_append, "append:%s"}, -+ {Opt_prepend, "prepend=%s"}, -+ {Opt_prepend, "prepend:%s"}, -+ -+ {Opt_del, "del=%s"}, -+ {Opt_del, "del:%s"}, -+ /* {Opt_idel, "idel:%d"}, */ -+ {Opt_mod, "mod=%s"}, -+ {Opt_mod, "mod:%s"}, -+ /* {Opt_imod, "imod:%d:%s"}, */ -+ -+ {Opt_dirwh, "dirwh=%d"}, -+ -+ {Opt_xino, "xino=%s"}, -+ {Opt_noxino, "noxino"}, -+ {Opt_trunc_xino, "trunc_xino"}, -+ {Opt_trunc_xino_v, "trunc_xino_v=%d:%d"}, -+ {Opt_notrunc_xino, "notrunc_xino"}, -+ {Opt_trunc_xino_path, "trunc_xino=%s"}, -+ {Opt_itrunc_xino, "itrunc_xino=%d"}, -+ /* {Opt_zxino, "zxino=%s"}, */ -+ {Opt_trunc_xib, "trunc_xib"}, -+ {Opt_notrunc_xib, "notrunc_xib"}, -+ -+#ifdef CONFIG_PROC_FS -+ {Opt_plink, "plink"}, -+#else -+ {Opt_ignore_silent, "plink"}, -+#endif -+ -+ {Opt_noplink, "noplink"}, -+ -+#ifdef CONFIG_AUFS_DEBUG -+ {Opt_list_plink, "list_plink"}, -+#endif -+ -+ {Opt_udba, "udba=%s"}, -+ -+ {Opt_dio, "dio"}, -+ {Opt_nodio, "nodio"}, -+ -+#ifdef CONFIG_AUFS_DIRREN -+ {Opt_dirren, "dirren"}, -+ {Opt_nodirren, "nodirren"}, -+#else -+ {Opt_ignore, "dirren"}, -+ {Opt_ignore_silent, "nodirren"}, -+#endif -+ -+#ifdef CONFIG_AUFS_FHSM -+ {Opt_fhsm_sec, "fhsm_sec=%d"}, -+#else -+ {Opt_ignore, "fhsm_sec=%d"}, -+#endif -+ -+ {Opt_diropq_a, "diropq=always"}, -+ {Opt_diropq_a, "diropq=a"}, -+ {Opt_diropq_w, "diropq=whiteouted"}, -+ {Opt_diropq_w, "diropq=w"}, -+ -+ {Opt_warn_perm, "warn_perm"}, -+ {Opt_nowarn_perm, "nowarn_perm"}, -+ -+ /* keep them temporary */ -+ {Opt_ignore_silent, "nodlgt"}, -+ {Opt_ignore, "clean_plink"}, -+ -+#ifdef CONFIG_AUFS_SHWH -+ {Opt_shwh, "shwh"}, -+#endif -+ {Opt_noshwh, "noshwh"}, -+ -+ {Opt_dirperm1, "dirperm1"}, -+ {Opt_nodirperm1, "nodirperm1"}, -+ -+ {Opt_verbose, "verbose"}, -+ {Opt_verbose, "v"}, -+ {Opt_noverbose, "noverbose"}, -+ {Opt_noverbose, "quiet"}, -+ {Opt_noverbose, "q"}, -+ {Opt_noverbose, "silent"}, -+ -+ {Opt_sum, "sum"}, -+ {Opt_nosum, "nosum"}, -+ {Opt_wsum, "wsum"}, -+ -+ {Opt_rdcache, "rdcache=%d"}, -+ {Opt_rdblk, "rdblk=%d"}, -+ {Opt_rdblk_def, "rdblk=def"}, -+ {Opt_rdhash, "rdhash=%d"}, -+ {Opt_rdhash_def, "rdhash=def"}, -+ -+ {Opt_wbr_create, "create=%s"}, -+ {Opt_wbr_create, "create_policy=%s"}, -+ {Opt_wbr_copyup, "cpup=%s"}, -+ {Opt_wbr_copyup, "copyup=%s"}, -+ {Opt_wbr_copyup, "copyup_policy=%s"}, -+ -+ /* generic VFS flag */ -+#ifdef CONFIG_FS_POSIX_ACL -+ {Opt_acl, "acl"}, -+ {Opt_noacl, "noacl"}, -+#else -+ {Opt_ignore, "acl"}, -+ {Opt_ignore_silent, "noacl"}, -+#endif -+ -+ /* internal use for the scripts */ -+ {Opt_ignore_silent, "si=%s"}, -+ -+ {Opt_br, "dirs=%s"}, -+ {Opt_ignore, "debug=%d"}, -+ {Opt_ignore, "delete=whiteout"}, -+ {Opt_ignore, "delete=all"}, -+ {Opt_ignore, "imap=%s"}, -+ -+ /* temporary workaround, due to old mount(8)? */ -+ {Opt_ignore_silent, "relatime"}, -+ -+ {Opt_err, NULL} -+}; -+ -+/* ---------------------------------------------------------------------- */ -+ -+static const char *au_parser_pattern(int val, match_table_t tbl) -+{ -+ struct match_token *p; -+ -+ p = tbl; -+ while (p->pattern) { -+ if (p->token == val) -+ return p->pattern; -+ p++; -+ } -+ BUG(); -+ return "??"; -+} -+ -+static const char *au_optstr(int *val, match_table_t tbl) -+{ -+ struct match_token *p; -+ int v; -+ -+ v = *val; -+ if (!v) -+ goto out; -+ p = tbl; -+ while (p->pattern) { -+ if (p->token -+ && (v & p->token) == p->token) { -+ *val &= ~p->token; -+ return p->pattern; -+ } -+ p++; -+ } -+ -+out: -+ return NULL; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static match_table_t brperm = { -+ {AuBrPerm_RO, AUFS_BRPERM_RO}, -+ {AuBrPerm_RR, AUFS_BRPERM_RR}, -+ {AuBrPerm_RW, AUFS_BRPERM_RW}, -+ {0, NULL} -+}; -+ -+static match_table_t brattr = { -+ /* general */ -+ {AuBrAttr_COO_REG, AUFS_BRATTR_COO_REG}, -+ {AuBrAttr_COO_ALL, AUFS_BRATTR_COO_ALL}, -+ /* 'unpin' attrib is meaningless since linux-3.18-rc1 */ -+ {AuBrAttr_UNPIN, AUFS_BRATTR_UNPIN}, -+#ifdef CONFIG_AUFS_FHSM -+ {AuBrAttr_FHSM, AUFS_BRATTR_FHSM}, -+#endif -+#ifdef CONFIG_AUFS_XATTR -+ {AuBrAttr_ICEX, AUFS_BRATTR_ICEX}, -+ {AuBrAttr_ICEX_SEC, AUFS_BRATTR_ICEX_SEC}, -+ {AuBrAttr_ICEX_SYS, AUFS_BRATTR_ICEX_SYS}, -+ {AuBrAttr_ICEX_TR, AUFS_BRATTR_ICEX_TR}, -+ {AuBrAttr_ICEX_USR, AUFS_BRATTR_ICEX_USR}, -+ {AuBrAttr_ICEX_OTH, AUFS_BRATTR_ICEX_OTH}, -+#endif -+ -+ /* ro/rr branch */ -+ {AuBrRAttr_WH, AUFS_BRRATTR_WH}, -+ -+ /* rw branch */ -+ {AuBrWAttr_MOO, AUFS_BRWATTR_MOO}, -+ {AuBrWAttr_NoLinkWH, AUFS_BRWATTR_NLWH}, -+ -+ {0, NULL} -+}; -+ -+static int br_attr_val(char *str, match_table_t table, substring_t args[]) -+{ -+ int attr, v; -+ char *p; -+ -+ attr = 0; -+ do { -+ p = strchr(str, '+'); -+ if (p) -+ *p = 0; -+ v = match_token(str, table, args); -+ if (v) { -+ if (v & AuBrAttr_CMOO_Mask) -+ attr &= ~AuBrAttr_CMOO_Mask; -+ attr |= v; -+ } else { -+ if (p) -+ *p = '+'; -+ pr_warn("ignored branch attribute %s\n", str); -+ break; -+ } -+ if (p) -+ str = p + 1; -+ } while (p); -+ -+ return attr; -+} -+ -+static int au_do_optstr_br_attr(au_br_perm_str_t *str, int perm) -+{ -+ int sz; -+ const char *p; -+ char *q; -+ -+ q = str->a; -+ *q = 0; -+ p = au_optstr(&perm, brattr); -+ if (p) { -+ sz = strlen(p); -+ memcpy(q, p, sz + 1); -+ q += sz; -+ } else -+ goto out; -+ -+ do { -+ p = au_optstr(&perm, brattr); -+ if (p) { -+ *q++ = '+'; -+ sz = strlen(p); -+ memcpy(q, p, sz + 1); -+ q += sz; -+ } -+ } while (p); -+ -+out: -+ return q - str->a; -+} -+ -+static int noinline_for_stack br_perm_val(char *perm) -+{ -+ int val, bad, sz; -+ char *p; -+ substring_t args[MAX_OPT_ARGS]; -+ au_br_perm_str_t attr; -+ -+ p = strchr(perm, '+'); -+ if (p) -+ *p = 0; -+ val = match_token(perm, brperm, args); -+ if (!val) { -+ if (p) -+ *p = '+'; -+ pr_warn("ignored branch permission %s\n", perm); -+ val = AuBrPerm_RO; -+ goto out; -+ } -+ if (!p) -+ goto out; -+ -+ val |= br_attr_val(p + 1, brattr, args); -+ -+ bad = 0; -+ switch (val & AuBrPerm_Mask) { -+ case AuBrPerm_RO: -+ case AuBrPerm_RR: -+ bad = val & AuBrWAttr_Mask; -+ val &= ~AuBrWAttr_Mask; -+ break; -+ case AuBrPerm_RW: -+ bad = val & AuBrRAttr_Mask; -+ val &= ~AuBrRAttr_Mask; -+ break; -+ } -+ -+ /* -+ * 'unpin' attrib becomes meaningless since linux-3.18-rc1, but aufs -+ * does not treat it as an error, just warning. -+ * this is a tiny guard for the user operation. -+ */ -+ if (val & AuBrAttr_UNPIN) { -+ bad |= AuBrAttr_UNPIN; -+ val &= ~AuBrAttr_UNPIN; -+ } -+ -+ if (unlikely(bad)) { -+ sz = au_do_optstr_br_attr(&attr, bad); -+ AuDebugOn(!sz); -+ pr_warn("ignored branch attribute %s\n", attr.a); -+ } -+ -+out: -+ return val; -+} -+ -+void au_optstr_br_perm(au_br_perm_str_t *str, int perm) -+{ -+ au_br_perm_str_t attr; -+ const char *p; -+ char *q; -+ int sz; -+ -+ q = str->a; -+ p = au_optstr(&perm, brperm); -+ AuDebugOn(!p || !*p); -+ sz = strlen(p); -+ memcpy(q, p, sz + 1); -+ q += sz; -+ -+ sz = au_do_optstr_br_attr(&attr, perm); -+ if (sz) { -+ *q++ = '+'; -+ memcpy(q, attr.a, sz + 1); -+ } -+ -+ AuDebugOn(strlen(str->a) >= sizeof(str->a)); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static match_table_t udbalevel = { -+ {AuOpt_UDBA_REVAL, "reval"}, -+ {AuOpt_UDBA_NONE, "none"}, -+#ifdef CONFIG_AUFS_HNOTIFY -+ {AuOpt_UDBA_HNOTIFY, "notify"}, /* abstraction */ -+#ifdef CONFIG_AUFS_HFSNOTIFY -+ {AuOpt_UDBA_HNOTIFY, "fsnotify"}, -+#endif -+#endif -+ {-1, NULL} -+}; -+ -+static int noinline_for_stack udba_val(char *str) -+{ -+ substring_t args[MAX_OPT_ARGS]; -+ -+ return match_token(str, udbalevel, args); -+} -+ -+const char *au_optstr_udba(int udba) -+{ -+ return au_parser_pattern(udba, udbalevel); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static match_table_t au_wbr_create_policy = { -+ {AuWbrCreate_TDP, "tdp"}, -+ {AuWbrCreate_TDP, "top-down-parent"}, -+ {AuWbrCreate_RR, "rr"}, -+ {AuWbrCreate_RR, "round-robin"}, -+ {AuWbrCreate_MFS, "mfs"}, -+ {AuWbrCreate_MFS, "most-free-space"}, -+ {AuWbrCreate_MFSV, "mfs:%d"}, -+ {AuWbrCreate_MFSV, "most-free-space:%d"}, -+ -+ /* top-down regardless the parent, and then mfs */ -+ {AuWbrCreate_TDMFS, "tdmfs:%d"}, -+ {AuWbrCreate_TDMFSV, "tdmfs:%d:%d"}, -+ -+ {AuWbrCreate_MFSRR, "mfsrr:%d"}, -+ {AuWbrCreate_MFSRRV, "mfsrr:%d:%d"}, -+ {AuWbrCreate_PMFS, "pmfs"}, -+ {AuWbrCreate_PMFSV, "pmfs:%d"}, -+ {AuWbrCreate_PMFSRR, "pmfsrr:%d"}, -+ {AuWbrCreate_PMFSRRV, "pmfsrr:%d:%d"}, -+ -+ {-1, NULL} -+}; -+ -+static int au_wbr_mfs_wmark(substring_t *arg, char *str, -+ struct au_opt_wbr_create *create) -+{ -+ int err; -+ unsigned long long ull; -+ -+ err = 0; -+ if (!match_u64(arg, &ull)) -+ create->mfsrr_watermark = ull; -+ else { -+ pr_err("bad integer in %s\n", str); -+ err = -EINVAL; -+ } -+ -+ return err; -+} -+ -+static int au_wbr_mfs_sec(substring_t *arg, char *str, -+ struct au_opt_wbr_create *create) -+{ -+ int n, err; -+ -+ err = 0; -+ if (!match_int(arg, &n) && 0 <= n && n <= AUFS_MFS_MAX_SEC) -+ create->mfs_second = n; -+ else { -+ pr_err("bad integer in %s\n", str); -+ err = -EINVAL; -+ } -+ -+ return err; -+} -+ -+static int noinline_for_stack -+au_wbr_create_val(char *str, struct au_opt_wbr_create *create) -+{ -+ int err, e; -+ substring_t args[MAX_OPT_ARGS]; -+ -+ err = match_token(str, au_wbr_create_policy, args); -+ create->wbr_create = err; -+ switch (err) { -+ case AuWbrCreate_MFSRRV: -+ case AuWbrCreate_TDMFSV: -+ case AuWbrCreate_PMFSRRV: -+ e = au_wbr_mfs_wmark(&args[0], str, create); -+ if (!e) -+ e = au_wbr_mfs_sec(&args[1], str, create); -+ if (unlikely(e)) -+ err = e; -+ break; -+ case AuWbrCreate_MFSRR: -+ case AuWbrCreate_TDMFS: -+ case AuWbrCreate_PMFSRR: -+ e = au_wbr_mfs_wmark(&args[0], str, create); -+ if (unlikely(e)) { -+ err = e; -+ break; -+ } -+ /*FALLTHROUGH*/ -+ case AuWbrCreate_MFS: -+ case AuWbrCreate_PMFS: -+ create->mfs_second = AUFS_MFS_DEF_SEC; -+ break; -+ case AuWbrCreate_MFSV: -+ case AuWbrCreate_PMFSV: -+ e = au_wbr_mfs_sec(&args[0], str, create); -+ if (unlikely(e)) -+ err = e; -+ break; -+ } -+ -+ return err; -+} -+ -+const char *au_optstr_wbr_create(int wbr_create) -+{ -+ return au_parser_pattern(wbr_create, au_wbr_create_policy); -+} -+ -+static match_table_t au_wbr_copyup_policy = { -+ {AuWbrCopyup_TDP, "tdp"}, -+ {AuWbrCopyup_TDP, "top-down-parent"}, -+ {AuWbrCopyup_BUP, "bup"}, -+ {AuWbrCopyup_BUP, "bottom-up-parent"}, -+ {AuWbrCopyup_BU, "bu"}, -+ {AuWbrCopyup_BU, "bottom-up"}, -+ {-1, NULL} -+}; -+ -+static int noinline_for_stack au_wbr_copyup_val(char *str) -+{ -+ substring_t args[MAX_OPT_ARGS]; -+ -+ return match_token(str, au_wbr_copyup_policy, args); -+} -+ -+const char *au_optstr_wbr_copyup(int wbr_copyup) -+{ -+ return au_parser_pattern(wbr_copyup, au_wbr_copyup_policy); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static const int lkup_dirflags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY; -+ -+static void dump_opts(struct au_opts *opts) -+{ -+#ifdef CONFIG_AUFS_DEBUG -+ /* reduce stack space */ -+ union { -+ struct au_opt_add *add; -+ struct au_opt_del *del; -+ struct au_opt_mod *mod; -+ struct au_opt_xino *xino; -+ struct au_opt_xino_itrunc *xino_itrunc; -+ struct au_opt_wbr_create *create; -+ } u; -+ struct au_opt *opt; -+ -+ opt = opts->opt; -+ while (opt->type != Opt_tail) { -+ switch (opt->type) { -+ case Opt_add: -+ u.add = &opt->add; -+ AuDbg("add {b%d, %s, 0x%x, %p}\n", -+ u.add->bindex, u.add->pathname, u.add->perm, -+ u.add->path.dentry); -+ break; -+ case Opt_del: -+ case Opt_idel: -+ u.del = &opt->del; -+ AuDbg("del {%s, %p}\n", -+ u.del->pathname, u.del->h_path.dentry); -+ break; -+ case Opt_mod: -+ case Opt_imod: -+ u.mod = &opt->mod; -+ AuDbg("mod {%s, 0x%x, %p}\n", -+ u.mod->path, u.mod->perm, u.mod->h_root); -+ break; -+ case Opt_append: -+ u.add = &opt->add; -+ AuDbg("append {b%d, %s, 0x%x, %p}\n", -+ u.add->bindex, u.add->pathname, u.add->perm, -+ u.add->path.dentry); -+ break; -+ case Opt_prepend: -+ u.add = &opt->add; -+ AuDbg("prepend {b%d, %s, 0x%x, %p}\n", -+ u.add->bindex, u.add->pathname, u.add->perm, -+ u.add->path.dentry); -+ break; -+ case Opt_dirwh: -+ AuDbg("dirwh %d\n", opt->dirwh); -+ break; -+ case Opt_rdcache: -+ AuDbg("rdcache %d\n", opt->rdcache); -+ break; -+ case Opt_rdblk: -+ AuDbg("rdblk %u\n", opt->rdblk); -+ break; -+ case Opt_rdblk_def: -+ AuDbg("rdblk_def\n"); -+ break; -+ case Opt_rdhash: -+ AuDbg("rdhash %u\n", opt->rdhash); -+ break; -+ case Opt_rdhash_def: -+ AuDbg("rdhash_def\n"); -+ break; -+ case Opt_xino: -+ u.xino = &opt->xino; -+ AuDbg("xino {%s %pD}\n", u.xino->path, u.xino->file); -+ break; -+ case Opt_trunc_xino: -+ AuLabel(trunc_xino); -+ break; -+ case Opt_notrunc_xino: -+ AuLabel(notrunc_xino); -+ break; -+ case Opt_trunc_xino_path: -+ case Opt_itrunc_xino: -+ u.xino_itrunc = &opt->xino_itrunc; -+ AuDbg("trunc_xino %d\n", u.xino_itrunc->bindex); -+ break; -+ case Opt_noxino: -+ AuLabel(noxino); -+ break; -+ case Opt_trunc_xib: -+ AuLabel(trunc_xib); -+ break; -+ case Opt_notrunc_xib: -+ AuLabel(notrunc_xib); -+ break; -+ case Opt_shwh: -+ AuLabel(shwh); -+ break; -+ case Opt_noshwh: -+ AuLabel(noshwh); -+ break; -+ case Opt_dirperm1: -+ AuLabel(dirperm1); -+ break; -+ case Opt_nodirperm1: -+ AuLabel(nodirperm1); -+ break; -+ case Opt_plink: -+ AuLabel(plink); -+ break; -+ case Opt_noplink: -+ AuLabel(noplink); -+ break; -+ case Opt_list_plink: -+ AuLabel(list_plink); -+ break; -+ case Opt_udba: -+ AuDbg("udba %d, %s\n", -+ opt->udba, au_optstr_udba(opt->udba)); -+ break; -+ case Opt_dio: -+ AuLabel(dio); -+ break; -+ case Opt_nodio: -+ AuLabel(nodio); -+ break; -+ case Opt_diropq_a: -+ AuLabel(diropq_a); -+ break; -+ case Opt_diropq_w: -+ AuLabel(diropq_w); -+ break; -+ case Opt_warn_perm: -+ AuLabel(warn_perm); -+ break; -+ case Opt_nowarn_perm: -+ AuLabel(nowarn_perm); -+ break; -+ case Opt_verbose: -+ AuLabel(verbose); -+ break; -+ case Opt_noverbose: -+ AuLabel(noverbose); -+ break; -+ case Opt_sum: -+ AuLabel(sum); -+ break; -+ case Opt_nosum: -+ AuLabel(nosum); -+ break; -+ case Opt_wsum: -+ AuLabel(wsum); -+ break; -+ case Opt_wbr_create: -+ u.create = &opt->wbr_create; -+ AuDbg("create %d, %s\n", u.create->wbr_create, -+ au_optstr_wbr_create(u.create->wbr_create)); -+ switch (u.create->wbr_create) { -+ case AuWbrCreate_MFSV: -+ case AuWbrCreate_PMFSV: -+ AuDbg("%d sec\n", u.create->mfs_second); -+ break; -+ case AuWbrCreate_MFSRR: -+ case AuWbrCreate_TDMFS: -+ AuDbg("%llu watermark\n", -+ u.create->mfsrr_watermark); -+ break; -+ case AuWbrCreate_MFSRRV: -+ case AuWbrCreate_TDMFSV: -+ case AuWbrCreate_PMFSRRV: -+ AuDbg("%llu watermark, %d sec\n", -+ u.create->mfsrr_watermark, -+ u.create->mfs_second); -+ break; -+ } -+ break; -+ case Opt_wbr_copyup: -+ AuDbg("copyup %d, %s\n", opt->wbr_copyup, -+ au_optstr_wbr_copyup(opt->wbr_copyup)); -+ break; -+ case Opt_fhsm_sec: -+ AuDbg("fhsm_sec %u\n", opt->fhsm_second); -+ break; -+ case Opt_dirren: -+ AuLabel(dirren); -+ break; -+ case Opt_nodirren: -+ AuLabel(nodirren); -+ break; -+ case Opt_acl: -+ AuLabel(acl); -+ break; -+ case Opt_noacl: -+ AuLabel(noacl); -+ break; -+ default: -+ BUG(); -+ } -+ opt++; -+ } -+#endif -+} -+ -+void au_opts_free(struct au_opts *opts) -+{ -+ struct au_opt *opt; -+ -+ opt = opts->opt; -+ while (opt->type != Opt_tail) { -+ switch (opt->type) { -+ case Opt_add: -+ case Opt_append: -+ case Opt_prepend: -+ path_put(&opt->add.path); -+ break; -+ case Opt_del: -+ case Opt_idel: -+ path_put(&opt->del.h_path); -+ break; -+ case Opt_mod: -+ case Opt_imod: -+ dput(opt->mod.h_root); -+ break; -+ case Opt_xino: -+ fput(opt->xino.file); -+ break; -+ } -+ opt++; -+ } -+} -+ -+static int opt_add(struct au_opt *opt, char *opt_str, unsigned long sb_flags, -+ aufs_bindex_t bindex) -+{ -+ int err; -+ struct au_opt_add *add = &opt->add; -+ char *p; -+ -+ add->bindex = bindex; -+ add->perm = AuBrPerm_RO; -+ add->pathname = opt_str; -+ p = strchr(opt_str, '='); -+ if (p) { -+ *p++ = 0; -+ if (*p) -+ add->perm = br_perm_val(p); -+ } -+ -+ err = vfsub_kern_path(add->pathname, lkup_dirflags, &add->path); -+ if (!err) { -+ if (!p) { -+ add->perm = AuBrPerm_RO; -+ if (au_test_fs_rr(add->path.dentry->d_sb)) -+ add->perm = AuBrPerm_RR; -+ else if (!bindex && !(sb_flags & SB_RDONLY)) -+ add->perm = AuBrPerm_RW; -+ } -+ opt->type = Opt_add; -+ goto out; -+ } -+ pr_err("lookup failed %s (%d)\n", add->pathname, err); -+ err = -EINVAL; -+ -+out: -+ return err; -+} -+ -+static int au_opts_parse_del(struct au_opt_del *del, substring_t args[]) -+{ -+ int err; -+ -+ del->pathname = args[0].from; -+ AuDbg("del path %s\n", del->pathname); -+ -+ err = vfsub_kern_path(del->pathname, lkup_dirflags, &del->h_path); -+ if (unlikely(err)) -+ pr_err("lookup failed %s (%d)\n", del->pathname, err); -+ -+ return err; -+} -+ -+#if 0 /* reserved for future use */ -+static int au_opts_parse_idel(struct super_block *sb, aufs_bindex_t bindex, -+ struct au_opt_del *del, substring_t args[]) -+{ -+ int err; -+ struct dentry *root; -+ -+ err = -EINVAL; -+ root = sb->s_root; -+ aufs_read_lock(root, AuLock_FLUSH); -+ if (bindex < 0 || au_sbbot(sb) < bindex) { -+ pr_err("out of bounds, %d\n", bindex); -+ goto out; -+ } -+ -+ err = 0; -+ del->h_path.dentry = dget(au_h_dptr(root, bindex)); -+ del->h_path.mnt = mntget(au_sbr_mnt(sb, bindex)); -+ -+out: -+ aufs_read_unlock(root, !AuLock_IR); -+ return err; -+} -+#endif -+ -+static int noinline_for_stack -+au_opts_parse_mod(struct au_opt_mod *mod, substring_t args[]) -+{ -+ int err; -+ struct path path; -+ char *p; -+ -+ err = -EINVAL; -+ mod->path = args[0].from; -+ p = strchr(mod->path, '='); -+ if (unlikely(!p)) { -+ pr_err("no permission %s\n", args[0].from); -+ goto out; -+ } -+ -+ *p++ = 0; -+ err = vfsub_kern_path(mod->path, lkup_dirflags, &path); -+ if (unlikely(err)) { -+ pr_err("lookup failed %s (%d)\n", mod->path, err); -+ goto out; -+ } -+ -+ mod->perm = br_perm_val(p); -+ AuDbg("mod path %s, perm 0x%x, %s\n", mod->path, mod->perm, p); -+ mod->h_root = dget(path.dentry); -+ path_put(&path); -+ -+out: -+ return err; -+} -+ -+#if 0 /* reserved for future use */ -+static int au_opts_parse_imod(struct super_block *sb, aufs_bindex_t bindex, -+ struct au_opt_mod *mod, substring_t args[]) -+{ -+ int err; -+ struct dentry *root; -+ -+ err = -EINVAL; -+ root = sb->s_root; -+ aufs_read_lock(root, AuLock_FLUSH); -+ if (bindex < 0 || au_sbbot(sb) < bindex) { -+ pr_err("out of bounds, %d\n", bindex); -+ goto out; -+ } -+ -+ err = 0; -+ mod->perm = br_perm_val(args[1].from); -+ AuDbg("mod path %s, perm 0x%x, %s\n", -+ mod->path, mod->perm, args[1].from); -+ mod->h_root = dget(au_h_dptr(root, bindex)); -+ -+out: -+ aufs_read_unlock(root, !AuLock_IR); -+ return err; -+} -+#endif -+ -+static int au_opts_parse_xino(struct super_block *sb, struct au_opt_xino *xino, -+ substring_t args[]) -+{ -+ int err; -+ struct file *file; -+ -+ file = au_xino_create(sb, args[0].from, /*silent*/0, /*wbrtop*/0); -+ err = PTR_ERR(file); -+ if (IS_ERR(file)) -+ goto out; -+ -+ err = -EINVAL; -+ if (unlikely(file->f_path.dentry->d_sb == sb)) { -+ fput(file); -+ pr_err("%s must be outside\n", args[0].from); -+ goto out; -+ } -+ -+ err = 0; -+ xino->file = file; -+ xino->path = args[0].from; -+ -+out: -+ return err; -+} -+ -+static int noinline_for_stack -+au_opts_parse_xino_itrunc_path(struct super_block *sb, -+ struct au_opt_xino_itrunc *xino_itrunc, -+ substring_t args[]) -+{ -+ int err; -+ aufs_bindex_t bbot, bindex; -+ struct path path; -+ struct dentry *root; -+ -+ err = vfsub_kern_path(args[0].from, lkup_dirflags, &path); -+ if (unlikely(err)) { -+ pr_err("lookup failed %s (%d)\n", args[0].from, err); -+ goto out; -+ } -+ -+ xino_itrunc->bindex = -1; -+ root = sb->s_root; -+ aufs_read_lock(root, AuLock_FLUSH); -+ bbot = au_sbbot(sb); -+ for (bindex = 0; bindex <= bbot; bindex++) { -+ if (au_h_dptr(root, bindex) == path.dentry) { -+ xino_itrunc->bindex = bindex; -+ break; -+ } -+ } -+ aufs_read_unlock(root, !AuLock_IR); -+ path_put(&path); -+ -+ if (unlikely(xino_itrunc->bindex < 0)) { -+ pr_err("no such branch %s\n", args[0].from); -+ err = -EINVAL; -+ } -+ -+out: -+ return err; -+} -+ -+/* called without aufs lock */ -+int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts) -+{ -+ int err, n, token; -+ aufs_bindex_t bindex; -+ unsigned char skipped; -+ struct dentry *root; -+ struct au_opt *opt, *opt_tail; -+ char *opt_str; -+ /* reduce the stack space */ -+ union { -+ struct au_opt_xino_itrunc *xino_itrunc; -+ struct au_opt_wbr_create *create; -+ } u; -+ struct { -+ substring_t args[MAX_OPT_ARGS]; -+ } *a; -+ -+ err = -ENOMEM; -+ a = kmalloc(sizeof(*a), GFP_NOFS); -+ if (unlikely(!a)) -+ goto out; -+ -+ root = sb->s_root; -+ err = 0; -+ bindex = 0; -+ opt = opts->opt; -+ opt_tail = opt + opts->max_opt - 1; -+ opt->type = Opt_tail; -+ while (!err && (opt_str = strsep(&str, ",")) && *opt_str) { -+ err = -EINVAL; -+ skipped = 0; -+ token = match_token(opt_str, options, a->args); -+ switch (token) { -+ case Opt_br: -+ err = 0; -+ while (!err && (opt_str = strsep(&a->args[0].from, ":")) -+ && *opt_str) { -+ err = opt_add(opt, opt_str, opts->sb_flags, -+ bindex++); -+ if (unlikely(!err && ++opt > opt_tail)) { -+ err = -E2BIG; -+ break; -+ } -+ opt->type = Opt_tail; -+ skipped = 1; -+ } -+ break; -+ case Opt_add: -+ if (unlikely(match_int(&a->args[0], &n))) { -+ pr_err("bad integer in %s\n", opt_str); -+ break; -+ } -+ bindex = n; -+ err = opt_add(opt, a->args[1].from, opts->sb_flags, -+ bindex); -+ if (!err) -+ opt->type = token; -+ break; -+ case Opt_append: -+ err = opt_add(opt, a->args[0].from, opts->sb_flags, -+ /*dummy bindex*/1); -+ if (!err) -+ opt->type = token; -+ break; -+ case Opt_prepend: -+ err = opt_add(opt, a->args[0].from, opts->sb_flags, -+ /*bindex*/0); -+ if (!err) -+ opt->type = token; -+ break; -+ case Opt_del: -+ err = au_opts_parse_del(&opt->del, a->args); -+ if (!err) -+ opt->type = token; -+ break; -+#if 0 /* reserved for future use */ -+ case Opt_idel: -+ del->pathname = "(indexed)"; -+ if (unlikely(match_int(&args[0], &n))) { -+ pr_err("bad integer in %s\n", opt_str); -+ break; -+ } -+ err = au_opts_parse_idel(sb, n, &opt->del, a->args); -+ if (!err) -+ opt->type = token; -+ break; -+#endif -+ case Opt_mod: -+ err = au_opts_parse_mod(&opt->mod, a->args); -+ if (!err) -+ opt->type = token; -+ break; -+#ifdef IMOD /* reserved for future use */ -+ case Opt_imod: -+ u.mod->path = "(indexed)"; -+ if (unlikely(match_int(&a->args[0], &n))) { -+ pr_err("bad integer in %s\n", opt_str); -+ break; -+ } -+ err = au_opts_parse_imod(sb, n, &opt->mod, a->args); -+ if (!err) -+ opt->type = token; -+ break; -+#endif -+ case Opt_xino: -+ err = au_opts_parse_xino(sb, &opt->xino, a->args); -+ if (!err) -+ opt->type = token; -+ break; -+ -+ case Opt_trunc_xino_path: -+ err = au_opts_parse_xino_itrunc_path -+ (sb, &opt->xino_itrunc, a->args); -+ if (!err) -+ opt->type = token; -+ break; -+ -+ case Opt_itrunc_xino: -+ u.xino_itrunc = &opt->xino_itrunc; -+ if (unlikely(match_int(&a->args[0], &n))) { -+ pr_err("bad integer in %s\n", opt_str); -+ break; -+ } -+ u.xino_itrunc->bindex = n; -+ aufs_read_lock(root, AuLock_FLUSH); -+ if (n < 0 || au_sbbot(sb) < n) { -+ pr_err("out of bounds, %d\n", n); -+ aufs_read_unlock(root, !AuLock_IR); -+ break; -+ } -+ aufs_read_unlock(root, !AuLock_IR); -+ err = 0; -+ opt->type = token; -+ break; -+ -+ case Opt_dirwh: -+ if (unlikely(match_int(&a->args[0], &opt->dirwh))) -+ break; -+ err = 0; -+ opt->type = token; -+ break; -+ -+ case Opt_rdcache: -+ if (unlikely(match_int(&a->args[0], &n))) { -+ pr_err("bad integer in %s\n", opt_str); -+ break; -+ } -+ if (unlikely(n > AUFS_RDCACHE_MAX)) { -+ pr_err("rdcache must be smaller than %d\n", -+ AUFS_RDCACHE_MAX); -+ break; -+ } -+ opt->rdcache = n; -+ err = 0; -+ opt->type = token; -+ break; -+ case Opt_rdblk: -+ if (unlikely(match_int(&a->args[0], &n) -+ || n < 0 -+ || n > KMALLOC_MAX_SIZE)) { -+ pr_err("bad integer in %s\n", opt_str); -+ break; -+ } -+ if (unlikely(n && n < NAME_MAX)) { -+ pr_err("rdblk must be larger than %d\n", -+ NAME_MAX); -+ break; -+ } -+ opt->rdblk = n; -+ err = 0; -+ opt->type = token; -+ break; -+ case Opt_rdhash: -+ if (unlikely(match_int(&a->args[0], &n) -+ || n < 0 -+ || n * sizeof(struct hlist_head) -+ > KMALLOC_MAX_SIZE)) { -+ pr_err("bad integer in %s\n", opt_str); -+ break; -+ } -+ opt->rdhash = n; -+ err = 0; -+ opt->type = token; -+ break; -+ -+ case Opt_trunc_xino: -+ case Opt_notrunc_xino: -+ case Opt_noxino: -+ case Opt_trunc_xib: -+ case Opt_notrunc_xib: -+ case Opt_shwh: -+ case Opt_noshwh: -+ case Opt_dirperm1: -+ case Opt_nodirperm1: -+ case Opt_plink: -+ case Opt_noplink: -+ case Opt_list_plink: -+ case Opt_dio: -+ case Opt_nodio: -+ case Opt_diropq_a: -+ case Opt_diropq_w: -+ case Opt_warn_perm: -+ case Opt_nowarn_perm: -+ case Opt_verbose: -+ case Opt_noverbose: -+ case Opt_sum: -+ case Opt_nosum: -+ case Opt_wsum: -+ case Opt_rdblk_def: -+ case Opt_rdhash_def: -+ case Opt_dirren: -+ case Opt_nodirren: -+ case Opt_acl: -+ case Opt_noacl: -+ err = 0; -+ opt->type = token; -+ break; -+ -+ case Opt_udba: -+ opt->udba = udba_val(a->args[0].from); -+ if (opt->udba >= 0) { -+ err = 0; -+ opt->type = token; -+ } else -+ pr_err("wrong value, %s\n", opt_str); -+ break; -+ -+ case Opt_wbr_create: -+ u.create = &opt->wbr_create; -+ u.create->wbr_create -+ = au_wbr_create_val(a->args[0].from, u.create); -+ if (u.create->wbr_create >= 0) { -+ err = 0; -+ opt->type = token; -+ } else -+ pr_err("wrong value, %s\n", opt_str); -+ break; -+ case Opt_wbr_copyup: -+ opt->wbr_copyup = au_wbr_copyup_val(a->args[0].from); -+ if (opt->wbr_copyup >= 0) { -+ err = 0; -+ opt->type = token; -+ } else -+ pr_err("wrong value, %s\n", opt_str); -+ break; -+ -+ case Opt_fhsm_sec: -+ if (unlikely(match_int(&a->args[0], &n) -+ || n < 0)) { -+ pr_err("bad integer in %s\n", opt_str); -+ break; -+ } -+ if (sysaufs_brs) { -+ opt->fhsm_second = n; -+ opt->type = token; -+ } else -+ pr_warn("ignored %s\n", opt_str); -+ err = 0; -+ break; -+ -+ case Opt_ignore: -+ pr_warn("ignored %s\n", opt_str); -+ /*FALLTHROUGH*/ -+ case Opt_ignore_silent: -+ skipped = 1; -+ err = 0; -+ break; -+ case Opt_err: -+ pr_err("unknown option %s\n", opt_str); -+ break; -+ } -+ -+ if (!err && !skipped) { -+ if (unlikely(++opt > opt_tail)) { -+ err = -E2BIG; -+ opt--; -+ opt->type = Opt_tail; -+ break; -+ } -+ opt->type = Opt_tail; -+ } -+ } -+ -+ au_kfree_rcu(a); -+ dump_opts(opts); -+ if (unlikely(err)) -+ au_opts_free(opts); -+ -+out: -+ return err; -+} -+ -+static int au_opt_wbr_create(struct super_block *sb, -+ struct au_opt_wbr_create *create) -+{ -+ int err; -+ struct au_sbinfo *sbinfo; -+ -+ SiMustWriteLock(sb); -+ -+ err = 1; /* handled */ -+ sbinfo = au_sbi(sb); -+ if (sbinfo->si_wbr_create_ops->fin) { -+ err = sbinfo->si_wbr_create_ops->fin(sb); -+ if (!err) -+ err = 1; -+ } -+ -+ sbinfo->si_wbr_create = create->wbr_create; -+ sbinfo->si_wbr_create_ops = au_wbr_create_ops + create->wbr_create; -+ switch (create->wbr_create) { -+ case AuWbrCreate_MFSRRV: -+ case AuWbrCreate_MFSRR: -+ case AuWbrCreate_TDMFS: -+ case AuWbrCreate_TDMFSV: -+ case AuWbrCreate_PMFSRR: -+ case AuWbrCreate_PMFSRRV: -+ sbinfo->si_wbr_mfs.mfsrr_watermark = create->mfsrr_watermark; -+ /*FALLTHROUGH*/ -+ case AuWbrCreate_MFS: -+ case AuWbrCreate_MFSV: -+ case AuWbrCreate_PMFS: -+ case AuWbrCreate_PMFSV: -+ sbinfo->si_wbr_mfs.mfs_expire -+ = msecs_to_jiffies(create->mfs_second * MSEC_PER_SEC); -+ break; -+ } -+ -+ if (sbinfo->si_wbr_create_ops->init) -+ sbinfo->si_wbr_create_ops->init(sb); /* ignore */ -+ -+ return err; -+} -+ -+/* -+ * returns, -+ * plus: processed without an error -+ * zero: unprocessed -+ */ -+static int au_opt_simple(struct super_block *sb, struct au_opt *opt, -+ struct au_opts *opts) -+{ -+ int err; -+ struct au_sbinfo *sbinfo; -+ -+ SiMustWriteLock(sb); -+ -+ err = 1; /* handled */ -+ sbinfo = au_sbi(sb); -+ switch (opt->type) { -+ case Opt_udba: -+ sbinfo->si_mntflags &= ~AuOptMask_UDBA; -+ sbinfo->si_mntflags |= opt->udba; -+ opts->given_udba |= opt->udba; -+ break; -+ -+ case Opt_plink: -+ au_opt_set(sbinfo->si_mntflags, PLINK); -+ break; -+ case Opt_noplink: -+ if (au_opt_test(sbinfo->si_mntflags, PLINK)) -+ au_plink_put(sb, /*verbose*/1); -+ au_opt_clr(sbinfo->si_mntflags, PLINK); -+ break; -+ case Opt_list_plink: -+ if (au_opt_test(sbinfo->si_mntflags, PLINK)) -+ au_plink_list(sb); -+ break; -+ -+ case Opt_dio: -+ au_opt_set(sbinfo->si_mntflags, DIO); -+ au_fset_opts(opts->flags, REFRESH_DYAOP); -+ break; -+ case Opt_nodio: -+ au_opt_clr(sbinfo->si_mntflags, DIO); -+ au_fset_opts(opts->flags, REFRESH_DYAOP); -+ break; -+ -+ case Opt_fhsm_sec: -+ au_fhsm_set(sbinfo, opt->fhsm_second); -+ break; -+ -+ case Opt_diropq_a: -+ au_opt_set(sbinfo->si_mntflags, ALWAYS_DIROPQ); -+ break; -+ case Opt_diropq_w: -+ au_opt_clr(sbinfo->si_mntflags, ALWAYS_DIROPQ); -+ break; -+ -+ case Opt_warn_perm: -+ au_opt_set(sbinfo->si_mntflags, WARN_PERM); -+ break; -+ case Opt_nowarn_perm: -+ au_opt_clr(sbinfo->si_mntflags, WARN_PERM); -+ break; -+ -+ case Opt_verbose: -+ au_opt_set(sbinfo->si_mntflags, VERBOSE); -+ break; -+ case Opt_noverbose: -+ au_opt_clr(sbinfo->si_mntflags, VERBOSE); -+ break; -+ -+ case Opt_sum: -+ au_opt_set(sbinfo->si_mntflags, SUM); -+ break; -+ case Opt_wsum: -+ au_opt_clr(sbinfo->si_mntflags, SUM); -+ au_opt_set(sbinfo->si_mntflags, SUM_W); -+ break; -+ case Opt_nosum: -+ au_opt_clr(sbinfo->si_mntflags, SUM); -+ au_opt_clr(sbinfo->si_mntflags, SUM_W); -+ break; -+ -+ case Opt_wbr_create: -+ err = au_opt_wbr_create(sb, &opt->wbr_create); -+ break; -+ case Opt_wbr_copyup: -+ sbinfo->si_wbr_copyup = opt->wbr_copyup; -+ sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + opt->wbr_copyup; -+ break; -+ -+ case Opt_dirwh: -+ sbinfo->si_dirwh = opt->dirwh; -+ break; -+ -+ case Opt_rdcache: -+ sbinfo->si_rdcache -+ = msecs_to_jiffies(opt->rdcache * MSEC_PER_SEC); -+ break; -+ case Opt_rdblk: -+ sbinfo->si_rdblk = opt->rdblk; -+ break; -+ case Opt_rdblk_def: -+ sbinfo->si_rdblk = AUFS_RDBLK_DEF; -+ break; -+ case Opt_rdhash: -+ sbinfo->si_rdhash = opt->rdhash; -+ break; -+ case Opt_rdhash_def: -+ sbinfo->si_rdhash = AUFS_RDHASH_DEF; -+ break; -+ -+ case Opt_shwh: -+ au_opt_set(sbinfo->si_mntflags, SHWH); -+ break; -+ case Opt_noshwh: -+ au_opt_clr(sbinfo->si_mntflags, SHWH); -+ break; -+ -+ case Opt_dirperm1: -+ au_opt_set(sbinfo->si_mntflags, DIRPERM1); -+ break; -+ case Opt_nodirperm1: -+ au_opt_clr(sbinfo->si_mntflags, DIRPERM1); -+ break; -+ -+ case Opt_trunc_xino: -+ au_opt_set(sbinfo->si_mntflags, TRUNC_XINO); -+ break; -+ case Opt_notrunc_xino: -+ au_opt_clr(sbinfo->si_mntflags, TRUNC_XINO); -+ break; -+ -+ case Opt_trunc_xino_path: -+ case Opt_itrunc_xino: -+ err = au_xino_trunc(sb, opt->xino_itrunc.bindex, -+ /*idx_begin*/0); -+ if (!err) -+ err = 1; -+ break; -+ -+ case Opt_trunc_xib: -+ au_fset_opts(opts->flags, TRUNC_XIB); -+ break; -+ case Opt_notrunc_xib: -+ au_fclr_opts(opts->flags, TRUNC_XIB); -+ break; -+ -+ case Opt_dirren: -+ err = 1; -+ if (!au_opt_test(sbinfo->si_mntflags, DIRREN)) { -+ err = au_dr_opt_set(sb); -+ if (!err) -+ err = 1; -+ } -+ if (err == 1) -+ au_opt_set(sbinfo->si_mntflags, DIRREN); -+ break; -+ case Opt_nodirren: -+ err = 1; -+ if (au_opt_test(sbinfo->si_mntflags, DIRREN)) { -+ err = au_dr_opt_clr(sb, au_ftest_opts(opts->flags, -+ DR_FLUSHED)); -+ if (!err) -+ err = 1; -+ } -+ if (err == 1) -+ au_opt_clr(sbinfo->si_mntflags, DIRREN); -+ break; -+ -+ case Opt_acl: -+ sb->s_flags |= SB_POSIXACL; -+ break; -+ case Opt_noacl: -+ sb->s_flags &= ~SB_POSIXACL; -+ break; -+ -+ default: -+ err = 0; -+ break; -+ } -+ -+ return err; -+} -+ -+/* -+ * returns tri-state. -+ * plus: processed without an error -+ * zero: unprocessed -+ * minus: error -+ */ -+static int au_opt_br(struct super_block *sb, struct au_opt *opt, -+ struct au_opts *opts) -+{ -+ int err, do_refresh; -+ -+ err = 0; -+ switch (opt->type) { -+ case Opt_append: -+ opt->add.bindex = au_sbbot(sb) + 1; -+ if (opt->add.bindex < 0) -+ opt->add.bindex = 0; -+ goto add; -+ /* Always goto add, not fallthrough */ -+ case Opt_prepend: -+ opt->add.bindex = 0; -+ /* fallthrough */ -+ add: /* indented label */ -+ case Opt_add: -+ err = au_br_add(sb, &opt->add, -+ au_ftest_opts(opts->flags, REMOUNT)); -+ if (!err) { -+ err = 1; -+ au_fset_opts(opts->flags, REFRESH); -+ } -+ break; -+ -+ case Opt_del: -+ case Opt_idel: -+ err = au_br_del(sb, &opt->del, -+ au_ftest_opts(opts->flags, REMOUNT)); -+ if (!err) { -+ err = 1; -+ au_fset_opts(opts->flags, TRUNC_XIB); -+ au_fset_opts(opts->flags, REFRESH); -+ } -+ break; -+ -+ case Opt_mod: -+ case Opt_imod: -+ err = au_br_mod(sb, &opt->mod, -+ au_ftest_opts(opts->flags, REMOUNT), -+ &do_refresh); -+ if (!err) { -+ err = 1; -+ if (do_refresh) -+ au_fset_opts(opts->flags, REFRESH); -+ } -+ break; -+ } -+ return err; -+} -+ -+static int au_opt_xino(struct super_block *sb, struct au_opt *opt, -+ struct au_opt_xino **opt_xino, -+ struct au_opts *opts) -+{ -+ int err; -+ -+ err = 0; -+ switch (opt->type) { -+ case Opt_xino: -+ err = au_xino_set(sb, &opt->xino, -+ !!au_ftest_opts(opts->flags, REMOUNT)); -+ if (unlikely(err)) -+ break; -+ -+ *opt_xino = &opt->xino; -+ break; -+ -+ case Opt_noxino: -+ au_xino_clr(sb); -+ *opt_xino = (void *)-1; -+ break; -+ } -+ -+ return err; -+} -+ -+int au_opts_verify(struct super_block *sb, unsigned long sb_flags, -+ unsigned int pending) -+{ -+ int err, fhsm; -+ aufs_bindex_t bindex, bbot; -+ unsigned char do_plink, skip, do_free, can_no_dreval; -+ struct au_branch *br; -+ struct au_wbr *wbr; -+ struct dentry *root, *dentry; -+ struct inode *dir, *h_dir; -+ struct au_sbinfo *sbinfo; -+ struct au_hinode *hdir; -+ -+ SiMustAnyLock(sb); -+ -+ sbinfo = au_sbi(sb); -+ AuDebugOn(!(sbinfo->si_mntflags & AuOptMask_UDBA)); -+ -+ if (!(sb_flags & SB_RDONLY)) { -+ if (unlikely(!au_br_writable(au_sbr_perm(sb, 0)))) -+ pr_warn("first branch should be rw\n"); -+ if (unlikely(au_opt_test(sbinfo->si_mntflags, SHWH))) -+ pr_warn_once("shwh should be used with ro\n"); -+ } -+ -+ if (au_opt_test((sbinfo->si_mntflags | pending), UDBA_HNOTIFY) -+ && !au_opt_test(sbinfo->si_mntflags, XINO)) -+ pr_warn_once("udba=*notify requires xino\n"); -+ -+ if (au_opt_test(sbinfo->si_mntflags, DIRPERM1)) -+ pr_warn_once("dirperm1 breaks the protection" -+ " by the permission bits on the lower branch\n"); -+ -+ err = 0; -+ fhsm = 0; -+ root = sb->s_root; -+ dir = d_inode(root); -+ do_plink = !!au_opt_test(sbinfo->si_mntflags, PLINK); -+ can_no_dreval = !!au_opt_test((sbinfo->si_mntflags | pending), -+ UDBA_NONE); -+ bbot = au_sbbot(sb); -+ for (bindex = 0; !err && bindex <= bbot; bindex++) { -+ skip = 0; -+ h_dir = au_h_iptr(dir, bindex); -+ br = au_sbr(sb, bindex); -+ -+ if ((br->br_perm & AuBrAttr_ICEX) -+ && !h_dir->i_op->listxattr) -+ br->br_perm &= ~AuBrAttr_ICEX; -+#if 0 /* untested */ -+ if ((br->br_perm & AuBrAttr_ICEX_SEC) -+ && (au_br_sb(br)->s_flags & SB_NOSEC)) -+ br->br_perm &= ~AuBrAttr_ICEX_SEC; -+#endif -+ -+ do_free = 0; -+ wbr = br->br_wbr; -+ if (wbr) -+ wbr_wh_read_lock(wbr); -+ -+ if (!au_br_writable(br->br_perm)) { -+ do_free = !!wbr; -+ skip = (!wbr -+ || (!wbr->wbr_whbase -+ && !wbr->wbr_plink -+ && !wbr->wbr_orph)); -+ } else if (!au_br_wh_linkable(br->br_perm)) { -+ /* skip = (!br->br_whbase && !br->br_orph); */ -+ skip = (!wbr || !wbr->wbr_whbase); -+ if (skip && wbr) { -+ if (do_plink) -+ skip = !!wbr->wbr_plink; -+ else -+ skip = !wbr->wbr_plink; -+ } -+ } else { -+ /* skip = (br->br_whbase && br->br_ohph); */ -+ skip = (wbr && wbr->wbr_whbase); -+ if (skip) { -+ if (do_plink) -+ skip = !!wbr->wbr_plink; -+ else -+ skip = !wbr->wbr_plink; -+ } -+ } -+ if (wbr) -+ wbr_wh_read_unlock(wbr); -+ -+ if (can_no_dreval) { -+ dentry = br->br_path.dentry; -+ spin_lock(&dentry->d_lock); -+ if (dentry->d_flags & -+ (DCACHE_OP_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE)) -+ can_no_dreval = 0; -+ spin_unlock(&dentry->d_lock); -+ } -+ -+ if (au_br_fhsm(br->br_perm)) { -+ fhsm++; -+ AuDebugOn(!br->br_fhsm); -+ } -+ -+ if (skip) -+ continue; -+ -+ hdir = au_hi(dir, bindex); -+ au_hn_inode_lock_nested(hdir, AuLsc_I_PARENT); -+ if (wbr) -+ wbr_wh_write_lock(wbr); -+ err = au_wh_init(br, sb); -+ if (wbr) -+ wbr_wh_write_unlock(wbr); -+ au_hn_inode_unlock(hdir); -+ -+ if (!err && do_free) { -+ au_kfree_rcu(wbr); -+ br->br_wbr = NULL; -+ } -+ } -+ -+ if (can_no_dreval) -+ au_fset_si(sbinfo, NO_DREVAL); -+ else -+ au_fclr_si(sbinfo, NO_DREVAL); -+ -+ if (fhsm >= 2) { -+ au_fset_si(sbinfo, FHSM); -+ for (bindex = bbot; bindex >= 0; bindex--) { -+ br = au_sbr(sb, bindex); -+ if (au_br_fhsm(br->br_perm)) { -+ au_fhsm_set_bottom(sb, bindex); -+ break; -+ } -+ } -+ } else { -+ au_fclr_si(sbinfo, FHSM); -+ au_fhsm_set_bottom(sb, -1); -+ } -+ -+ return err; -+} -+ -+int au_opts_mount(struct super_block *sb, struct au_opts *opts) -+{ -+ int err; -+ unsigned int tmp; -+ aufs_bindex_t bindex, bbot; -+ struct au_opt *opt; -+ struct au_opt_xino *opt_xino, xino; -+ struct au_sbinfo *sbinfo; -+ struct au_branch *br; -+ struct inode *dir; -+ -+ SiMustWriteLock(sb); -+ -+ err = 0; -+ opt_xino = NULL; -+ opt = opts->opt; -+ while (err >= 0 && opt->type != Opt_tail) -+ err = au_opt_simple(sb, opt++, opts); -+ if (err > 0) -+ err = 0; -+ else if (unlikely(err < 0)) -+ goto out; -+ -+ /* disable xino and udba temporary */ -+ sbinfo = au_sbi(sb); -+ tmp = sbinfo->si_mntflags; -+ au_opt_clr(sbinfo->si_mntflags, XINO); -+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_REVAL); -+ -+ opt = opts->opt; -+ while (err >= 0 && opt->type != Opt_tail) -+ err = au_opt_br(sb, opt++, opts); -+ if (err > 0) -+ err = 0; -+ else if (unlikely(err < 0)) -+ goto out; -+ -+ bbot = au_sbbot(sb); -+ if (unlikely(bbot < 0)) { -+ err = -EINVAL; -+ pr_err("no branches\n"); -+ goto out; -+ } -+ -+ if (au_opt_test(tmp, XINO)) -+ au_opt_set(sbinfo->si_mntflags, XINO); -+ opt = opts->opt; -+ while (!err && opt->type != Opt_tail) -+ err = au_opt_xino(sb, opt++, &opt_xino, opts); -+ if (unlikely(err)) -+ goto out; -+ -+ err = au_opts_verify(sb, sb->s_flags, tmp); -+ if (unlikely(err)) -+ goto out; -+ -+ /* restore xino */ -+ if (au_opt_test(tmp, XINO) && !opt_xino) { -+ xino.file = au_xino_def(sb); -+ err = PTR_ERR(xino.file); -+ if (IS_ERR(xino.file)) -+ goto out; -+ -+ err = au_xino_set(sb, &xino, /*remount*/0); -+ fput(xino.file); -+ if (unlikely(err)) -+ goto out; -+ } -+ -+ /* restore udba */ -+ tmp &= AuOptMask_UDBA; -+ sbinfo->si_mntflags &= ~AuOptMask_UDBA; -+ sbinfo->si_mntflags |= tmp; -+ bbot = au_sbbot(sb); -+ for (bindex = 0; bindex <= bbot; bindex++) { -+ br = au_sbr(sb, bindex); -+ err = au_hnotify_reset_br(tmp, br, br->br_perm); -+ if (unlikely(err)) -+ AuIOErr("hnotify failed on br %d, %d, ignored\n", -+ bindex, err); -+ /* go on even if err */ -+ } -+ if (au_opt_test(tmp, UDBA_HNOTIFY)) { -+ dir = d_inode(sb->s_root); -+ au_hn_reset(dir, au_hi_flags(dir, /*isdir*/1) & ~AuHi_XINO); -+ } -+ -+out: -+ return err; -+} -+ -+int au_opts_remount(struct super_block *sb, struct au_opts *opts) -+{ -+ int err, rerr; -+ unsigned char no_dreval; -+ struct inode *dir; -+ struct au_opt_xino *opt_xino; -+ struct au_opt *opt; -+ struct au_sbinfo *sbinfo; -+ -+ SiMustWriteLock(sb); -+ -+ err = au_dr_opt_flush(sb); -+ if (unlikely(err)) -+ goto out; -+ au_fset_opts(opts->flags, DR_FLUSHED); -+ -+ dir = d_inode(sb->s_root); -+ sbinfo = au_sbi(sb); -+ opt_xino = NULL; -+ opt = opts->opt; -+ while (err >= 0 && opt->type != Opt_tail) { -+ err = au_opt_simple(sb, opt, opts); -+ if (!err) -+ err = au_opt_br(sb, opt, opts); -+ if (!err) -+ err = au_opt_xino(sb, opt, &opt_xino, opts); -+ opt++; -+ } -+ if (err > 0) -+ err = 0; -+ AuTraceErr(err); -+ /* go on even err */ -+ -+ no_dreval = !!au_ftest_si(sbinfo, NO_DREVAL); -+ rerr = au_opts_verify(sb, opts->sb_flags, /*pending*/0); -+ if (unlikely(rerr && !err)) -+ err = rerr; -+ -+ if (no_dreval != !!au_ftest_si(sbinfo, NO_DREVAL)) -+ au_fset_opts(opts->flags, REFRESH_IDOP); -+ -+ if (au_ftest_opts(opts->flags, TRUNC_XIB)) { -+ rerr = au_xib_trunc(sb); -+ if (unlikely(rerr && !err)) -+ err = rerr; -+ } -+ -+ /* will be handled by the caller */ -+ if (!au_ftest_opts(opts->flags, REFRESH) -+ && (opts->given_udba -+ || au_opt_test(sbinfo->si_mntflags, XINO) -+ || au_ftest_opts(opts->flags, REFRESH_IDOP) -+ )) -+ au_fset_opts(opts->flags, REFRESH); -+ -+ AuDbg("status 0x%x\n", opts->flags); -+ -+out: -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+unsigned int au_opt_udba(struct super_block *sb) -+{ -+ return au_mntflags(sb) & AuOptMask_UDBA; -+} -diff --git a/fs/aufs/opts.h b/fs/aufs/opts.h -new file mode 100644 -index 000000000000..5e00aeac6d21 ---- /dev/null -+++ b/fs/aufs/opts.h -@@ -0,0 +1,212 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * mount options/flags -+ */ -+ -+#ifndef __AUFS_OPTS_H__ -+#define __AUFS_OPTS_H__ -+ -+#ifdef __KERNEL__ -+ -+#include -+ -+struct file; -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* mount flags */ -+#define AuOpt_XINO 1 /* external inode number bitmap -+ and translation table */ -+#define AuOpt_TRUNC_XINO (1 << 1) /* truncate xino files */ -+#define AuOpt_UDBA_NONE (1 << 2) /* users direct branch access */ -+#define AuOpt_UDBA_REVAL (1 << 3) -+#define AuOpt_UDBA_HNOTIFY (1 << 4) -+#define AuOpt_SHWH (1 << 5) /* show whiteout */ -+#define AuOpt_PLINK (1 << 6) /* pseudo-link */ -+#define AuOpt_DIRPERM1 (1 << 7) /* ignore the lower dir's perm -+ bits */ -+#define AuOpt_ALWAYS_DIROPQ (1 << 9) /* policy to creating diropq */ -+#define AuOpt_SUM (1 << 10) /* summation for statfs(2) */ -+#define AuOpt_SUM_W (1 << 11) /* unimplemented */ -+#define AuOpt_WARN_PERM (1 << 12) /* warn when add-branch */ -+#define AuOpt_VERBOSE (1 << 13) /* print the cause of error */ -+#define AuOpt_DIO (1 << 14) /* direct io */ -+#define AuOpt_DIRREN (1 << 15) /* directory rename */ -+ -+#ifndef CONFIG_AUFS_HNOTIFY -+#undef AuOpt_UDBA_HNOTIFY -+#define AuOpt_UDBA_HNOTIFY 0 -+#endif -+#ifndef CONFIG_AUFS_DIRREN -+#undef AuOpt_DIRREN -+#define AuOpt_DIRREN 0 -+#endif -+#ifndef CONFIG_AUFS_SHWH -+#undef AuOpt_SHWH -+#define AuOpt_SHWH 0 -+#endif -+ -+#define AuOpt_Def (AuOpt_XINO \ -+ | AuOpt_UDBA_REVAL \ -+ | AuOpt_PLINK \ -+ /* | AuOpt_DIRPERM1 */ \ -+ | AuOpt_WARN_PERM) -+#define AuOptMask_UDBA (AuOpt_UDBA_NONE \ -+ | AuOpt_UDBA_REVAL \ -+ | AuOpt_UDBA_HNOTIFY) -+ -+#define au_opt_test(flags, name) (flags & AuOpt_##name) -+#define au_opt_set(flags, name) do { \ -+ BUILD_BUG_ON(AuOpt_##name & AuOptMask_UDBA); \ -+ ((flags) |= AuOpt_##name); \ -+} while (0) -+#define au_opt_set_udba(flags, name) do { \ -+ (flags) &= ~AuOptMask_UDBA; \ -+ ((flags) |= AuOpt_##name); \ -+} while (0) -+#define au_opt_clr(flags, name) do { \ -+ ((flags) &= ~AuOpt_##name); \ -+} while (0) -+ -+static inline unsigned int au_opts_plink(unsigned int mntflags) -+{ -+#ifdef CONFIG_PROC_FS -+ return mntflags; -+#else -+ return mntflags & ~AuOpt_PLINK; -+#endif -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* policies to select one among multiple writable branches */ -+enum { -+ AuWbrCreate_TDP, /* top down parent */ -+ AuWbrCreate_RR, /* round robin */ -+ AuWbrCreate_MFS, /* most free space */ -+ AuWbrCreate_MFSV, /* mfs with seconds */ -+ AuWbrCreate_MFSRR, /* mfs then rr */ -+ AuWbrCreate_MFSRRV, /* mfs then rr with seconds */ -+ AuWbrCreate_TDMFS, /* top down regardless parent and mfs */ -+ AuWbrCreate_TDMFSV, /* top down regardless parent and mfs */ -+ AuWbrCreate_PMFS, /* parent and mfs */ -+ AuWbrCreate_PMFSV, /* parent and mfs with seconds */ -+ AuWbrCreate_PMFSRR, /* parent, mfs and round-robin */ -+ AuWbrCreate_PMFSRRV, /* plus seconds */ -+ -+ AuWbrCreate_Def = AuWbrCreate_TDP -+}; -+ -+enum { -+ AuWbrCopyup_TDP, /* top down parent */ -+ AuWbrCopyup_BUP, /* bottom up parent */ -+ AuWbrCopyup_BU, /* bottom up */ -+ -+ AuWbrCopyup_Def = AuWbrCopyup_TDP -+}; -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct au_opt_add { -+ aufs_bindex_t bindex; -+ char *pathname; -+ int perm; -+ struct path path; -+}; -+ -+struct au_opt_del { -+ char *pathname; -+ struct path h_path; -+}; -+ -+struct au_opt_mod { -+ char *path; -+ int perm; -+ struct dentry *h_root; -+}; -+ -+struct au_opt_xino { -+ char *path; -+ struct file *file; -+}; -+ -+struct au_opt_xino_itrunc { -+ aufs_bindex_t bindex; -+}; -+ -+struct au_opt_wbr_create { -+ int wbr_create; -+ int mfs_second; -+ unsigned long long mfsrr_watermark; -+}; -+ -+struct au_opt { -+ int type; -+ union { -+ struct au_opt_xino xino; -+ struct au_opt_xino_itrunc xino_itrunc; -+ struct au_opt_add add; -+ struct au_opt_del del; -+ struct au_opt_mod mod; -+ int dirwh; -+ int rdcache; -+ unsigned int rdblk; -+ unsigned int rdhash; -+ int udba; -+ struct au_opt_wbr_create wbr_create; -+ int wbr_copyup; -+ unsigned int fhsm_second; -+ }; -+}; -+ -+/* opts flags */ -+#define AuOpts_REMOUNT 1 -+#define AuOpts_REFRESH (1 << 1) -+#define AuOpts_TRUNC_XIB (1 << 2) -+#define AuOpts_REFRESH_DYAOP (1 << 3) -+#define AuOpts_REFRESH_IDOP (1 << 4) -+#define AuOpts_DR_FLUSHED (1 << 5) -+#define au_ftest_opts(flags, name) ((flags) & AuOpts_##name) -+#define au_fset_opts(flags, name) \ -+ do { (flags) |= AuOpts_##name; } while (0) -+#define au_fclr_opts(flags, name) \ -+ do { (flags) &= ~AuOpts_##name; } while (0) -+ -+#ifndef CONFIG_AUFS_DIRREN -+#undef AuOpts_DR_FLUSHED -+#define AuOpts_DR_FLUSHED 0 -+#endif -+ -+struct au_opts { -+ struct au_opt *opt; -+ int max_opt; -+ -+ unsigned int given_udba; -+ unsigned int flags; -+ unsigned long sb_flags; -+}; -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* opts.c */ -+void au_optstr_br_perm(au_br_perm_str_t *str, int perm); -+const char *au_optstr_udba(int udba); -+const char *au_optstr_wbr_copyup(int wbr_copyup); -+const char *au_optstr_wbr_create(int wbr_create); -+ -+void au_opts_free(struct au_opts *opts); -+struct super_block; -+int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts); -+int au_opts_verify(struct super_block *sb, unsigned long sb_flags, -+ unsigned int pending); -+int au_opts_mount(struct super_block *sb, struct au_opts *opts); -+int au_opts_remount(struct super_block *sb, struct au_opts *opts); -+ -+unsigned int au_opt_udba(struct super_block *sb); -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_OPTS_H__ */ -diff --git a/fs/aufs/plink.c b/fs/aufs/plink.c -new file mode 100644 -index 000000000000..1c67183bebfb ---- /dev/null -+++ b/fs/aufs/plink.c -@@ -0,0 +1,503 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * pseudo-link -+ */ -+ -+#include "aufs.h" -+ -+/* -+ * the pseudo-link maintenance mode. -+ * during a user process maintains the pseudo-links, -+ * prohibit adding a new plink and branch manipulation. -+ * -+ * Flags -+ * NOPLM: -+ * For entry functions which will handle plink, and i_mutex is already held -+ * in VFS. -+ * They cannot wait and should return an error at once. -+ * Callers has to check the error. -+ * NOPLMW: -+ * For entry functions which will handle plink, but i_mutex is not held -+ * in VFS. -+ * They can wait the plink maintenance mode to finish. -+ * -+ * They behave like F_SETLK and F_SETLKW. -+ * If the caller never handle plink, then both flags are unnecessary. -+ */ -+ -+int au_plink_maint(struct super_block *sb, int flags) -+{ -+ int err; -+ pid_t pid, ppid; -+ struct task_struct *parent, *prev; -+ struct au_sbinfo *sbi; -+ -+ SiMustAnyLock(sb); -+ -+ err = 0; -+ if (!au_opt_test(au_mntflags(sb), PLINK)) -+ goto out; -+ -+ sbi = au_sbi(sb); -+ pid = sbi->si_plink_maint_pid; -+ if (!pid || pid == current->pid) -+ goto out; -+ -+ /* todo: it highly depends upon /sbin/mount.aufs */ -+ prev = NULL; -+ parent = current; -+ ppid = 0; -+ rcu_read_lock(); -+ while (1) { -+ parent = rcu_dereference(parent->real_parent); -+ if (parent == prev) -+ break; -+ ppid = task_pid_vnr(parent); -+ if (pid == ppid) { -+ rcu_read_unlock(); -+ goto out; -+ } -+ prev = parent; -+ } -+ rcu_read_unlock(); -+ -+ if (au_ftest_lock(flags, NOPLMW)) { -+ /* if there is no i_mutex lock in VFS, we don't need to wait */ -+ /* AuDebugOn(!lockdep_depth(current)); */ -+ while (sbi->si_plink_maint_pid) { -+ si_read_unlock(sb); -+ /* gave up wake_up_bit() */ -+ wait_event(sbi->si_plink_wq, !sbi->si_plink_maint_pid); -+ -+ if (au_ftest_lock(flags, FLUSH)) -+ au_nwt_flush(&sbi->si_nowait); -+ si_noflush_read_lock(sb); -+ } -+ } else if (au_ftest_lock(flags, NOPLM)) { -+ AuDbg("ppid %d, pid %d\n", ppid, pid); -+ err = -EAGAIN; -+ } -+ -+out: -+ return err; -+} -+ -+void au_plink_maint_leave(struct au_sbinfo *sbinfo) -+{ -+ spin_lock(&sbinfo->si_plink_maint_lock); -+ sbinfo->si_plink_maint_pid = 0; -+ spin_unlock(&sbinfo->si_plink_maint_lock); -+ wake_up_all(&sbinfo->si_plink_wq); -+} -+ -+int au_plink_maint_enter(struct super_block *sb) -+{ -+ int err; -+ struct au_sbinfo *sbinfo; -+ -+ err = 0; -+ sbinfo = au_sbi(sb); -+ /* make sure i am the only one in this fs */ -+ si_write_lock(sb, AuLock_FLUSH); -+ if (au_opt_test(au_mntflags(sb), PLINK)) { -+ spin_lock(&sbinfo->si_plink_maint_lock); -+ if (!sbinfo->si_plink_maint_pid) -+ sbinfo->si_plink_maint_pid = current->pid; -+ else -+ err = -EBUSY; -+ spin_unlock(&sbinfo->si_plink_maint_lock); -+ } -+ si_write_unlock(sb); -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+#ifdef CONFIG_AUFS_DEBUG -+void au_plink_list(struct super_block *sb) -+{ -+ int i; -+ struct au_sbinfo *sbinfo; -+ struct hlist_bl_head *hbl; -+ struct hlist_bl_node *pos; -+ struct au_icntnr *icntnr; -+ -+ SiMustAnyLock(sb); -+ -+ sbinfo = au_sbi(sb); -+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK)); -+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM)); -+ -+ for (i = 0; i < AuPlink_NHASH; i++) { -+ hbl = sbinfo->si_plink + i; -+ hlist_bl_lock(hbl); -+ hlist_bl_for_each_entry(icntnr, pos, hbl, plink) -+ AuDbg("%lu\n", icntnr->vfs_inode.i_ino); -+ hlist_bl_unlock(hbl); -+ } -+} -+#endif -+ -+/* is the inode pseudo-linked? */ -+int au_plink_test(struct inode *inode) -+{ -+ int found, i; -+ struct au_sbinfo *sbinfo; -+ struct hlist_bl_head *hbl; -+ struct hlist_bl_node *pos; -+ struct au_icntnr *icntnr; -+ -+ sbinfo = au_sbi(inode->i_sb); -+ AuRwMustAnyLock(&sbinfo->si_rwsem); -+ AuDebugOn(!au_opt_test(au_mntflags(inode->i_sb), PLINK)); -+ AuDebugOn(au_plink_maint(inode->i_sb, AuLock_NOPLM)); -+ -+ found = 0; -+ i = au_plink_hash(inode->i_ino); -+ hbl = sbinfo->si_plink + i; -+ hlist_bl_lock(hbl); -+ hlist_bl_for_each_entry(icntnr, pos, hbl, plink) -+ if (&icntnr->vfs_inode == inode) { -+ found = 1; -+ break; -+ } -+ hlist_bl_unlock(hbl); -+ return found; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * generate a name for plink. -+ * the file will be stored under AUFS_WH_PLINKDIR. -+ */ -+/* 20 is max digits length of ulong 64 */ -+#define PLINK_NAME_LEN ((20 + 1) * 2) -+ -+static int plink_name(char *name, int len, struct inode *inode, -+ aufs_bindex_t bindex) -+{ -+ int rlen; -+ struct inode *h_inode; -+ -+ h_inode = au_h_iptr(inode, bindex); -+ rlen = snprintf(name, len, "%lu.%lu", inode->i_ino, h_inode->i_ino); -+ return rlen; -+} -+ -+struct au_do_plink_lkup_args { -+ struct dentry **errp; -+ struct qstr *tgtname; -+ struct dentry *h_parent; -+ struct au_branch *br; -+}; -+ -+static struct dentry *au_do_plink_lkup(struct qstr *tgtname, -+ struct dentry *h_parent, -+ struct au_branch *br) -+{ -+ struct dentry *h_dentry; -+ struct inode *h_inode; -+ -+ h_inode = d_inode(h_parent); -+ inode_lock_shared_nested(h_inode, AuLsc_I_CHILD2); -+ h_dentry = vfsub_lkup_one(tgtname, h_parent); -+ inode_unlock_shared(h_inode); -+ return h_dentry; -+} -+ -+static void au_call_do_plink_lkup(void *args) -+{ -+ struct au_do_plink_lkup_args *a = args; -+ *a->errp = au_do_plink_lkup(a->tgtname, a->h_parent, a->br); -+} -+ -+/* lookup the plink-ed @inode under the branch at @bindex */ -+struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex) -+{ -+ struct dentry *h_dentry, *h_parent; -+ struct au_branch *br; -+ int wkq_err; -+ char a[PLINK_NAME_LEN]; -+ struct qstr tgtname = QSTR_INIT(a, 0); -+ -+ AuDebugOn(au_plink_maint(inode->i_sb, AuLock_NOPLM)); -+ -+ br = au_sbr(inode->i_sb, bindex); -+ h_parent = br->br_wbr->wbr_plink; -+ tgtname.len = plink_name(a, sizeof(a), inode, bindex); -+ -+ if (!uid_eq(current_fsuid(), GLOBAL_ROOT_UID)) { -+ struct au_do_plink_lkup_args args = { -+ .errp = &h_dentry, -+ .tgtname = &tgtname, -+ .h_parent = h_parent, -+ .br = br -+ }; -+ -+ wkq_err = au_wkq_wait(au_call_do_plink_lkup, &args); -+ if (unlikely(wkq_err)) -+ h_dentry = ERR_PTR(wkq_err); -+ } else -+ h_dentry = au_do_plink_lkup(&tgtname, h_parent, br); -+ -+ return h_dentry; -+} -+ -+/* create a pseudo-link */ -+static int do_whplink(struct qstr *tgt, struct dentry *h_parent, -+ struct dentry *h_dentry, struct au_branch *br) -+{ -+ int err; -+ struct path h_path = { -+ .mnt = au_br_mnt(br) -+ }; -+ struct inode *h_dir, *delegated; -+ -+ h_dir = d_inode(h_parent); -+ inode_lock_nested(h_dir, AuLsc_I_CHILD2); -+again: -+ h_path.dentry = vfsub_lkup_one(tgt, h_parent); -+ err = PTR_ERR(h_path.dentry); -+ if (IS_ERR(h_path.dentry)) -+ goto out; -+ -+ err = 0; -+ /* wh.plink dir is not monitored */ -+ /* todo: is it really safe? */ -+ if (d_is_positive(h_path.dentry) -+ && d_inode(h_path.dentry) != d_inode(h_dentry)) { -+ delegated = NULL; -+ err = vfsub_unlink(h_dir, &h_path, &delegated, /*force*/0); -+ if (unlikely(err == -EWOULDBLOCK)) { -+ pr_warn("cannot retry for NFSv4 delegation" -+ " for an internal unlink\n"); -+ iput(delegated); -+ } -+ dput(h_path.dentry); -+ h_path.dentry = NULL; -+ if (!err) -+ goto again; -+ } -+ if (!err && d_is_negative(h_path.dentry)) { -+ delegated = NULL; -+ err = vfsub_link(h_dentry, h_dir, &h_path, &delegated); -+ if (unlikely(err == -EWOULDBLOCK)) { -+ pr_warn("cannot retry for NFSv4 delegation" -+ " for an internal link\n"); -+ iput(delegated); -+ } -+ } -+ dput(h_path.dentry); -+ -+out: -+ inode_unlock(h_dir); -+ return err; -+} -+ -+struct do_whplink_args { -+ int *errp; -+ struct qstr *tgt; -+ struct dentry *h_parent; -+ struct dentry *h_dentry; -+ struct au_branch *br; -+}; -+ -+static void call_do_whplink(void *args) -+{ -+ struct do_whplink_args *a = args; -+ *a->errp = do_whplink(a->tgt, a->h_parent, a->h_dentry, a->br); -+} -+ -+static int whplink(struct dentry *h_dentry, struct inode *inode, -+ aufs_bindex_t bindex, struct au_branch *br) -+{ -+ int err, wkq_err; -+ struct au_wbr *wbr; -+ struct dentry *h_parent; -+ char a[PLINK_NAME_LEN]; -+ struct qstr tgtname = QSTR_INIT(a, 0); -+ -+ wbr = au_sbr(inode->i_sb, bindex)->br_wbr; -+ h_parent = wbr->wbr_plink; -+ tgtname.len = plink_name(a, sizeof(a), inode, bindex); -+ -+ /* always superio. */ -+ if (!uid_eq(current_fsuid(), GLOBAL_ROOT_UID)) { -+ struct do_whplink_args args = { -+ .errp = &err, -+ .tgt = &tgtname, -+ .h_parent = h_parent, -+ .h_dentry = h_dentry, -+ .br = br -+ }; -+ wkq_err = au_wkq_wait(call_do_whplink, &args); -+ if (unlikely(wkq_err)) -+ err = wkq_err; -+ } else -+ err = do_whplink(&tgtname, h_parent, h_dentry, br); -+ -+ return err; -+} -+ -+/* -+ * create a new pseudo-link for @h_dentry on @bindex. -+ * the linked inode is held in aufs @inode. -+ */ -+void au_plink_append(struct inode *inode, aufs_bindex_t bindex, -+ struct dentry *h_dentry) -+{ -+ struct super_block *sb; -+ struct au_sbinfo *sbinfo; -+ struct hlist_bl_head *hbl; -+ struct hlist_bl_node *pos; -+ struct au_icntnr *icntnr; -+ int found, err, cnt, i; -+ -+ sb = inode->i_sb; -+ sbinfo = au_sbi(sb); -+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK)); -+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM)); -+ -+ found = au_plink_test(inode); -+ if (found) -+ return; -+ -+ i = au_plink_hash(inode->i_ino); -+ hbl = sbinfo->si_plink + i; -+ au_igrab(inode); -+ -+ hlist_bl_lock(hbl); -+ hlist_bl_for_each_entry(icntnr, pos, hbl, plink) { -+ if (&icntnr->vfs_inode == inode) { -+ found = 1; -+ break; -+ } -+ } -+ if (!found) { -+ icntnr = container_of(inode, struct au_icntnr, vfs_inode); -+ hlist_bl_add_head(&icntnr->plink, hbl); -+ } -+ hlist_bl_unlock(hbl); -+ if (!found) { -+ cnt = au_hbl_count(hbl); -+#define msg "unexpectedly unbalanced or too many pseudo-links" -+ if (cnt > AUFS_PLINK_WARN) -+ AuWarn1(msg ", %d\n", cnt); -+#undef msg -+ err = whplink(h_dentry, inode, bindex, au_sbr(sb, bindex)); -+ if (unlikely(err)) { -+ pr_warn("err %d, damaged pseudo link.\n", err); -+ au_hbl_del(&icntnr->plink, hbl); -+ iput(&icntnr->vfs_inode); -+ } -+ } else -+ iput(&icntnr->vfs_inode); -+} -+ -+/* free all plinks */ -+void au_plink_put(struct super_block *sb, int verbose) -+{ -+ int i, warned; -+ struct au_sbinfo *sbinfo; -+ struct hlist_bl_head *hbl; -+ struct hlist_bl_node *pos, *tmp; -+ struct au_icntnr *icntnr; -+ -+ SiMustWriteLock(sb); -+ -+ sbinfo = au_sbi(sb); -+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK)); -+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM)); -+ -+ /* no spin_lock since sbinfo is write-locked */ -+ warned = 0; -+ for (i = 0; i < AuPlink_NHASH; i++) { -+ hbl = sbinfo->si_plink + i; -+ if (!warned && verbose && !hlist_bl_empty(hbl)) { -+ pr_warn("pseudo-link is not flushed"); -+ warned = 1; -+ } -+ hlist_bl_for_each_entry_safe(icntnr, pos, tmp, hbl, plink) -+ iput(&icntnr->vfs_inode); -+ INIT_HLIST_BL_HEAD(hbl); -+ } -+} -+ -+void au_plink_clean(struct super_block *sb, int verbose) -+{ -+ struct dentry *root; -+ -+ root = sb->s_root; -+ aufs_write_lock(root); -+ if (au_opt_test(au_mntflags(sb), PLINK)) -+ au_plink_put(sb, verbose); -+ aufs_write_unlock(root); -+} -+ -+static int au_plink_do_half_refresh(struct inode *inode, aufs_bindex_t br_id) -+{ -+ int do_put; -+ aufs_bindex_t btop, bbot, bindex; -+ -+ do_put = 0; -+ btop = au_ibtop(inode); -+ bbot = au_ibbot(inode); -+ if (btop >= 0) { -+ for (bindex = btop; bindex <= bbot; bindex++) { -+ if (!au_h_iptr(inode, bindex) -+ || au_ii_br_id(inode, bindex) != br_id) -+ continue; -+ au_set_h_iptr(inode, bindex, NULL, 0); -+ do_put = 1; -+ break; -+ } -+ if (do_put) -+ for (bindex = btop; bindex <= bbot; bindex++) -+ if (au_h_iptr(inode, bindex)) { -+ do_put = 0; -+ break; -+ } -+ } else -+ do_put = 1; -+ -+ return do_put; -+} -+ -+/* free the plinks on a branch specified by @br_id */ -+void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id) -+{ -+ struct au_sbinfo *sbinfo; -+ struct hlist_bl_head *hbl; -+ struct hlist_bl_node *pos, *tmp; -+ struct au_icntnr *icntnr; -+ struct inode *inode; -+ int i, do_put; -+ -+ SiMustWriteLock(sb); -+ -+ sbinfo = au_sbi(sb); -+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK)); -+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM)); -+ -+ /* no bit_lock since sbinfo is write-locked */ -+ for (i = 0; i < AuPlink_NHASH; i++) { -+ hbl = sbinfo->si_plink + i; -+ hlist_bl_for_each_entry_safe(icntnr, pos, tmp, hbl, plink) { -+ inode = au_igrab(&icntnr->vfs_inode); -+ ii_write_lock_child(inode); -+ do_put = au_plink_do_half_refresh(inode, br_id); -+ if (do_put) { -+ hlist_bl_del(&icntnr->plink); -+ iput(inode); -+ } -+ ii_write_unlock(inode); -+ iput(inode); -+ } -+ } -+} -diff --git a/fs/aufs/poll.c b/fs/aufs/poll.c -new file mode 100644 -index 000000000000..ff7697c334b4 ---- /dev/null -+++ b/fs/aufs/poll.c -@@ -0,0 +1,38 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * poll operation -+ * There is only one filesystem which implements ->poll operation, currently. -+ */ -+ -+#include "aufs.h" -+ -+__poll_t aufs_poll(struct file *file, struct poll_table_struct *pt) -+{ -+ __poll_t mask; -+ struct file *h_file; -+ struct super_block *sb; -+ -+ /* We should pretend an error happened. */ -+ mask = EPOLLERR /* | EPOLLIN | EPOLLOUT */; -+ sb = file->f_path.dentry->d_sb; -+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW); -+ -+ h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0); -+ if (IS_ERR(h_file)) { -+ AuDbg("h_file %ld\n", PTR_ERR(h_file)); -+ goto out; -+ } -+ -+ mask = vfs_poll(h_file, pt); -+ fput(h_file); /* instead of au_read_post() */ -+ -+out: -+ si_read_unlock(sb); -+ if (mask & EPOLLERR) -+ AuDbg("mask 0x%x\n", mask); -+ return mask; -+} -diff --git a/fs/aufs/posix_acl.c b/fs/aufs/posix_acl.c -new file mode 100644 -index 000000000000..946c2247e78d ---- /dev/null -+++ b/fs/aufs/posix_acl.c -@@ -0,0 +1,92 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2014-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * posix acl operations -+ */ -+ -+#include -+#include "aufs.h" -+ -+struct posix_acl *aufs_get_acl(struct inode *inode, int type) -+{ -+ struct posix_acl *acl; -+ int err; -+ aufs_bindex_t bindex; -+ struct inode *h_inode; -+ struct super_block *sb; -+ -+ acl = NULL; -+ sb = inode->i_sb; -+ si_read_lock(sb, AuLock_FLUSH); -+ ii_read_lock_child(inode); -+ if (!(sb->s_flags & SB_POSIXACL)) -+ goto out; -+ -+ bindex = au_ibtop(inode); -+ h_inode = au_h_iptr(inode, bindex); -+ if (unlikely(!h_inode -+ || ((h_inode->i_mode & S_IFMT) -+ != (inode->i_mode & S_IFMT)))) { -+ err = au_busy_or_stale(); -+ acl = ERR_PTR(err); -+ goto out; -+ } -+ -+ /* always topmost only */ -+ acl = get_acl(h_inode, type); -+ if (IS_ERR(acl)) -+ forget_cached_acl(inode, type); -+ else -+ set_cached_acl(inode, type, acl); -+ -+out: -+ ii_read_unlock(inode); -+ si_read_unlock(sb); -+ -+ AuTraceErrPtr(acl); -+ return acl; -+} -+ -+int aufs_set_acl(struct inode *inode, struct posix_acl *acl, int type) -+{ -+ int err; -+ ssize_t ssz; -+ struct dentry *dentry; -+ struct au_sxattr arg = { -+ .type = AU_ACL_SET, -+ .u.acl_set = { -+ .acl = acl, -+ .type = type -+ }, -+ }; -+ -+ IMustLock(inode); -+ -+ if (inode->i_ino == AUFS_ROOT_INO) -+ dentry = dget(inode->i_sb->s_root); -+ else { -+ dentry = d_find_alias(inode); -+ if (!dentry) -+ dentry = d_find_any_alias(inode); -+ if (!dentry) { -+ pr_warn("cannot handle this inode, " -+ "please report to aufs-users ML\n"); -+ err = -ENOENT; -+ goto out; -+ } -+ } -+ -+ ssz = au_sxattr(dentry, inode, &arg); -+ /* forget even it if succeeds since the branch might set differently */ -+ forget_cached_acl(inode, type); -+ dput(dentry); -+ err = ssz; -+ if (ssz >= 0) -+ err = 0; -+ -+out: -+ return err; -+} -diff --git a/fs/aufs/procfs.c b/fs/aufs/procfs.c -new file mode 100644 -index 000000000000..055e9bcc9af4 ---- /dev/null -+++ b/fs/aufs/procfs.c -@@ -0,0 +1,157 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2010-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * procfs interfaces -+ */ -+ -+#include -+#include "aufs.h" -+ -+static int au_procfs_plm_release(struct inode *inode, struct file *file) -+{ -+ struct au_sbinfo *sbinfo; -+ -+ sbinfo = file->private_data; -+ if (sbinfo) { -+ au_plink_maint_leave(sbinfo); -+ kobject_put(&sbinfo->si_kobj); -+ } -+ -+ return 0; -+} -+ -+static void au_procfs_plm_write_clean(struct file *file) -+{ -+ struct au_sbinfo *sbinfo; -+ -+ sbinfo = file->private_data; -+ if (sbinfo) -+ au_plink_clean(sbinfo->si_sb, /*verbose*/0); -+} -+ -+static int au_procfs_plm_write_si(struct file *file, unsigned long id) -+{ -+ int err; -+ struct super_block *sb; -+ struct au_sbinfo *sbinfo; -+ struct hlist_bl_node *pos; -+ -+ err = -EBUSY; -+ if (unlikely(file->private_data)) -+ goto out; -+ -+ sb = NULL; -+ /* don't use au_sbilist_lock() here */ -+ hlist_bl_lock(&au_sbilist); -+ hlist_bl_for_each_entry(sbinfo, pos, &au_sbilist, si_list) -+ if (id == sysaufs_si_id(sbinfo)) { -+ if (kobject_get_unless_zero(&sbinfo->si_kobj)) -+ sb = sbinfo->si_sb; -+ break; -+ } -+ hlist_bl_unlock(&au_sbilist); -+ -+ err = -EINVAL; -+ if (unlikely(!sb)) -+ goto out; -+ -+ err = au_plink_maint_enter(sb); -+ if (!err) -+ /* keep kobject_get() */ -+ file->private_data = sbinfo; -+ else -+ kobject_put(&sbinfo->si_kobj); -+out: -+ return err; -+} -+ -+/* -+ * Accept a valid "si=xxxx" only. -+ * Once it is accepted successfully, accept "clean" too. -+ */ -+static ssize_t au_procfs_plm_write(struct file *file, const char __user *ubuf, -+ size_t count, loff_t *ppos) -+{ -+ ssize_t err; -+ unsigned long id; -+ /* last newline is allowed */ -+ char buf[3 + sizeof(unsigned long) * 2 + 1]; -+ -+ err = -EACCES; -+ if (unlikely(!capable(CAP_SYS_ADMIN))) -+ goto out; -+ -+ err = -EINVAL; -+ if (unlikely(count > sizeof(buf))) -+ goto out; -+ -+ err = copy_from_user(buf, ubuf, count); -+ if (unlikely(err)) { -+ err = -EFAULT; -+ goto out; -+ } -+ buf[count] = 0; -+ -+ err = -EINVAL; -+ if (!strcmp("clean", buf)) { -+ au_procfs_plm_write_clean(file); -+ goto out_success; -+ } else if (unlikely(strncmp("si=", buf, 3))) -+ goto out; -+ -+ err = kstrtoul(buf + 3, 16, &id); -+ if (unlikely(err)) -+ goto out; -+ -+ err = au_procfs_plm_write_si(file, id); -+ if (unlikely(err)) -+ goto out; -+ -+out_success: -+ err = count; /* success */ -+out: -+ return err; -+} -+ -+static const struct proc_ops au_procfs_plm_op = { -+ .proc_write = au_procfs_plm_write, -+ .proc_release = au_procfs_plm_release -+}; -+ -+/* ---------------------------------------------------------------------- */ -+ -+static struct proc_dir_entry *au_procfs_dir; -+ -+void au_procfs_fin(void) -+{ -+ remove_proc_entry(AUFS_PLINK_MAINT_NAME, au_procfs_dir); -+ remove_proc_entry(AUFS_PLINK_MAINT_DIR, NULL); -+} -+ -+int __init au_procfs_init(void) -+{ -+ int err; -+ struct proc_dir_entry *entry; -+ -+ err = -ENOMEM; -+ au_procfs_dir = proc_mkdir(AUFS_PLINK_MAINT_DIR, NULL); -+ if (unlikely(!au_procfs_dir)) -+ goto out; -+ -+ entry = proc_create(AUFS_PLINK_MAINT_NAME, S_IFREG | 0200, -+ au_procfs_dir, &au_procfs_plm_op); -+ if (unlikely(!entry)) -+ goto out_dir; -+ -+ err = 0; -+ goto out; /* success */ -+ -+ -+out_dir: -+ remove_proc_entry(AUFS_PLINK_MAINT_DIR, NULL); -+out: -+ return err; -+} -diff --git a/fs/aufs/rdu.c b/fs/aufs/rdu.c -new file mode 100644 -index 000000000000..bef4607f057e ---- /dev/null -+++ b/fs/aufs/rdu.c -@@ -0,0 +1,371 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * readdir in userspace. -+ */ -+ -+#include -+#include -+#include -+#include "aufs.h" -+ -+/* bits for struct aufs_rdu.flags */ -+#define AuRdu_CALLED 1 -+#define AuRdu_CONT (1 << 1) -+#define AuRdu_FULL (1 << 2) -+#define au_ftest_rdu(flags, name) ((flags) & AuRdu_##name) -+#define au_fset_rdu(flags, name) \ -+ do { (flags) |= AuRdu_##name; } while (0) -+#define au_fclr_rdu(flags, name) \ -+ do { (flags) &= ~AuRdu_##name; } while (0) -+ -+struct au_rdu_arg { -+ struct dir_context ctx; -+ struct aufs_rdu *rdu; -+ union au_rdu_ent_ul ent; -+ unsigned long end; -+ -+ struct super_block *sb; -+ int err; -+}; -+ -+static int au_rdu_fill(struct dir_context *ctx, const char *name, int nlen, -+ loff_t offset, u64 h_ino, unsigned int d_type) -+{ -+ int err, len; -+ struct au_rdu_arg *arg = container_of(ctx, struct au_rdu_arg, ctx); -+ struct aufs_rdu *rdu = arg->rdu; -+ struct au_rdu_ent ent; -+ -+ err = 0; -+ arg->err = 0; -+ au_fset_rdu(rdu->cookie.flags, CALLED); -+ len = au_rdu_len(nlen); -+ if (arg->ent.ul + len < arg->end) { -+ ent.ino = h_ino; -+ ent.bindex = rdu->cookie.bindex; -+ ent.type = d_type; -+ ent.nlen = nlen; -+ if (unlikely(nlen > AUFS_MAX_NAMELEN)) -+ ent.type = DT_UNKNOWN; -+ -+ /* unnecessary to support mmap_sem since this is a dir */ -+ err = -EFAULT; -+ if (copy_to_user(arg->ent.e, &ent, sizeof(ent))) -+ goto out; -+ if (copy_to_user(arg->ent.e->name, name, nlen)) -+ goto out; -+ /* the terminating NULL */ -+ if (__put_user(0, arg->ent.e->name + nlen)) -+ goto out; -+ err = 0; -+ /* AuDbg("%p, %.*s\n", arg->ent.p, nlen, name); */ -+ arg->ent.ul += len; -+ rdu->rent++; -+ } else { -+ err = -EFAULT; -+ au_fset_rdu(rdu->cookie.flags, FULL); -+ rdu->full = 1; -+ rdu->tail = arg->ent; -+ } -+ -+out: -+ /* AuTraceErr(err); */ -+ return err; -+} -+ -+static int au_rdu_do(struct file *h_file, struct au_rdu_arg *arg) -+{ -+ int err; -+ loff_t offset; -+ struct au_rdu_cookie *cookie = &arg->rdu->cookie; -+ -+ /* we don't have to care (FMODE_32BITHASH | FMODE_64BITHASH) for ext4 */ -+ offset = vfsub_llseek(h_file, cookie->h_pos, SEEK_SET); -+ err = offset; -+ if (unlikely(offset != cookie->h_pos)) -+ goto out; -+ -+ err = 0; -+ do { -+ arg->err = 0; -+ au_fclr_rdu(cookie->flags, CALLED); -+ /* smp_mb(); */ -+ err = vfsub_iterate_dir(h_file, &arg->ctx); -+ if (err >= 0) -+ err = arg->err; -+ } while (!err -+ && au_ftest_rdu(cookie->flags, CALLED) -+ && !au_ftest_rdu(cookie->flags, FULL)); -+ cookie->h_pos = h_file->f_pos; -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+static int au_rdu(struct file *file, struct aufs_rdu *rdu) -+{ -+ int err; -+ aufs_bindex_t bbot; -+ struct au_rdu_arg arg = { -+ .ctx = { -+ .actor = au_rdu_fill -+ } -+ }; -+ struct dentry *dentry; -+ struct inode *inode; -+ struct file *h_file; -+ struct au_rdu_cookie *cookie = &rdu->cookie; -+ -+ /* VERIFY_WRITE */ -+ err = !access_ok(rdu->ent.e, rdu->sz); -+ if (unlikely(err)) { -+ err = -EFAULT; -+ AuTraceErr(err); -+ goto out; -+ } -+ rdu->rent = 0; -+ rdu->tail = rdu->ent; -+ rdu->full = 0; -+ arg.rdu = rdu; -+ arg.ent = rdu->ent; -+ arg.end = arg.ent.ul; -+ arg.end += rdu->sz; -+ -+ err = -ENOTDIR; -+ if (unlikely(!file->f_op->iterate && !file->f_op->iterate_shared)) -+ goto out; -+ -+ err = security_file_permission(file, MAY_READ); -+ AuTraceErr(err); -+ if (unlikely(err)) -+ goto out; -+ -+ dentry = file->f_path.dentry; -+ inode = d_inode(dentry); -+ inode_lock_shared(inode); -+ -+ arg.sb = inode->i_sb; -+ err = si_read_lock(arg.sb, AuLock_FLUSH | AuLock_NOPLM); -+ if (unlikely(err)) -+ goto out_mtx; -+ err = au_alive_dir(dentry); -+ if (unlikely(err)) -+ goto out_si; -+ /* todo: reval? */ -+ fi_read_lock(file); -+ -+ err = -EAGAIN; -+ if (unlikely(au_ftest_rdu(cookie->flags, CONT) -+ && cookie->generation != au_figen(file))) -+ goto out_unlock; -+ -+ err = 0; -+ if (!rdu->blk) { -+ rdu->blk = au_sbi(arg.sb)->si_rdblk; -+ if (!rdu->blk) -+ rdu->blk = au_dir_size(file, /*dentry*/NULL); -+ } -+ bbot = au_fbtop(file); -+ if (cookie->bindex < bbot) -+ cookie->bindex = bbot; -+ bbot = au_fbbot_dir(file); -+ /* AuDbg("b%d, b%d\n", cookie->bindex, bbot); */ -+ for (; !err && cookie->bindex <= bbot; -+ cookie->bindex++, cookie->h_pos = 0) { -+ h_file = au_hf_dir(file, cookie->bindex); -+ if (!h_file) -+ continue; -+ -+ au_fclr_rdu(cookie->flags, FULL); -+ err = au_rdu_do(h_file, &arg); -+ AuTraceErr(err); -+ if (unlikely(au_ftest_rdu(cookie->flags, FULL) || err)) -+ break; -+ } -+ AuDbg("rent %llu\n", rdu->rent); -+ -+ if (!err && !au_ftest_rdu(cookie->flags, CONT)) { -+ rdu->shwh = !!au_opt_test(au_sbi(arg.sb)->si_mntflags, SHWH); -+ au_fset_rdu(cookie->flags, CONT); -+ cookie->generation = au_figen(file); -+ } -+ -+ ii_read_lock_child(inode); -+ fsstack_copy_attr_atime(inode, au_h_iptr(inode, au_ibtop(inode))); -+ ii_read_unlock(inode); -+ -+out_unlock: -+ fi_read_unlock(file); -+out_si: -+ si_read_unlock(arg.sb); -+out_mtx: -+ inode_unlock_shared(inode); -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+static int au_rdu_ino(struct file *file, struct aufs_rdu *rdu) -+{ -+ int err; -+ ino_t ino; -+ unsigned long long nent; -+ union au_rdu_ent_ul *u; -+ struct au_rdu_ent ent; -+ struct super_block *sb; -+ -+ err = 0; -+ nent = rdu->nent; -+ u = &rdu->ent; -+ sb = file->f_path.dentry->d_sb; -+ si_read_lock(sb, AuLock_FLUSH); -+ while (nent-- > 0) { -+ /* unnecessary to support mmap_sem since this is a dir */ -+ err = copy_from_user(&ent, u->e, sizeof(ent)); -+ if (!err) -+ /* VERIFY_WRITE */ -+ err = !access_ok(&u->e->ino, sizeof(ino)); -+ if (unlikely(err)) { -+ err = -EFAULT; -+ AuTraceErr(err); -+ break; -+ } -+ -+ /* AuDbg("b%d, i%llu\n", ent.bindex, ent.ino); */ -+ if (!ent.wh) -+ err = au_ino(sb, ent.bindex, ent.ino, ent.type, &ino); -+ else -+ err = au_wh_ino(sb, ent.bindex, ent.ino, ent.type, -+ &ino); -+ if (unlikely(err)) { -+ AuTraceErr(err); -+ break; -+ } -+ -+ err = __put_user(ino, &u->e->ino); -+ if (unlikely(err)) { -+ err = -EFAULT; -+ AuTraceErr(err); -+ break; -+ } -+ u->ul += au_rdu_len(ent.nlen); -+ } -+ si_read_unlock(sb); -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int au_rdu_verify(struct aufs_rdu *rdu) -+{ -+ AuDbg("rdu{%llu, %p, %u | %u | %llu, %u, %u | " -+ "%llu, b%d, 0x%x, g%u}\n", -+ rdu->sz, rdu->ent.e, rdu->verify[AufsCtlRduV_SZ], -+ rdu->blk, -+ rdu->rent, rdu->shwh, rdu->full, -+ rdu->cookie.h_pos, rdu->cookie.bindex, rdu->cookie.flags, -+ rdu->cookie.generation); -+ -+ if (rdu->verify[AufsCtlRduV_SZ] == sizeof(*rdu)) -+ return 0; -+ -+ AuDbg("%u:%u\n", -+ rdu->verify[AufsCtlRduV_SZ], (unsigned int)sizeof(*rdu)); -+ return -EINVAL; -+} -+ -+long au_rdu_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -+{ -+ long err, e; -+ struct aufs_rdu rdu; -+ void __user *p = (void __user *)arg; -+ -+ err = copy_from_user(&rdu, p, sizeof(rdu)); -+ if (unlikely(err)) { -+ err = -EFAULT; -+ AuTraceErr(err); -+ goto out; -+ } -+ err = au_rdu_verify(&rdu); -+ if (unlikely(err)) -+ goto out; -+ -+ switch (cmd) { -+ case AUFS_CTL_RDU: -+ err = au_rdu(file, &rdu); -+ if (unlikely(err)) -+ break; -+ -+ e = copy_to_user(p, &rdu, sizeof(rdu)); -+ if (unlikely(e)) { -+ err = -EFAULT; -+ AuTraceErr(err); -+ } -+ break; -+ case AUFS_CTL_RDU_INO: -+ err = au_rdu_ino(file, &rdu); -+ break; -+ -+ default: -+ /* err = -ENOTTY; */ -+ err = -EINVAL; -+ } -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+#ifdef CONFIG_COMPAT -+long au_rdu_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -+{ -+ long err, e; -+ struct aufs_rdu rdu; -+ void __user *p = compat_ptr(arg); -+ -+ /* todo: get_user()? */ -+ err = copy_from_user(&rdu, p, sizeof(rdu)); -+ if (unlikely(err)) { -+ err = -EFAULT; -+ AuTraceErr(err); -+ goto out; -+ } -+ rdu.ent.e = compat_ptr(rdu.ent.ul); -+ err = au_rdu_verify(&rdu); -+ if (unlikely(err)) -+ goto out; -+ -+ switch (cmd) { -+ case AUFS_CTL_RDU: -+ err = au_rdu(file, &rdu); -+ if (unlikely(err)) -+ break; -+ -+ rdu.ent.ul = ptr_to_compat(rdu.ent.e); -+ rdu.tail.ul = ptr_to_compat(rdu.tail.e); -+ e = copy_to_user(p, &rdu, sizeof(rdu)); -+ if (unlikely(e)) { -+ err = -EFAULT; -+ AuTraceErr(err); -+ } -+ break; -+ case AUFS_CTL_RDU_INO: -+ err = au_rdu_ino(file, &rdu); -+ break; -+ -+ default: -+ /* err = -ENOTTY; */ -+ err = -EINVAL; -+ } -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+#endif -diff --git a/fs/aufs/rwsem.h b/fs/aufs/rwsem.h -new file mode 100644 -index 000000000000..ab5af8236699 ---- /dev/null -+++ b/fs/aufs/rwsem.h -@@ -0,0 +1,60 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * simple read-write semaphore wrappers -+ */ -+ -+#ifndef __AUFS_RWSEM_H__ -+#define __AUFS_RWSEM_H__ -+ -+#ifdef __KERNEL__ -+ -+#include "debug.h" -+ -+/* in the future, the name 'au_rwsem' will be totally gone */ -+#define au_rwsem rw_semaphore -+ -+/* to debug easier, do not make them inlined functions */ -+#define AuRwMustNoWaiters(rw) AuDebugOn(rwsem_is_contended(rw)) -+/* rwsem_is_locked() is unusable */ -+#define AuRwMustReadLock(rw) AuDebugOn(!lockdep_recursing(current) \ -+ && debug_locks \ -+ && !lockdep_is_held_type(rw, 1)) -+#define AuRwMustWriteLock(rw) AuDebugOn(!lockdep_recursing(current) \ -+ && debug_locks \ -+ && !lockdep_is_held_type(rw, 0)) -+#define AuRwMustAnyLock(rw) AuDebugOn(!lockdep_recursing(current) \ -+ && debug_locks \ -+ && !lockdep_is_held(rw)) -+#define AuRwDestroy(rw) AuDebugOn(!lockdep_recursing(current) \ -+ && debug_locks \ -+ && lockdep_is_held(rw)) -+ -+#define au_rw_init(rw) init_rwsem(rw) -+ -+#define au_rw_init_wlock(rw) do { \ -+ au_rw_init(rw); \ -+ down_write(rw); \ -+ } while (0) -+ -+#define au_rw_init_wlock_nested(rw, lsc) do { \ -+ au_rw_init(rw); \ -+ down_write_nested(rw, lsc); \ -+ } while (0) -+ -+#define au_rw_read_lock(rw) down_read(rw) -+#define au_rw_read_lock_nested(rw, lsc) down_read_nested(rw, lsc) -+#define au_rw_read_unlock(rw) up_read(rw) -+#define au_rw_dgrade_lock(rw) downgrade_write(rw) -+#define au_rw_write_lock(rw) down_write(rw) -+#define au_rw_write_lock_nested(rw, lsc) down_write_nested(rw, lsc) -+#define au_rw_write_unlock(rw) up_write(rw) -+/* why is not _nested version defined? */ -+#define au_rw_read_trylock(rw) down_read_trylock(rw) -+#define au_rw_write_trylock(rw) down_write_trylock(rw) -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_RWSEM_H__ */ -diff --git a/fs/aufs/sbinfo.c b/fs/aufs/sbinfo.c -new file mode 100644 -index 000000000000..26c6afab5df6 ---- /dev/null -+++ b/fs/aufs/sbinfo.c -@@ -0,0 +1,301 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * superblock private data -+ */ -+ -+#include -+#include "aufs.h" -+ -+/* -+ * they are necessary regardless sysfs is disabled. -+ */ -+void au_si_free(struct kobject *kobj) -+{ -+ int i; -+ struct au_sbinfo *sbinfo; -+ char *locked __maybe_unused; /* debug only */ -+ -+ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj); -+ for (i = 0; i < AuPlink_NHASH; i++) -+ AuDebugOn(!hlist_bl_empty(sbinfo->si_plink + i)); -+ AuDebugOn(atomic_read(&sbinfo->si_nowait.nw_len)); -+ -+ AuLCntZero(au_lcnt_read(&sbinfo->si_ninodes, /*do_rev*/0)); -+ au_lcnt_fin(&sbinfo->si_ninodes, /*do_sync*/0); -+ AuLCntZero(au_lcnt_read(&sbinfo->si_nfiles, /*do_rev*/0)); -+ au_lcnt_fin(&sbinfo->si_nfiles, /*do_sync*/0); -+ -+ dbgaufs_si_fin(sbinfo); -+ au_rw_write_lock(&sbinfo->si_rwsem); -+ au_br_free(sbinfo); -+ au_rw_write_unlock(&sbinfo->si_rwsem); -+ -+ au_kfree_try_rcu(sbinfo->si_branch); -+ mutex_destroy(&sbinfo->si_xib_mtx); -+ AuRwDestroy(&sbinfo->si_rwsem); -+ -+ au_lcnt_wait_for_fin(&sbinfo->si_ninodes); -+ /* si_nfiles is waited too */ -+ au_kfree_rcu(sbinfo); -+} -+ -+int au_si_alloc(struct super_block *sb) -+{ -+ int err, i; -+ struct au_sbinfo *sbinfo; -+ -+ err = -ENOMEM; -+ sbinfo = kzalloc(sizeof(*sbinfo), GFP_NOFS); -+ if (unlikely(!sbinfo)) -+ goto out; -+ -+ /* will be reallocated separately */ -+ sbinfo->si_branch = kzalloc(sizeof(*sbinfo->si_branch), GFP_NOFS); -+ if (unlikely(!sbinfo->si_branch)) -+ goto out_sbinfo; -+ -+ err = sysaufs_si_init(sbinfo); -+ if (!err) { -+ dbgaufs_si_null(sbinfo); -+ err = dbgaufs_si_init(sbinfo); -+ if (unlikely(err)) -+ kobject_put(&sbinfo->si_kobj); -+ } -+ if (unlikely(err)) -+ goto out_br; -+ -+ au_nwt_init(&sbinfo->si_nowait); -+ au_rw_init_wlock(&sbinfo->si_rwsem); -+ -+ au_lcnt_init(&sbinfo->si_ninodes, /*release*/NULL); -+ au_lcnt_init(&sbinfo->si_nfiles, /*release*/NULL); -+ -+ sbinfo->si_bbot = -1; -+ sbinfo->si_last_br_id = AUFS_BRANCH_MAX / 2; -+ -+ sbinfo->si_wbr_copyup = AuWbrCopyup_Def; -+ sbinfo->si_wbr_create = AuWbrCreate_Def; -+ sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + sbinfo->si_wbr_copyup; -+ sbinfo->si_wbr_create_ops = au_wbr_create_ops + sbinfo->si_wbr_create; -+ -+ au_fhsm_init(sbinfo); -+ -+ sbinfo->si_mntflags = au_opts_plink(AuOpt_Def); -+ -+ sbinfo->si_xino_jiffy = jiffies; -+ sbinfo->si_xino_expire -+ = msecs_to_jiffies(AUFS_XINO_DEF_SEC * MSEC_PER_SEC); -+ mutex_init(&sbinfo->si_xib_mtx); -+ /* leave si_xib_last_pindex and si_xib_next_bit */ -+ -+ INIT_HLIST_BL_HEAD(&sbinfo->si_aopen); -+ -+ sbinfo->si_rdcache = msecs_to_jiffies(AUFS_RDCACHE_DEF * MSEC_PER_SEC); -+ sbinfo->si_rdblk = AUFS_RDBLK_DEF; -+ sbinfo->si_rdhash = AUFS_RDHASH_DEF; -+ sbinfo->si_dirwh = AUFS_DIRWH_DEF; -+ -+ for (i = 0; i < AuPlink_NHASH; i++) -+ INIT_HLIST_BL_HEAD(sbinfo->si_plink + i); -+ init_waitqueue_head(&sbinfo->si_plink_wq); -+ spin_lock_init(&sbinfo->si_plink_maint_lock); -+ -+ INIT_HLIST_BL_HEAD(&sbinfo->si_files); -+ -+ /* with getattr by default */ -+ sbinfo->si_iop_array = aufs_iop; -+ -+ /* leave other members for sysaufs and si_mnt. */ -+ sbinfo->si_sb = sb; -+ sb->s_fs_info = sbinfo; -+ si_pid_set(sb); -+ return 0; /* success */ -+ -+out_br: -+ au_kfree_try_rcu(sbinfo->si_branch); -+out_sbinfo: -+ au_kfree_rcu(sbinfo); -+out: -+ return err; -+} -+ -+int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr, int may_shrink) -+{ -+ int err, sz; -+ struct au_branch **brp; -+ -+ AuRwMustWriteLock(&sbinfo->si_rwsem); -+ -+ err = -ENOMEM; -+ sz = sizeof(*brp) * (sbinfo->si_bbot + 1); -+ if (unlikely(!sz)) -+ sz = sizeof(*brp); -+ brp = au_kzrealloc(sbinfo->si_branch, sz, sizeof(*brp) * nbr, GFP_NOFS, -+ may_shrink); -+ if (brp) { -+ sbinfo->si_branch = brp; -+ err = 0; -+ } -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+unsigned int au_sigen_inc(struct super_block *sb) -+{ -+ unsigned int gen; -+ struct inode *inode; -+ -+ SiMustWriteLock(sb); -+ -+ gen = ++au_sbi(sb)->si_generation; -+ au_update_digen(sb->s_root); -+ inode = d_inode(sb->s_root); -+ au_update_iigen(inode, /*half*/0); -+ inode_inc_iversion(inode); -+ return gen; -+} -+ -+aufs_bindex_t au_new_br_id(struct super_block *sb) -+{ -+ aufs_bindex_t br_id; -+ int i; -+ struct au_sbinfo *sbinfo; -+ -+ SiMustWriteLock(sb); -+ -+ sbinfo = au_sbi(sb); -+ for (i = 0; i <= AUFS_BRANCH_MAX; i++) { -+ br_id = ++sbinfo->si_last_br_id; -+ AuDebugOn(br_id < 0); -+ if (br_id && au_br_index(sb, br_id) < 0) -+ return br_id; -+ } -+ -+ return -1; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* it is ok that new 'nwt' tasks are appended while we are sleeping */ -+int si_read_lock(struct super_block *sb, int flags) -+{ -+ int err; -+ -+ err = 0; -+ if (au_ftest_lock(flags, FLUSH)) -+ au_nwt_flush(&au_sbi(sb)->si_nowait); -+ -+ si_noflush_read_lock(sb); -+ err = au_plink_maint(sb, flags); -+ if (unlikely(err)) -+ si_read_unlock(sb); -+ -+ return err; -+} -+ -+int si_write_lock(struct super_block *sb, int flags) -+{ -+ int err; -+ -+ if (au_ftest_lock(flags, FLUSH)) -+ au_nwt_flush(&au_sbi(sb)->si_nowait); -+ -+ si_noflush_write_lock(sb); -+ err = au_plink_maint(sb, flags); -+ if (unlikely(err)) -+ si_write_unlock(sb); -+ -+ return err; -+} -+ -+/* dentry and super_block lock. call at entry point */ -+int aufs_read_lock(struct dentry *dentry, int flags) -+{ -+ int err; -+ struct super_block *sb; -+ -+ sb = dentry->d_sb; -+ err = si_read_lock(sb, flags); -+ if (unlikely(err)) -+ goto out; -+ -+ if (au_ftest_lock(flags, DW)) -+ di_write_lock_child(dentry); -+ else -+ di_read_lock_child(dentry, flags); -+ -+ if (au_ftest_lock(flags, GEN)) { -+ err = au_digen_test(dentry, au_sigen(sb)); -+ if (!au_opt_test(au_mntflags(sb), UDBA_NONE)) -+ AuDebugOn(!err && au_dbrange_test(dentry)); -+ else if (!err) -+ err = au_dbrange_test(dentry); -+ if (unlikely(err)) -+ aufs_read_unlock(dentry, flags); -+ } -+ -+out: -+ return err; -+} -+ -+void aufs_read_unlock(struct dentry *dentry, int flags) -+{ -+ if (au_ftest_lock(flags, DW)) -+ di_write_unlock(dentry); -+ else -+ di_read_unlock(dentry, flags); -+ si_read_unlock(dentry->d_sb); -+} -+ -+void aufs_write_lock(struct dentry *dentry) -+{ -+ si_write_lock(dentry->d_sb, AuLock_FLUSH | AuLock_NOPLMW); -+ di_write_lock_child(dentry); -+} -+ -+void aufs_write_unlock(struct dentry *dentry) -+{ -+ di_write_unlock(dentry); -+ si_write_unlock(dentry->d_sb); -+} -+ -+int aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags) -+{ -+ int err; -+ unsigned int sigen; -+ struct super_block *sb; -+ -+ sb = d1->d_sb; -+ err = si_read_lock(sb, flags); -+ if (unlikely(err)) -+ goto out; -+ -+ di_write_lock2_child(d1, d2, au_ftest_lock(flags, DIRS)); -+ -+ if (au_ftest_lock(flags, GEN)) { -+ sigen = au_sigen(sb); -+ err = au_digen_test(d1, sigen); -+ AuDebugOn(!err && au_dbrange_test(d1)); -+ if (!err) { -+ err = au_digen_test(d2, sigen); -+ AuDebugOn(!err && au_dbrange_test(d2)); -+ } -+ if (unlikely(err)) -+ aufs_read_and_write_unlock2(d1, d2); -+ } -+ -+out: -+ return err; -+} -+ -+void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2) -+{ -+ di_write_unlock2(d1, d2); -+ si_read_unlock(d1->d_sb); -+} -diff --git a/fs/aufs/super.c b/fs/aufs/super.c -new file mode 100644 -index 000000000000..589dd0122020 ---- /dev/null -+++ b/fs/aufs/super.c -@@ -0,0 +1,1034 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * mount and super_block operations -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include "aufs.h" -+ -+/* -+ * super_operations -+ */ -+static struct inode *aufs_alloc_inode(struct super_block *sb __maybe_unused) -+{ -+ struct au_icntnr *c; -+ -+ c = au_cache_alloc_icntnr(); -+ if (c) { -+ au_icntnr_init(c); -+ inode_set_iversion(&c->vfs_inode, 1); /* sigen(sb); */ -+ c->iinfo.ii_hinode = NULL; -+ return &c->vfs_inode; -+ } -+ return NULL; -+} -+ -+static void aufs_destroy_inode(struct inode *inode) -+{ -+ if (!au_is_bad_inode(inode)) -+ au_iinfo_fin(inode); -+} -+ -+static void aufs_free_inode(struct inode *inode) -+{ -+ au_cache_free_icntnr(container_of(inode, struct au_icntnr, vfs_inode)); -+} -+ -+struct inode *au_iget_locked(struct super_block *sb, ino_t ino) -+{ -+ struct inode *inode; -+ int err; -+ -+ inode = iget_locked(sb, ino); -+ if (unlikely(!inode)) { -+ inode = ERR_PTR(-ENOMEM); -+ goto out; -+ } -+ if (!(inode->i_state & I_NEW)) -+ goto out; -+ -+ err = au_xigen_new(inode); -+ if (!err) -+ err = au_iinfo_init(inode); -+ if (!err) -+ inode_inc_iversion(inode); -+ else { -+ iget_failed(inode); -+ inode = ERR_PTR(err); -+ } -+ -+out: -+ /* never return NULL */ -+ AuDebugOn(!inode); -+ AuTraceErrPtr(inode); -+ return inode; -+} -+ -+/* lock free root dinfo */ -+static int au_show_brs(struct seq_file *seq, struct super_block *sb) -+{ -+ int err; -+ aufs_bindex_t bindex, bbot; -+ struct path path; -+ struct au_hdentry *hdp; -+ struct au_branch *br; -+ au_br_perm_str_t perm; -+ -+ err = 0; -+ bbot = au_sbbot(sb); -+ bindex = 0; -+ hdp = au_hdentry(au_di(sb->s_root), bindex); -+ for (; !err && bindex <= bbot; bindex++, hdp++) { -+ br = au_sbr(sb, bindex); -+ path.mnt = au_br_mnt(br); -+ path.dentry = hdp->hd_dentry; -+ err = au_seq_path(seq, &path); -+ if (!err) { -+ au_optstr_br_perm(&perm, br->br_perm); -+ seq_printf(seq, "=%s", perm.a); -+ if (bindex != bbot) -+ seq_putc(seq, ':'); -+ } -+ } -+ if (unlikely(err || seq_has_overflowed(seq))) -+ err = -E2BIG; -+ -+ return err; -+} -+ -+static void au_gen_fmt(char *fmt, int len __maybe_unused, const char *pat, -+ const char *append) -+{ -+ char *p; -+ -+ p = fmt; -+ while (*pat != ':') -+ *p++ = *pat++; -+ *p++ = *pat++; -+ strcpy(p, append); -+ AuDebugOn(strlen(fmt) >= len); -+} -+ -+static void au_show_wbr_create(struct seq_file *m, int v, -+ struct au_sbinfo *sbinfo) -+{ -+ const char *pat; -+ char fmt[32]; -+ struct au_wbr_mfs *mfs; -+ -+ AuRwMustAnyLock(&sbinfo->si_rwsem); -+ -+ seq_puts(m, ",create="); -+ pat = au_optstr_wbr_create(v); -+ mfs = &sbinfo->si_wbr_mfs; -+ switch (v) { -+ case AuWbrCreate_TDP: -+ case AuWbrCreate_RR: -+ case AuWbrCreate_MFS: -+ case AuWbrCreate_PMFS: -+ seq_puts(m, pat); -+ break; -+ case AuWbrCreate_MFSRR: -+ case AuWbrCreate_TDMFS: -+ case AuWbrCreate_PMFSRR: -+ au_gen_fmt(fmt, sizeof(fmt), pat, "%llu"); -+ seq_printf(m, fmt, mfs->mfsrr_watermark); -+ break; -+ case AuWbrCreate_MFSV: -+ case AuWbrCreate_PMFSV: -+ au_gen_fmt(fmt, sizeof(fmt), pat, "%lu"); -+ seq_printf(m, fmt, -+ jiffies_to_msecs(mfs->mfs_expire) -+ / MSEC_PER_SEC); -+ break; -+ case AuWbrCreate_MFSRRV: -+ case AuWbrCreate_TDMFSV: -+ case AuWbrCreate_PMFSRRV: -+ au_gen_fmt(fmt, sizeof(fmt), pat, "%llu:%lu"); -+ seq_printf(m, fmt, mfs->mfsrr_watermark, -+ jiffies_to_msecs(mfs->mfs_expire) / MSEC_PER_SEC); -+ break; -+ default: -+ BUG(); -+ } -+} -+ -+static int au_show_xino(struct seq_file *seq, struct super_block *sb) -+{ -+#ifdef CONFIG_SYSFS -+ return 0; -+#else -+ int err; -+ const int len = sizeof(AUFS_XINO_FNAME) - 1; -+ aufs_bindex_t bindex, brid; -+ struct qstr *name; -+ struct file *f; -+ struct dentry *d, *h_root; -+ struct au_branch *br; -+ -+ AuRwMustAnyLock(&sbinfo->si_rwsem); -+ -+ err = 0; -+ f = au_sbi(sb)->si_xib; -+ if (!f) -+ goto out; -+ -+ /* stop printing the default xino path on the first writable branch */ -+ h_root = NULL; -+ bindex = au_xi_root(sb, f->f_path.dentry); -+ if (bindex >= 0) { -+ br = au_sbr_sb(sb, bindex); -+ h_root = au_br_dentry(br); -+ } -+ -+ d = f->f_path.dentry; -+ name = &d->d_name; -+ /* safe ->d_parent because the file is unlinked */ -+ if (d->d_parent == h_root -+ && name->len == len -+ && !memcmp(name->name, AUFS_XINO_FNAME, len)) -+ goto out; -+ -+ seq_puts(seq, ",xino="); -+ err = au_xino_path(seq, f); -+ -+out: -+ return err; -+#endif -+} -+ -+/* seq_file will re-call me in case of too long string */ -+static int aufs_show_options(struct seq_file *m, struct dentry *dentry) -+{ -+ int err; -+ unsigned int mnt_flags, v; -+ struct super_block *sb; -+ struct au_sbinfo *sbinfo; -+ -+#define AuBool(name, str) do { \ -+ v = au_opt_test(mnt_flags, name); \ -+ if (v != au_opt_test(AuOpt_Def, name)) \ -+ seq_printf(m, ",%s" #str, v ? "" : "no"); \ -+} while (0) -+ -+#define AuStr(name, str) do { \ -+ v = mnt_flags & AuOptMask_##name; \ -+ if (v != (AuOpt_Def & AuOptMask_##name)) \ -+ seq_printf(m, "," #str "=%s", au_optstr_##str(v)); \ -+} while (0) -+ -+#define AuUInt(name, str, val) do { \ -+ if (val != AUFS_##name##_DEF) \ -+ seq_printf(m, "," #str "=%u", val); \ -+} while (0) -+ -+ sb = dentry->d_sb; -+ if (sb->s_flags & SB_POSIXACL) -+ seq_puts(m, ",acl"); -+#if 0 /* reserved for future use */ -+ if (sb->s_flags & SB_I_VERSION) -+ seq_puts(m, ",i_version"); -+#endif -+ -+ /* lock free root dinfo */ -+ si_noflush_read_lock(sb); -+ sbinfo = au_sbi(sb); -+ seq_printf(m, ",si=%lx", sysaufs_si_id(sbinfo)); -+ -+ mnt_flags = au_mntflags(sb); -+ if (au_opt_test(mnt_flags, XINO)) { -+ err = au_show_xino(m, sb); -+ if (unlikely(err)) -+ goto out; -+ } else -+ seq_puts(m, ",noxino"); -+ -+ AuBool(TRUNC_XINO, trunc_xino); -+ AuStr(UDBA, udba); -+ AuBool(SHWH, shwh); -+ AuBool(PLINK, plink); -+ AuBool(DIO, dio); -+ AuBool(DIRPERM1, dirperm1); -+ -+ v = sbinfo->si_wbr_create; -+ if (v != AuWbrCreate_Def) -+ au_show_wbr_create(m, v, sbinfo); -+ -+ v = sbinfo->si_wbr_copyup; -+ if (v != AuWbrCopyup_Def) -+ seq_printf(m, ",cpup=%s", au_optstr_wbr_copyup(v)); -+ -+ v = au_opt_test(mnt_flags, ALWAYS_DIROPQ); -+ if (v != au_opt_test(AuOpt_Def, ALWAYS_DIROPQ)) -+ seq_printf(m, ",diropq=%c", v ? 'a' : 'w'); -+ -+ AuUInt(DIRWH, dirwh, sbinfo->si_dirwh); -+ -+ v = jiffies_to_msecs(sbinfo->si_rdcache) / MSEC_PER_SEC; -+ AuUInt(RDCACHE, rdcache, v); -+ -+ AuUInt(RDBLK, rdblk, sbinfo->si_rdblk); -+ AuUInt(RDHASH, rdhash, sbinfo->si_rdhash); -+ -+ au_fhsm_show(m, sbinfo); -+ -+ AuBool(DIRREN, dirren); -+ AuBool(SUM, sum); -+ /* AuBool(SUM_W, wsum); */ -+ AuBool(WARN_PERM, warn_perm); -+ AuBool(VERBOSE, verbose); -+ -+out: -+ /* be sure to print "br:" last */ -+ if (!sysaufs_brs) { -+ seq_puts(m, ",br:"); -+ au_show_brs(m, sb); -+ } -+ si_read_unlock(sb); -+ return 0; -+ -+#undef AuBool -+#undef AuStr -+#undef AuUInt -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* sum mode which returns the summation for statfs(2) */ -+ -+static u64 au_add_till_max(u64 a, u64 b) -+{ -+ u64 old; -+ -+ old = a; -+ a += b; -+ if (old <= a) -+ return a; -+ return ULLONG_MAX; -+} -+ -+static u64 au_mul_till_max(u64 a, long mul) -+{ -+ u64 old; -+ -+ old = a; -+ a *= mul; -+ if (old <= a) -+ return a; -+ return ULLONG_MAX; -+} -+ -+static int au_statfs_sum(struct super_block *sb, struct kstatfs *buf) -+{ -+ int err; -+ long bsize, factor; -+ u64 blocks, bfree, bavail, files, ffree; -+ aufs_bindex_t bbot, bindex, i; -+ unsigned char shared; -+ struct path h_path; -+ struct super_block *h_sb; -+ -+ err = 0; -+ bsize = LONG_MAX; -+ files = 0; -+ ffree = 0; -+ blocks = 0; -+ bfree = 0; -+ bavail = 0; -+ bbot = au_sbbot(sb); -+ for (bindex = 0; bindex <= bbot; bindex++) { -+ h_path.mnt = au_sbr_mnt(sb, bindex); -+ h_sb = h_path.mnt->mnt_sb; -+ shared = 0; -+ for (i = 0; !shared && i < bindex; i++) -+ shared = (au_sbr_sb(sb, i) == h_sb); -+ if (shared) -+ continue; -+ -+ /* sb->s_root for NFS is unreliable */ -+ h_path.dentry = h_path.mnt->mnt_root; -+ err = vfs_statfs(&h_path, buf); -+ if (unlikely(err)) -+ goto out; -+ -+ if (bsize > buf->f_bsize) { -+ /* -+ * we will reduce bsize, so we have to expand blocks -+ * etc. to match them again -+ */ -+ factor = (bsize / buf->f_bsize); -+ blocks = au_mul_till_max(blocks, factor); -+ bfree = au_mul_till_max(bfree, factor); -+ bavail = au_mul_till_max(bavail, factor); -+ bsize = buf->f_bsize; -+ } -+ -+ factor = (buf->f_bsize / bsize); -+ blocks = au_add_till_max(blocks, -+ au_mul_till_max(buf->f_blocks, factor)); -+ bfree = au_add_till_max(bfree, -+ au_mul_till_max(buf->f_bfree, factor)); -+ bavail = au_add_till_max(bavail, -+ au_mul_till_max(buf->f_bavail, factor)); -+ files = au_add_till_max(files, buf->f_files); -+ ffree = au_add_till_max(ffree, buf->f_ffree); -+ } -+ -+ buf->f_bsize = bsize; -+ buf->f_blocks = blocks; -+ buf->f_bfree = bfree; -+ buf->f_bavail = bavail; -+ buf->f_files = files; -+ buf->f_ffree = ffree; -+ buf->f_frsize = 0; -+ -+out: -+ return err; -+} -+ -+static int aufs_statfs(struct dentry *dentry, struct kstatfs *buf) -+{ -+ int err; -+ struct path h_path; -+ struct super_block *sb; -+ -+ /* lock free root dinfo */ -+ sb = dentry->d_sb; -+ si_noflush_read_lock(sb); -+ if (!au_opt_test(au_mntflags(sb), SUM)) { -+ /* sb->s_root for NFS is unreliable */ -+ h_path.mnt = au_sbr_mnt(sb, 0); -+ h_path.dentry = h_path.mnt->mnt_root; -+ err = vfs_statfs(&h_path, buf); -+ } else -+ err = au_statfs_sum(sb, buf); -+ si_read_unlock(sb); -+ -+ if (!err) { -+ buf->f_type = AUFS_SUPER_MAGIC; -+ buf->f_namelen = AUFS_MAX_NAMELEN; -+ memset(&buf->f_fsid, 0, sizeof(buf->f_fsid)); -+ } -+ /* buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1; */ -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int aufs_sync_fs(struct super_block *sb, int wait) -+{ -+ int err, e; -+ aufs_bindex_t bbot, bindex; -+ struct au_branch *br; -+ struct super_block *h_sb; -+ -+ err = 0; -+ si_noflush_read_lock(sb); -+ bbot = au_sbbot(sb); -+ for (bindex = 0; bindex <= bbot; bindex++) { -+ br = au_sbr(sb, bindex); -+ if (!au_br_writable(br->br_perm)) -+ continue; -+ -+ h_sb = au_sbr_sb(sb, bindex); -+ e = vfsub_sync_filesystem(h_sb, wait); -+ if (unlikely(e && !err)) -+ err = e; -+ /* go on even if an error happens */ -+ } -+ si_read_unlock(sb); -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* final actions when unmounting a file system */ -+static void aufs_put_super(struct super_block *sb) -+{ -+ struct au_sbinfo *sbinfo; -+ -+ sbinfo = au_sbi(sb); -+ if (sbinfo) -+ kobject_put(&sbinfo->si_kobj); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+void *au_array_alloc(unsigned long long *hint, au_arraycb_t cb, -+ struct super_block *sb, void *arg) -+{ -+ void *array; -+ unsigned long long n, sz; -+ -+ array = NULL; -+ n = 0; -+ if (!*hint) -+ goto out; -+ -+ if (*hint > ULLONG_MAX / sizeof(array)) { -+ array = ERR_PTR(-EMFILE); -+ pr_err("hint %llu\n", *hint); -+ goto out; -+ } -+ -+ sz = sizeof(array) * *hint; -+ array = kzalloc(sz, GFP_NOFS); -+ if (unlikely(!array)) -+ array = vzalloc(sz); -+ if (unlikely(!array)) { -+ array = ERR_PTR(-ENOMEM); -+ goto out; -+ } -+ -+ n = cb(sb, array, *hint, arg); -+ AuDebugOn(n > *hint); -+ -+out: -+ *hint = n; -+ return array; -+} -+ -+static unsigned long long au_iarray_cb(struct super_block *sb, void *a, -+ unsigned long long max __maybe_unused, -+ void *arg) -+{ -+ unsigned long long n; -+ struct inode **p, *inode; -+ struct list_head *head; -+ -+ n = 0; -+ p = a; -+ head = arg; -+ spin_lock(&sb->s_inode_list_lock); -+ list_for_each_entry(inode, head, i_sb_list) { -+ if (!au_is_bad_inode(inode) -+ && au_ii(inode)->ii_btop >= 0) { -+ spin_lock(&inode->i_lock); -+ if (atomic_read(&inode->i_count)) { -+ au_igrab(inode); -+ *p++ = inode; -+ n++; -+ AuDebugOn(n > max); -+ } -+ spin_unlock(&inode->i_lock); -+ } -+ } -+ spin_unlock(&sb->s_inode_list_lock); -+ -+ return n; -+} -+ -+struct inode **au_iarray_alloc(struct super_block *sb, unsigned long long *max) -+{ -+ struct au_sbinfo *sbi; -+ -+ sbi = au_sbi(sb); -+ *max = au_lcnt_read(&sbi->si_ninodes, /*do_rev*/1); -+ return au_array_alloc(max, au_iarray_cb, sb, &sb->s_inodes); -+} -+ -+void au_iarray_free(struct inode **a, unsigned long long max) -+{ -+ unsigned long long ull; -+ -+ for (ull = 0; ull < max; ull++) -+ iput(a[ull]); -+ kvfree(a); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * refresh dentry and inode at remount time. -+ */ -+/* todo: consolidate with simple_reval_dpath() and au_reval_for_attr() */ -+static int au_do_refresh(struct dentry *dentry, unsigned int dir_flags, -+ struct dentry *parent) -+{ -+ int err; -+ -+ di_write_lock_child(dentry); -+ di_read_lock_parent(parent, AuLock_IR); -+ err = au_refresh_dentry(dentry, parent); -+ if (!err && dir_flags) -+ au_hn_reset(d_inode(dentry), dir_flags); -+ di_read_unlock(parent, AuLock_IR); -+ di_write_unlock(dentry); -+ -+ return err; -+} -+ -+static int au_do_refresh_d(struct dentry *dentry, unsigned int sigen, -+ struct au_sbinfo *sbinfo, -+ const unsigned int dir_flags, unsigned int do_idop) -+{ -+ int err; -+ struct dentry *parent; -+ -+ err = 0; -+ parent = dget_parent(dentry); -+ if (!au_digen_test(parent, sigen) && au_digen_test(dentry, sigen)) { -+ if (d_really_is_positive(dentry)) { -+ if (!d_is_dir(dentry)) -+ err = au_do_refresh(dentry, /*dir_flags*/0, -+ parent); -+ else { -+ err = au_do_refresh(dentry, dir_flags, parent); -+ if (unlikely(err)) -+ au_fset_si(sbinfo, FAILED_REFRESH_DIR); -+ } -+ } else -+ err = au_do_refresh(dentry, /*dir_flags*/0, parent); -+ AuDbgDentry(dentry); -+ } -+ dput(parent); -+ -+ if (!err) { -+ if (do_idop) -+ au_refresh_dop(dentry, /*force_reval*/0); -+ } else -+ au_refresh_dop(dentry, /*force_reval*/1); -+ -+ AuTraceErr(err); -+ return err; -+} -+ -+static int au_refresh_d(struct super_block *sb, unsigned int do_idop) -+{ -+ int err, i, j, ndentry, e; -+ unsigned int sigen; -+ struct au_dcsub_pages dpages; -+ struct au_dpage *dpage; -+ struct dentry **dentries, *d; -+ struct au_sbinfo *sbinfo; -+ struct dentry *root = sb->s_root; -+ const unsigned int dir_flags = au_hi_flags(d_inode(root), /*isdir*/1); -+ -+ if (do_idop) -+ au_refresh_dop(root, /*force_reval*/0); -+ -+ err = au_dpages_init(&dpages, GFP_NOFS); -+ if (unlikely(err)) -+ goto out; -+ err = au_dcsub_pages(&dpages, root, NULL, NULL); -+ if (unlikely(err)) -+ goto out_dpages; -+ -+ sigen = au_sigen(sb); -+ sbinfo = au_sbi(sb); -+ for (i = 0; i < dpages.ndpage; i++) { -+ dpage = dpages.dpages + i; -+ dentries = dpage->dentries; -+ ndentry = dpage->ndentry; -+ for (j = 0; j < ndentry; j++) { -+ d = dentries[j]; -+ e = au_do_refresh_d(d, sigen, sbinfo, dir_flags, -+ do_idop); -+ if (unlikely(e && !err)) -+ err = e; -+ /* go on even err */ -+ } -+ } -+ -+out_dpages: -+ au_dpages_free(&dpages); -+out: -+ return err; -+} -+ -+static int au_refresh_i(struct super_block *sb, unsigned int do_idop) -+{ -+ int err, e; -+ unsigned int sigen; -+ unsigned long long max, ull; -+ struct inode *inode, **array; -+ -+ array = au_iarray_alloc(sb, &max); -+ err = PTR_ERR(array); -+ if (IS_ERR(array)) -+ goto out; -+ -+ err = 0; -+ sigen = au_sigen(sb); -+ for (ull = 0; ull < max; ull++) { -+ inode = array[ull]; -+ if (unlikely(!inode)) -+ break; -+ -+ e = 0; -+ ii_write_lock_child(inode); -+ if (au_iigen(inode, NULL) != sigen) { -+ e = au_refresh_hinode_self(inode); -+ if (unlikely(e)) { -+ au_refresh_iop(inode, /*force_getattr*/1); -+ pr_err("error %d, i%lu\n", e, inode->i_ino); -+ if (!err) -+ err = e; -+ /* go on even if err */ -+ } -+ } -+ if (!e && do_idop) -+ au_refresh_iop(inode, /*force_getattr*/0); -+ ii_write_unlock(inode); -+ } -+ -+ au_iarray_free(array, max); -+ -+out: -+ return err; -+} -+ -+static void au_remount_refresh(struct super_block *sb, unsigned int do_idop) -+{ -+ int err, e; -+ unsigned int udba; -+ aufs_bindex_t bindex, bbot; -+ struct dentry *root; -+ struct inode *inode; -+ struct au_branch *br; -+ struct au_sbinfo *sbi; -+ -+ au_sigen_inc(sb); -+ sbi = au_sbi(sb); -+ au_fclr_si(sbi, FAILED_REFRESH_DIR); -+ -+ root = sb->s_root; -+ DiMustNoWaiters(root); -+ inode = d_inode(root); -+ IiMustNoWaiters(inode); -+ -+ udba = au_opt_udba(sb); -+ bbot = au_sbbot(sb); -+ for (bindex = 0; bindex <= bbot; bindex++) { -+ br = au_sbr(sb, bindex); -+ err = au_hnotify_reset_br(udba, br, br->br_perm); -+ if (unlikely(err)) -+ AuIOErr("hnotify failed on br %d, %d, ignored\n", -+ bindex, err); -+ /* go on even if err */ -+ } -+ au_hn_reset(inode, au_hi_flags(inode, /*isdir*/1)); -+ -+ if (do_idop) { -+ if (au_ftest_si(sbi, NO_DREVAL)) { -+ AuDebugOn(sb->s_d_op == &aufs_dop_noreval); -+ sb->s_d_op = &aufs_dop_noreval; -+ AuDebugOn(sbi->si_iop_array == aufs_iop_nogetattr); -+ sbi->si_iop_array = aufs_iop_nogetattr; -+ } else { -+ AuDebugOn(sb->s_d_op == &aufs_dop); -+ sb->s_d_op = &aufs_dop; -+ AuDebugOn(sbi->si_iop_array == aufs_iop); -+ sbi->si_iop_array = aufs_iop; -+ } -+ pr_info("reset to %ps and %ps\n", -+ sb->s_d_op, sbi->si_iop_array); -+ } -+ -+ di_write_unlock(root); -+ err = au_refresh_d(sb, do_idop); -+ e = au_refresh_i(sb, do_idop); -+ if (unlikely(e && !err)) -+ err = e; -+ /* aufs_write_lock() calls ..._child() */ -+ di_write_lock_child(root); -+ -+ au_cpup_attr_all(inode, /*force*/1); -+ -+ if (unlikely(err)) -+ AuIOErr("refresh failed, ignored, %d\n", err); -+} -+ -+/* stop extra interpretation of errno in mount(8), and strange error messages */ -+static int cvt_err(int err) -+{ -+ AuTraceErr(err); -+ -+ switch (err) { -+ case -ENOENT: -+ case -ENOTDIR: -+ case -EEXIST: -+ case -EIO: -+ err = -EINVAL; -+ } -+ return err; -+} -+ -+static int aufs_remount_fs(struct super_block *sb, int *flags, char *data) -+{ -+ int err, do_dx; -+ unsigned int mntflags; -+ struct au_opts opts = { -+ .opt = NULL -+ }; -+ struct dentry *root; -+ struct inode *inode; -+ struct au_sbinfo *sbinfo; -+ -+ err = 0; -+ root = sb->s_root; -+ if (!data || !*data) { -+ err = si_write_lock(sb, AuLock_FLUSH | AuLock_NOPLM); -+ if (!err) { -+ di_write_lock_child(root); -+ err = au_opts_verify(sb, *flags, /*pending*/0); -+ aufs_write_unlock(root); -+ } -+ goto out; -+ } -+ -+ err = -ENOMEM; -+ opts.opt = (void *)__get_free_page(GFP_NOFS); -+ if (unlikely(!opts.opt)) -+ goto out; -+ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt); -+ opts.flags = AuOpts_REMOUNT; -+ opts.sb_flags = *flags; -+ -+ /* parse it before aufs lock */ -+ err = au_opts_parse(sb, data, &opts); -+ if (unlikely(err)) -+ goto out_opts; -+ -+ sbinfo = au_sbi(sb); -+ inode = d_inode(root); -+ inode_lock(inode); -+ err = si_write_lock(sb, AuLock_FLUSH | AuLock_NOPLM); -+ if (unlikely(err)) -+ goto out_mtx; -+ di_write_lock_child(root); -+ -+ /* au_opts_remount() may return an error */ -+ err = au_opts_remount(sb, &opts); -+ au_opts_free(&opts); -+ -+ if (au_ftest_opts(opts.flags, REFRESH)) -+ au_remount_refresh(sb, au_ftest_opts(opts.flags, REFRESH_IDOP)); -+ -+ if (au_ftest_opts(opts.flags, REFRESH_DYAOP)) { -+ mntflags = au_mntflags(sb); -+ do_dx = !!au_opt_test(mntflags, DIO); -+ au_dy_arefresh(do_dx); -+ } -+ -+ au_fhsm_wrote_all(sb, /*force*/1); /* ?? */ -+ aufs_write_unlock(root); -+ -+out_mtx: -+ inode_unlock(inode); -+out_opts: -+ free_page((unsigned long)opts.opt); -+out: -+ err = cvt_err(err); -+ AuTraceErr(err); -+ return err; -+} -+ -+static const struct super_operations aufs_sop = { -+ .alloc_inode = aufs_alloc_inode, -+ .destroy_inode = aufs_destroy_inode, -+ .free_inode = aufs_free_inode, -+ /* always deleting, no clearing */ -+ .drop_inode = generic_delete_inode, -+ .show_options = aufs_show_options, -+ .statfs = aufs_statfs, -+ .put_super = aufs_put_super, -+ .sync_fs = aufs_sync_fs, -+ .remount_fs = aufs_remount_fs -+}; -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int alloc_root(struct super_block *sb) -+{ -+ int err; -+ struct inode *inode; -+ struct dentry *root; -+ -+ err = -ENOMEM; -+ inode = au_iget_locked(sb, AUFS_ROOT_INO); -+ err = PTR_ERR(inode); -+ if (IS_ERR(inode)) -+ goto out; -+ -+ inode->i_op = aufs_iop + AuIop_DIR; /* with getattr by default */ -+ inode->i_fop = &aufs_dir_fop; -+ inode->i_mode = S_IFDIR; -+ set_nlink(inode, 2); -+ unlock_new_inode(inode); -+ -+ root = d_make_root(inode); -+ if (unlikely(!root)) -+ goto out; -+ err = PTR_ERR(root); -+ if (IS_ERR(root)) -+ goto out; -+ -+ err = au_di_init(root); -+ if (!err) { -+ sb->s_root = root; -+ return 0; /* success */ -+ } -+ dput(root); -+ -+out: -+ return err; -+} -+ -+static int aufs_fill_super(struct super_block *sb, void *raw_data, -+ int silent __maybe_unused) -+{ -+ int err; -+ struct au_opts opts = { -+ .opt = NULL -+ }; -+ struct au_sbinfo *sbinfo; -+ struct dentry *root; -+ struct inode *inode; -+ char *arg = raw_data; -+ -+ if (unlikely(!arg || !*arg)) { -+ err = -EINVAL; -+ pr_err("no arg\n"); -+ goto out; -+ } -+ -+ err = -ENOMEM; -+ opts.opt = (void *)__get_free_page(GFP_NOFS); -+ if (unlikely(!opts.opt)) -+ goto out; -+ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt); -+ opts.sb_flags = sb->s_flags; -+ -+ err = au_si_alloc(sb); -+ if (unlikely(err)) -+ goto out_opts; -+ sbinfo = au_sbi(sb); -+ -+ /* all timestamps always follow the ones on the branch */ -+ sb->s_flags |= SB_NOATIME | SB_NODIRATIME; -+ sb->s_flags |= SB_I_VERSION; /* do we really need this? */ -+ sb->s_op = &aufs_sop; -+ sb->s_d_op = &aufs_dop; -+ sb->s_magic = AUFS_SUPER_MAGIC; -+ sb->s_maxbytes = 0; -+ sb->s_stack_depth = 1; -+ au_export_init(sb); -+ au_xattr_init(sb); -+ -+ err = alloc_root(sb); -+ if (unlikely(err)) { -+ si_write_unlock(sb); -+ goto out_info; -+ } -+ root = sb->s_root; -+ inode = d_inode(root); -+ -+ /* -+ * actually we can parse options regardless aufs lock here. -+ * but at remount time, parsing must be done before aufs lock. -+ * so we follow the same rule. -+ */ -+ ii_write_lock_parent(inode); -+ aufs_write_unlock(root); -+ err = au_opts_parse(sb, arg, &opts); -+ if (unlikely(err)) -+ goto out_root; -+ -+ /* lock vfs_inode first, then aufs. */ -+ inode_lock(inode); -+ aufs_write_lock(root); -+ err = au_opts_mount(sb, &opts); -+ au_opts_free(&opts); -+ if (!err && au_ftest_si(sbinfo, NO_DREVAL)) { -+ sb->s_d_op = &aufs_dop_noreval; -+ pr_info("%ps\n", sb->s_d_op); -+ au_refresh_dop(root, /*force_reval*/0); -+ sbinfo->si_iop_array = aufs_iop_nogetattr; -+ au_refresh_iop(inode, /*force_getattr*/0); -+ } -+ aufs_write_unlock(root); -+ inode_unlock(inode); -+ if (!err) -+ goto out_opts; /* success */ -+ -+out_root: -+ dput(root); -+ sb->s_root = NULL; -+out_info: -+ kobject_put(&sbinfo->si_kobj); -+ sb->s_fs_info = NULL; -+out_opts: -+ free_page((unsigned long)opts.opt); -+out: -+ AuTraceErr(err); -+ err = cvt_err(err); -+ AuTraceErr(err); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static struct dentry *aufs_mount(struct file_system_type *fs_type, int flags, -+ const char *dev_name __maybe_unused, -+ void *raw_data) -+{ -+ struct dentry *root; -+ -+ /* all timestamps always follow the ones on the branch */ -+ /* mnt->mnt_flags |= MNT_NOATIME | MNT_NODIRATIME; */ -+ root = mount_nodev(fs_type, flags, raw_data, aufs_fill_super); -+ if (IS_ERR(root)) -+ goto out; -+ -+ au_sbilist_add(root->d_sb); -+ -+out: -+ return root; -+} -+ -+static void aufs_kill_sb(struct super_block *sb) -+{ -+ struct au_sbinfo *sbinfo; -+ -+ sbinfo = au_sbi(sb); -+ if (sbinfo) { -+ au_sbilist_del(sb); -+ aufs_write_lock(sb->s_root); -+ au_fhsm_fin(sb); -+ if (sbinfo->si_wbr_create_ops->fin) -+ sbinfo->si_wbr_create_ops->fin(sb); -+ if (au_opt_test(sbinfo->si_mntflags, UDBA_HNOTIFY)) { -+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_NONE); -+ au_remount_refresh(sb, /*do_idop*/0); -+ } -+ if (au_opt_test(sbinfo->si_mntflags, PLINK)) -+ au_plink_put(sb, /*verbose*/1); -+ au_xino_clr(sb); -+ au_dr_opt_flush(sb); -+ sbinfo->si_sb = NULL; -+ aufs_write_unlock(sb->s_root); -+ au_nwt_flush(&sbinfo->si_nowait); -+ } -+ kill_anon_super(sb); -+} -+ -+struct file_system_type aufs_fs_type = { -+ .name = AUFS_FSTYPE, -+ /* a race between rename and others */ -+ .fs_flags = FS_RENAME_DOES_D_MOVE, -+ .mount = aufs_mount, -+ .kill_sb = aufs_kill_sb, -+ /* no need to __module_get() and module_put(). */ -+ .owner = THIS_MODULE, -+}; -diff --git a/fs/aufs/super.h b/fs/aufs/super.h -new file mode 100644 -index 000000000000..37205202c272 ---- /dev/null -+++ b/fs/aufs/super.h -@@ -0,0 +1,576 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * super_block operations -+ */ -+ -+#ifndef __AUFS_SUPER_H__ -+#define __AUFS_SUPER_H__ -+ -+#ifdef __KERNEL__ -+ -+#include -+#include -+#include "hbl.h" -+#include "lcnt.h" -+#include "rwsem.h" -+#include "wkq.h" -+ -+/* policies to select one among multiple writable branches */ -+struct au_wbr_copyup_operations { -+ int (*copyup)(struct dentry *dentry); -+}; -+ -+#define AuWbr_DIR 1 /* target is a dir */ -+#define AuWbr_PARENT (1 << 1) /* always require a parent */ -+ -+#define au_ftest_wbr(flags, name) ((flags) & AuWbr_##name) -+#define au_fset_wbr(flags, name) { (flags) |= AuWbr_##name; } -+#define au_fclr_wbr(flags, name) { (flags) &= ~AuWbr_##name; } -+ -+struct au_wbr_create_operations { -+ int (*create)(struct dentry *dentry, unsigned int flags); -+ int (*init)(struct super_block *sb); -+ int (*fin)(struct super_block *sb); -+}; -+ -+struct au_wbr_mfs { -+ struct mutex mfs_lock; /* protect this structure */ -+ unsigned long mfs_jiffy; -+ unsigned long mfs_expire; -+ aufs_bindex_t mfs_bindex; -+ -+ unsigned long long mfsrr_bytes; -+ unsigned long long mfsrr_watermark; -+}; -+ -+#define AuPlink_NHASH 100 -+static inline int au_plink_hash(ino_t ino) -+{ -+ return ino % AuPlink_NHASH; -+} -+ -+/* File-based Hierarchical Storage Management */ -+struct au_fhsm { -+#ifdef CONFIG_AUFS_FHSM -+ /* allow only one process who can receive the notification */ -+ spinlock_t fhsm_spin; -+ pid_t fhsm_pid; -+ wait_queue_head_t fhsm_wqh; -+ atomic_t fhsm_readable; -+ -+ /* these are protected by si_rwsem */ -+ unsigned long fhsm_expire; -+ aufs_bindex_t fhsm_bottom; -+#endif -+}; -+ -+struct au_branch; -+struct au_sbinfo { -+ /* nowait tasks in the system-wide workqueue */ -+ struct au_nowait_tasks si_nowait; -+ -+ /* -+ * tried sb->s_umount, but failed due to the dependency between i_mutex. -+ * rwsem for au_sbinfo is necessary. -+ */ -+ struct au_rwsem si_rwsem; -+ -+ /* -+ * dirty approach to protect sb->sb_inodes and ->s_files (gone) from -+ * remount. -+ */ -+ au_lcnt_t si_ninodes, si_nfiles; -+ -+ /* branch management */ -+ unsigned int si_generation; -+ -+ /* see AuSi_ flags */ -+ unsigned char au_si_status; -+ -+ aufs_bindex_t si_bbot; -+ -+ /* dirty trick to keep br_id plus */ -+ unsigned int si_last_br_id : -+ sizeof(aufs_bindex_t) * BITS_PER_BYTE - 1; -+ struct au_branch **si_branch; -+ -+ /* policy to select a writable branch */ -+ unsigned char si_wbr_copyup; -+ unsigned char si_wbr_create; -+ struct au_wbr_copyup_operations *si_wbr_copyup_ops; -+ struct au_wbr_create_operations *si_wbr_create_ops; -+ -+ /* round robin */ -+ atomic_t si_wbr_rr_next; -+ -+ /* most free space */ -+ struct au_wbr_mfs si_wbr_mfs; -+ -+ /* File-based Hierarchical Storage Management */ -+ struct au_fhsm si_fhsm; -+ -+ /* mount flags */ -+ /* include/asm-ia64/siginfo.h defines a macro named si_flags */ -+ unsigned int si_mntflags; -+ -+ /* external inode number (bitmap and translation table) */ -+ vfs_readf_t si_xread; -+ vfs_writef_t si_xwrite; -+ loff_t si_ximaxent; /* max entries in a xino */ -+ -+ struct file *si_xib; -+ struct mutex si_xib_mtx; /* protect xib members */ -+ unsigned long *si_xib_buf; -+ unsigned long si_xib_last_pindex; -+ int si_xib_next_bit; -+ -+ unsigned long si_xino_jiffy; -+ unsigned long si_xino_expire; -+ /* reserved for future use */ -+ /* unsigned long long si_xib_limit; */ /* Max xib file size */ -+ -+#ifdef CONFIG_AUFS_EXPORT -+ /* i_generation */ -+ /* todo: make xigen file an array to support many inode numbers */ -+ struct file *si_xigen; -+ atomic_t si_xigen_next; -+#endif -+ -+ /* dirty trick to support atomic_open */ -+ struct hlist_bl_head si_aopen; -+ -+ /* vdir parameters */ -+ unsigned long si_rdcache; /* max cache time in jiffies */ -+ unsigned int si_rdblk; /* deblk size */ -+ unsigned int si_rdhash; /* hash size */ -+ -+ /* -+ * If the number of whiteouts are larger than si_dirwh, leave all of -+ * them after au_whtmp_ren to reduce the cost of rmdir(2). -+ * future fsck.aufs or kernel thread will remove them later. -+ * Otherwise, remove all whiteouts and the dir in rmdir(2). -+ */ -+ unsigned int si_dirwh; -+ -+ /* pseudo_link list */ -+ struct hlist_bl_head si_plink[AuPlink_NHASH]; -+ wait_queue_head_t si_plink_wq; -+ spinlock_t si_plink_maint_lock; -+ pid_t si_plink_maint_pid; -+ -+ /* file list */ -+ struct hlist_bl_head si_files; -+ -+ /* with/without getattr, brother of sb->s_d_op */ -+ const struct inode_operations *si_iop_array; -+ -+ /* -+ * sysfs and lifetime management. -+ * this is not a small structure and it may be a waste of memory in case -+ * of sysfs is disabled, particularly when many aufs-es are mounted. -+ * but using sysfs is majority. -+ */ -+ struct kobject si_kobj; -+#ifdef CONFIG_DEBUG_FS -+ struct dentry *si_dbgaufs; -+ struct dentry *si_dbgaufs_plink; -+ struct dentry *si_dbgaufs_xib; -+#ifdef CONFIG_AUFS_EXPORT -+ struct dentry *si_dbgaufs_xigen; -+#endif -+#endif -+ -+#ifdef CONFIG_AUFS_SBILIST -+ struct hlist_bl_node si_list; -+#endif -+ -+ /* dirty, necessary for unmounting, sysfs and sysrq */ -+ struct super_block *si_sb; -+}; -+ -+/* sbinfo status flags */ -+/* -+ * set true when refresh_dirs() failed at remount time. -+ * then try refreshing dirs at access time again. -+ * if it is false, refreshing dirs at access time is unnecessary -+ */ -+#define AuSi_FAILED_REFRESH_DIR 1 -+#define AuSi_FHSM (1 << 1) /* fhsm is active now */ -+#define AuSi_NO_DREVAL (1 << 2) /* disable all d_revalidate */ -+ -+#ifndef CONFIG_AUFS_FHSM -+#undef AuSi_FHSM -+#define AuSi_FHSM 0 -+#endif -+ -+static inline unsigned char au_do_ftest_si(struct au_sbinfo *sbi, -+ unsigned int flag) -+{ -+ AuRwMustAnyLock(&sbi->si_rwsem); -+ return sbi->au_si_status & flag; -+} -+#define au_ftest_si(sbinfo, name) au_do_ftest_si(sbinfo, AuSi_##name) -+#define au_fset_si(sbinfo, name) do { \ -+ AuRwMustWriteLock(&(sbinfo)->si_rwsem); \ -+ (sbinfo)->au_si_status |= AuSi_##name; \ -+} while (0) -+#define au_fclr_si(sbinfo, name) do { \ -+ AuRwMustWriteLock(&(sbinfo)->si_rwsem); \ -+ (sbinfo)->au_si_status &= ~AuSi_##name; \ -+} while (0) -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* policy to select one among writable branches */ -+#define AuWbrCopyup(sbinfo, ...) \ -+ ((sbinfo)->si_wbr_copyup_ops->copyup(__VA_ARGS__)) -+#define AuWbrCreate(sbinfo, ...) \ -+ ((sbinfo)->si_wbr_create_ops->create(__VA_ARGS__)) -+ -+/* flags for si_read_lock()/aufs_read_lock()/di_read_lock() */ -+#define AuLock_DW 1 /* write-lock dentry */ -+#define AuLock_IR (1 << 1) /* read-lock inode */ -+#define AuLock_IW (1 << 2) /* write-lock inode */ -+#define AuLock_FLUSH (1 << 3) /* wait for 'nowait' tasks */ -+#define AuLock_DIRS (1 << 4) /* target is a pair of dirs */ -+ /* except RENAME_EXCHANGE */ -+#define AuLock_NOPLM (1 << 5) /* return err in plm mode */ -+#define AuLock_NOPLMW (1 << 6) /* wait for plm mode ends */ -+#define AuLock_GEN (1 << 7) /* test digen/iigen */ -+#define au_ftest_lock(flags, name) ((flags) & AuLock_##name) -+#define au_fset_lock(flags, name) \ -+ do { (flags) |= AuLock_##name; } while (0) -+#define au_fclr_lock(flags, name) \ -+ do { (flags) &= ~AuLock_##name; } while (0) -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* super.c */ -+extern struct file_system_type aufs_fs_type; -+struct inode *au_iget_locked(struct super_block *sb, ino_t ino); -+typedef unsigned long long (*au_arraycb_t)(struct super_block *sb, void *array, -+ unsigned long long max, void *arg); -+void *au_array_alloc(unsigned long long *hint, au_arraycb_t cb, -+ struct super_block *sb, void *arg); -+struct inode **au_iarray_alloc(struct super_block *sb, unsigned long long *max); -+void au_iarray_free(struct inode **a, unsigned long long max); -+ -+/* sbinfo.c */ -+void au_si_free(struct kobject *kobj); -+int au_si_alloc(struct super_block *sb); -+int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr, int may_shrink); -+ -+unsigned int au_sigen_inc(struct super_block *sb); -+aufs_bindex_t au_new_br_id(struct super_block *sb); -+ -+int si_read_lock(struct super_block *sb, int flags); -+int si_write_lock(struct super_block *sb, int flags); -+int aufs_read_lock(struct dentry *dentry, int flags); -+void aufs_read_unlock(struct dentry *dentry, int flags); -+void aufs_write_lock(struct dentry *dentry); -+void aufs_write_unlock(struct dentry *dentry); -+int aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags); -+void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2); -+ -+/* wbr_policy.c */ -+extern struct au_wbr_copyup_operations au_wbr_copyup_ops[]; -+extern struct au_wbr_create_operations au_wbr_create_ops[]; -+int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst); -+int au_wbr_nonopq(struct dentry *dentry, aufs_bindex_t bindex); -+int au_wbr_do_copyup_bu(struct dentry *dentry, aufs_bindex_t btop); -+ -+/* mvdown.c */ -+int au_mvdown(struct dentry *dentry, struct aufs_mvdown __user *arg); -+ -+#ifdef CONFIG_AUFS_FHSM -+/* fhsm.c */ -+ -+static inline pid_t au_fhsm_pid(struct au_fhsm *fhsm) -+{ -+ pid_t pid; -+ -+ spin_lock(&fhsm->fhsm_spin); -+ pid = fhsm->fhsm_pid; -+ spin_unlock(&fhsm->fhsm_spin); -+ -+ return pid; -+} -+ -+void au_fhsm_wrote(struct super_block *sb, aufs_bindex_t bindex, int force); -+void au_fhsm_wrote_all(struct super_block *sb, int force); -+int au_fhsm_fd(struct super_block *sb, int oflags); -+int au_fhsm_br_alloc(struct au_branch *br); -+void au_fhsm_set_bottom(struct super_block *sb, aufs_bindex_t bindex); -+void au_fhsm_fin(struct super_block *sb); -+void au_fhsm_init(struct au_sbinfo *sbinfo); -+void au_fhsm_set(struct au_sbinfo *sbinfo, unsigned int sec); -+void au_fhsm_show(struct seq_file *seq, struct au_sbinfo *sbinfo); -+#else -+AuStubVoid(au_fhsm_wrote, struct super_block *sb, aufs_bindex_t bindex, -+ int force) -+AuStubVoid(au_fhsm_wrote_all, struct super_block *sb, int force) -+AuStub(int, au_fhsm_fd, return -EOPNOTSUPP, struct super_block *sb, int oflags) -+AuStub(pid_t, au_fhsm_pid, return 0, struct au_fhsm *fhsm) -+AuStubInt0(au_fhsm_br_alloc, struct au_branch *br) -+AuStubVoid(au_fhsm_set_bottom, struct super_block *sb, aufs_bindex_t bindex) -+AuStubVoid(au_fhsm_fin, struct super_block *sb) -+AuStubVoid(au_fhsm_init, struct au_sbinfo *sbinfo) -+AuStubVoid(au_fhsm_set, struct au_sbinfo *sbinfo, unsigned int sec) -+AuStubVoid(au_fhsm_show, struct seq_file *seq, struct au_sbinfo *sbinfo) -+#endif -+ -+/* ---------------------------------------------------------------------- */ -+ -+static inline struct au_sbinfo *au_sbi(struct super_block *sb) -+{ -+ return sb->s_fs_info; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+#ifdef CONFIG_AUFS_EXPORT -+int au_test_nfsd(void); -+void au_export_init(struct super_block *sb); -+void au_xigen_inc(struct inode *inode); -+int au_xigen_new(struct inode *inode); -+int au_xigen_set(struct super_block *sb, struct path *path); -+void au_xigen_clr(struct super_block *sb); -+ -+static inline int au_busy_or_stale(void) -+{ -+ if (!au_test_nfsd()) -+ return -EBUSY; -+ return -ESTALE; -+} -+#else -+AuStubInt0(au_test_nfsd, void) -+AuStubVoid(au_export_init, struct super_block *sb) -+AuStubVoid(au_xigen_inc, struct inode *inode) -+AuStubInt0(au_xigen_new, struct inode *inode) -+AuStubInt0(au_xigen_set, struct super_block *sb, struct path *path) -+AuStubVoid(au_xigen_clr, struct super_block *sb) -+AuStub(int, au_busy_or_stale, return -EBUSY, void) -+#endif /* CONFIG_AUFS_EXPORT */ -+ -+/* ---------------------------------------------------------------------- */ -+ -+#ifdef CONFIG_AUFS_SBILIST -+/* module.c */ -+extern struct hlist_bl_head au_sbilist; -+ -+static inline void au_sbilist_init(void) -+{ -+ INIT_HLIST_BL_HEAD(&au_sbilist); -+} -+ -+static inline void au_sbilist_add(struct super_block *sb) -+{ -+ au_hbl_add(&au_sbi(sb)->si_list, &au_sbilist); -+} -+ -+static inline void au_sbilist_del(struct super_block *sb) -+{ -+ au_hbl_del(&au_sbi(sb)->si_list, &au_sbilist); -+} -+ -+#ifdef CONFIG_AUFS_MAGIC_SYSRQ -+static inline void au_sbilist_lock(void) -+{ -+ hlist_bl_lock(&au_sbilist); -+} -+ -+static inline void au_sbilist_unlock(void) -+{ -+ hlist_bl_unlock(&au_sbilist); -+} -+#define AuGFP_SBILIST GFP_ATOMIC -+#else -+AuStubVoid(au_sbilist_lock, void) -+AuStubVoid(au_sbilist_unlock, void) -+#define AuGFP_SBILIST GFP_NOFS -+#endif /* CONFIG_AUFS_MAGIC_SYSRQ */ -+#else -+AuStubVoid(au_sbilist_init, void) -+AuStubVoid(au_sbilist_add, struct super_block *sb) -+AuStubVoid(au_sbilist_del, struct super_block *sb) -+AuStubVoid(au_sbilist_lock, void) -+AuStubVoid(au_sbilist_unlock, void) -+#define AuGFP_SBILIST GFP_NOFS -+#endif -+ -+/* ---------------------------------------------------------------------- */ -+ -+static inline void dbgaufs_si_null(struct au_sbinfo *sbinfo) -+{ -+ /* -+ * This function is a dynamic '__init' function actually, -+ * so the tiny check for si_rwsem is unnecessary. -+ */ -+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */ -+#ifdef CONFIG_DEBUG_FS -+ sbinfo->si_dbgaufs = NULL; -+ sbinfo->si_dbgaufs_plink = NULL; -+ sbinfo->si_dbgaufs_xib = NULL; -+#ifdef CONFIG_AUFS_EXPORT -+ sbinfo->si_dbgaufs_xigen = NULL; -+#endif -+#endif -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* current->atomic_flags */ -+/* this value should never corrupt the ones defined in linux/sched.h */ -+#define PFA_AUFS 0x10 -+ -+TASK_PFA_TEST(AUFS, test_aufs) /* task_test_aufs */ -+TASK_PFA_SET(AUFS, aufs) /* task_set_aufs */ -+TASK_PFA_CLEAR(AUFS, aufs) /* task_clear_aufs */ -+ -+static inline int si_pid_test(struct super_block *sb) -+{ -+ return !!task_test_aufs(current); -+} -+ -+static inline void si_pid_clr(struct super_block *sb) -+{ -+ AuDebugOn(!task_test_aufs(current)); -+ task_clear_aufs(current); -+} -+ -+static inline void si_pid_set(struct super_block *sb) -+{ -+ AuDebugOn(task_test_aufs(current)); -+ task_set_aufs(current); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* lock superblock. mainly for entry point functions */ -+#define __si_read_lock(sb) au_rw_read_lock(&au_sbi(sb)->si_rwsem) -+#define __si_write_lock(sb) au_rw_write_lock(&au_sbi(sb)->si_rwsem) -+#define __si_read_trylock(sb) au_rw_read_trylock(&au_sbi(sb)->si_rwsem) -+#define __si_write_trylock(sb) au_rw_write_trylock(&au_sbi(sb)->si_rwsem) -+/* -+#define __si_read_trylock_nested(sb) \ -+ au_rw_read_trylock_nested(&au_sbi(sb)->si_rwsem) -+#define __si_write_trylock_nested(sb) \ -+ au_rw_write_trylock_nested(&au_sbi(sb)->si_rwsem) -+*/ -+ -+#define __si_read_unlock(sb) au_rw_read_unlock(&au_sbi(sb)->si_rwsem) -+#define __si_write_unlock(sb) au_rw_write_unlock(&au_sbi(sb)->si_rwsem) -+#define __si_downgrade_lock(sb) au_rw_dgrade_lock(&au_sbi(sb)->si_rwsem) -+ -+#define SiMustNoWaiters(sb) AuRwMustNoWaiters(&au_sbi(sb)->si_rwsem) -+#define SiMustAnyLock(sb) AuRwMustAnyLock(&au_sbi(sb)->si_rwsem) -+#define SiMustWriteLock(sb) AuRwMustWriteLock(&au_sbi(sb)->si_rwsem) -+ -+static inline void si_noflush_read_lock(struct super_block *sb) -+{ -+ __si_read_lock(sb); -+ si_pid_set(sb); -+} -+ -+static inline int si_noflush_read_trylock(struct super_block *sb) -+{ -+ int locked; -+ -+ locked = __si_read_trylock(sb); -+ if (locked) -+ si_pid_set(sb); -+ return locked; -+} -+ -+static inline void si_noflush_write_lock(struct super_block *sb) -+{ -+ __si_write_lock(sb); -+ si_pid_set(sb); -+} -+ -+static inline int si_noflush_write_trylock(struct super_block *sb) -+{ -+ int locked; -+ -+ locked = __si_write_trylock(sb); -+ if (locked) -+ si_pid_set(sb); -+ return locked; -+} -+ -+#if 0 /* reserved */ -+static inline int si_read_trylock(struct super_block *sb, int flags) -+{ -+ if (au_ftest_lock(flags, FLUSH)) -+ au_nwt_flush(&au_sbi(sb)->si_nowait); -+ return si_noflush_read_trylock(sb); -+} -+#endif -+ -+static inline void si_read_unlock(struct super_block *sb) -+{ -+ si_pid_clr(sb); -+ __si_read_unlock(sb); -+} -+ -+#if 0 /* reserved */ -+static inline int si_write_trylock(struct super_block *sb, int flags) -+{ -+ if (au_ftest_lock(flags, FLUSH)) -+ au_nwt_flush(&au_sbi(sb)->si_nowait); -+ return si_noflush_write_trylock(sb); -+} -+#endif -+ -+static inline void si_write_unlock(struct super_block *sb) -+{ -+ si_pid_clr(sb); -+ __si_write_unlock(sb); -+} -+ -+#if 0 /* reserved */ -+static inline void si_downgrade_lock(struct super_block *sb) -+{ -+ __si_downgrade_lock(sb); -+} -+#endif -+ -+/* ---------------------------------------------------------------------- */ -+ -+static inline aufs_bindex_t au_sbbot(struct super_block *sb) -+{ -+ SiMustAnyLock(sb); -+ return au_sbi(sb)->si_bbot; -+} -+ -+static inline unsigned int au_mntflags(struct super_block *sb) -+{ -+ SiMustAnyLock(sb); -+ return au_sbi(sb)->si_mntflags; -+} -+ -+static inline unsigned int au_sigen(struct super_block *sb) -+{ -+ SiMustAnyLock(sb); -+ return au_sbi(sb)->si_generation; -+} -+ -+static inline struct au_branch *au_sbr(struct super_block *sb, -+ aufs_bindex_t bindex) -+{ -+ SiMustAnyLock(sb); -+ return au_sbi(sb)->si_branch[0 + bindex]; -+} -+ -+static inline loff_t au_xi_maxent(struct super_block *sb) -+{ -+ SiMustAnyLock(sb); -+ return au_sbi(sb)->si_ximaxent; -+} -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_SUPER_H__ */ -diff --git a/fs/aufs/sysaufs.c b/fs/aufs/sysaufs.c -new file mode 100644 -index 000000000000..88d64b34555e ---- /dev/null -+++ b/fs/aufs/sysaufs.c -@@ -0,0 +1,80 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * sysfs interface and lifetime management -+ * they are necessary regardless sysfs is disabled. -+ */ -+ -+#include -+#include "aufs.h" -+ -+unsigned long sysaufs_si_mask; -+struct kset *sysaufs_kset; -+ -+#define AuSiAttr(_name) { \ -+ .attr = { .name = __stringify(_name), .mode = 0444 }, \ -+ .show = sysaufs_si_##_name, \ -+} -+ -+static struct sysaufs_si_attr sysaufs_si_attr_xi_path = AuSiAttr(xi_path); -+struct attribute *sysaufs_si_attrs[] = { -+ &sysaufs_si_attr_xi_path.attr, -+ NULL, -+}; -+ -+static const struct sysfs_ops au_sbi_ops = { -+ .show = sysaufs_si_show -+}; -+ -+static struct kobj_type au_sbi_ktype = { -+ .release = au_si_free, -+ .sysfs_ops = &au_sbi_ops, -+ .default_attrs = sysaufs_si_attrs -+}; -+ -+/* ---------------------------------------------------------------------- */ -+ -+int sysaufs_si_init(struct au_sbinfo *sbinfo) -+{ -+ int err; -+ -+ sbinfo->si_kobj.kset = sysaufs_kset; -+ /* cf. sysaufs_name() */ -+ err = kobject_init_and_add -+ (&sbinfo->si_kobj, &au_sbi_ktype, /*&sysaufs_kset->kobj*/NULL, -+ SysaufsSiNamePrefix "%lx", sysaufs_si_id(sbinfo)); -+ -+ return err; -+} -+ -+void sysaufs_fin(void) -+{ -+ sysfs_remove_group(&sysaufs_kset->kobj, sysaufs_attr_group); -+ kset_unregister(sysaufs_kset); -+} -+ -+int __init sysaufs_init(void) -+{ -+ int err; -+ -+ do { -+ get_random_bytes(&sysaufs_si_mask, sizeof(sysaufs_si_mask)); -+ } while (!sysaufs_si_mask); -+ -+ err = -EINVAL; -+ sysaufs_kset = kset_create_and_add(AUFS_NAME, NULL, fs_kobj); -+ if (unlikely(!sysaufs_kset)) -+ goto out; -+ err = PTR_ERR(sysaufs_kset); -+ if (IS_ERR(sysaufs_kset)) -+ goto out; -+ err = sysfs_create_group(&sysaufs_kset->kobj, sysaufs_attr_group); -+ if (unlikely(err)) -+ kset_unregister(sysaufs_kset); -+ -+out: -+ return err; -+} -diff --git a/fs/aufs/sysaufs.h b/fs/aufs/sysaufs.h -new file mode 100644 -index 000000000000..0d14752482cf ---- /dev/null -+++ b/fs/aufs/sysaufs.h -@@ -0,0 +1,89 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * sysfs interface and mount lifetime management -+ */ -+ -+#ifndef __SYSAUFS_H__ -+#define __SYSAUFS_H__ -+ -+#ifdef __KERNEL__ -+ -+#include -+#include "module.h" -+ -+struct super_block; -+struct au_sbinfo; -+ -+struct sysaufs_si_attr { -+ struct attribute attr; -+ int (*show)(struct seq_file *seq, struct super_block *sb); -+}; -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* sysaufs.c */ -+extern unsigned long sysaufs_si_mask; -+extern struct kset *sysaufs_kset; -+extern struct attribute *sysaufs_si_attrs[]; -+int sysaufs_si_init(struct au_sbinfo *sbinfo); -+int __init sysaufs_init(void); -+void sysaufs_fin(void); -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* some people doesn't like to show a pointer in kernel */ -+static inline unsigned long sysaufs_si_id(struct au_sbinfo *sbinfo) -+{ -+ return sysaufs_si_mask ^ (unsigned long)sbinfo; -+} -+ -+#define SysaufsSiNamePrefix "si_" -+#define SysaufsSiNameLen (sizeof(SysaufsSiNamePrefix) + 16) -+static inline void sysaufs_name(struct au_sbinfo *sbinfo, char *name) -+{ -+ snprintf(name, SysaufsSiNameLen, SysaufsSiNamePrefix "%lx", -+ sysaufs_si_id(sbinfo)); -+} -+ -+struct au_branch; -+#ifdef CONFIG_SYSFS -+/* sysfs.c */ -+extern struct attribute_group *sysaufs_attr_group; -+ -+int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb); -+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr, -+ char *buf); -+long au_brinfo_ioctl(struct file *file, unsigned long arg); -+#ifdef CONFIG_COMPAT -+long au_brinfo_compat_ioctl(struct file *file, unsigned long arg); -+#endif -+ -+void sysaufs_br_init(struct au_branch *br); -+void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex); -+void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex); -+ -+#define sysaufs_brs_init() do {} while (0) -+ -+#else -+#define sysaufs_attr_group NULL -+ -+AuStubInt0(sysaufs_si_xi_path, struct seq_file *seq, struct super_block *sb) -+AuStub(ssize_t, sysaufs_si_show, return 0, struct kobject *kobj, -+ struct attribute *attr, char *buf) -+AuStubVoid(sysaufs_br_init, struct au_branch *br) -+AuStubVoid(sysaufs_brs_add, struct super_block *sb, aufs_bindex_t bindex) -+AuStubVoid(sysaufs_brs_del, struct super_block *sb, aufs_bindex_t bindex) -+ -+static inline void sysaufs_brs_init(void) -+{ -+ sysaufs_brs = 0; -+} -+ -+#endif /* CONFIG_SYSFS */ -+ -+#endif /* __KERNEL__ */ -+#endif /* __SYSAUFS_H__ */ -diff --git a/fs/aufs/sysfs.c b/fs/aufs/sysfs.c -new file mode 100644 -index 000000000000..955ed071a12a ---- /dev/null -+++ b/fs/aufs/sysfs.c -@@ -0,0 +1,338 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * sysfs interface -+ */ -+ -+#include -+#include -+#include "aufs.h" -+ -+static struct attribute *au_attr[] = { -+ NULL, /* need to NULL terminate the list of attributes */ -+}; -+ -+static struct attribute_group sysaufs_attr_group_body = { -+ .attrs = au_attr -+}; -+ -+struct attribute_group *sysaufs_attr_group = &sysaufs_attr_group_body; -+ -+/* ---------------------------------------------------------------------- */ -+ -+int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb) -+{ -+ int err; -+ -+ SiMustAnyLock(sb); -+ -+ err = 0; -+ if (au_opt_test(au_mntflags(sb), XINO)) { -+ err = au_xino_path(seq, au_sbi(sb)->si_xib); -+ seq_putc(seq, '\n'); -+ } -+ return err; -+} -+ -+/* -+ * the lifetime of branch is independent from the entry under sysfs. -+ * sysfs handles the lifetime of the entry, and never call ->show() after it is -+ * unlinked. -+ */ -+static int sysaufs_si_br(struct seq_file *seq, struct super_block *sb, -+ aufs_bindex_t bindex, int idx) -+{ -+ int err; -+ struct path path; -+ struct dentry *root; -+ struct au_branch *br; -+ au_br_perm_str_t perm; -+ -+ AuDbg("b%d\n", bindex); -+ -+ err = 0; -+ root = sb->s_root; -+ di_read_lock_parent(root, !AuLock_IR); -+ br = au_sbr(sb, bindex); -+ -+ switch (idx) { -+ case AuBrSysfs_BR: -+ path.mnt = au_br_mnt(br); -+ path.dentry = au_h_dptr(root, bindex); -+ err = au_seq_path(seq, &path); -+ if (!err) { -+ au_optstr_br_perm(&perm, br->br_perm); -+ seq_printf(seq, "=%s\n", perm.a); -+ } -+ break; -+ case AuBrSysfs_BRID: -+ seq_printf(seq, "%d\n", br->br_id); -+ break; -+ } -+ di_read_unlock(root, !AuLock_IR); -+ if (unlikely(err || seq_has_overflowed(seq))) -+ err = -E2BIG; -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static struct seq_file *au_seq(char *p, ssize_t len) -+{ -+ struct seq_file *seq; -+ -+ seq = kzalloc(sizeof(*seq), GFP_NOFS); -+ if (seq) { -+ /* mutex_init(&seq.lock); */ -+ seq->buf = p; -+ seq->size = len; -+ return seq; /* success */ -+ } -+ -+ seq = ERR_PTR(-ENOMEM); -+ return seq; -+} -+ -+#define SysaufsBr_PREFIX "br" -+#define SysaufsBrid_PREFIX "brid" -+ -+/* todo: file size may exceed PAGE_SIZE */ -+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr, -+ char *buf) -+{ -+ ssize_t err; -+ int idx; -+ long l; -+ aufs_bindex_t bbot; -+ struct au_sbinfo *sbinfo; -+ struct super_block *sb; -+ struct seq_file *seq; -+ char *name; -+ struct attribute **cattr; -+ -+ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj); -+ sb = sbinfo->si_sb; -+ -+ /* -+ * prevent a race condition between sysfs and aufs. -+ * for instance, sysfs_file_read() calls sysfs_get_active_two() which -+ * prohibits maintaining the sysfs entries. -+ * hew we acquire read lock after sysfs_get_active_two(). -+ * on the other hand, the remount process may maintain the sysfs/aufs -+ * entries after acquiring write lock. -+ * it can cause a deadlock. -+ * simply we gave up processing read here. -+ */ -+ err = -EBUSY; -+ if (unlikely(!si_noflush_read_trylock(sb))) -+ goto out; -+ -+ seq = au_seq(buf, PAGE_SIZE); -+ err = PTR_ERR(seq); -+ if (IS_ERR(seq)) -+ goto out_unlock; -+ -+ name = (void *)attr->name; -+ cattr = sysaufs_si_attrs; -+ while (*cattr) { -+ if (!strcmp(name, (*cattr)->name)) { -+ err = container_of(*cattr, struct sysaufs_si_attr, attr) -+ ->show(seq, sb); -+ goto out_seq; -+ } -+ cattr++; -+ } -+ -+ if (!strncmp(name, SysaufsBrid_PREFIX, -+ sizeof(SysaufsBrid_PREFIX) - 1)) { -+ idx = AuBrSysfs_BRID; -+ name += sizeof(SysaufsBrid_PREFIX) - 1; -+ } else if (!strncmp(name, SysaufsBr_PREFIX, -+ sizeof(SysaufsBr_PREFIX) - 1)) { -+ idx = AuBrSysfs_BR; -+ name += sizeof(SysaufsBr_PREFIX) - 1; -+ } else -+ BUG(); -+ -+ err = kstrtol(name, 10, &l); -+ if (!err) { -+ bbot = au_sbbot(sb); -+ if (l <= bbot) -+ err = sysaufs_si_br(seq, sb, (aufs_bindex_t)l, idx); -+ else -+ err = -ENOENT; -+ } -+ -+out_seq: -+ if (!err) { -+ err = seq->count; -+ /* sysfs limit */ -+ if (unlikely(err == PAGE_SIZE)) -+ err = -EFBIG; -+ } -+ au_kfree_rcu(seq); -+out_unlock: -+ si_read_unlock(sb); -+out: -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int au_brinfo(struct super_block *sb, union aufs_brinfo __user *arg) -+{ -+ int err; -+ int16_t brid; -+ aufs_bindex_t bindex, bbot; -+ size_t sz; -+ char *buf; -+ struct seq_file *seq; -+ struct au_branch *br; -+ -+ si_read_lock(sb, AuLock_FLUSH); -+ bbot = au_sbbot(sb); -+ err = bbot + 1; -+ if (!arg) -+ goto out; -+ -+ err = -ENOMEM; -+ buf = (void *)__get_free_page(GFP_NOFS); -+ if (unlikely(!buf)) -+ goto out; -+ -+ seq = au_seq(buf, PAGE_SIZE); -+ err = PTR_ERR(seq); -+ if (IS_ERR(seq)) -+ goto out_buf; -+ -+ sz = sizeof(*arg) - offsetof(union aufs_brinfo, path); -+ for (bindex = 0; bindex <= bbot; bindex++, arg++) { -+ /* VERIFY_WRITE */ -+ err = !access_ok(arg, sizeof(*arg)); -+ if (unlikely(err)) -+ break; -+ -+ br = au_sbr(sb, bindex); -+ brid = br->br_id; -+ BUILD_BUG_ON(sizeof(brid) != sizeof(arg->id)); -+ err = __put_user(brid, &arg->id); -+ if (unlikely(err)) -+ break; -+ -+ BUILD_BUG_ON(sizeof(br->br_perm) != sizeof(arg->perm)); -+ err = __put_user(br->br_perm, &arg->perm); -+ if (unlikely(err)) -+ break; -+ -+ err = au_seq_path(seq, &br->br_path); -+ if (unlikely(err)) -+ break; -+ seq_putc(seq, '\0'); -+ if (!seq_has_overflowed(seq)) { -+ err = copy_to_user(arg->path, seq->buf, seq->count); -+ seq->count = 0; -+ if (unlikely(err)) -+ break; -+ } else { -+ err = -E2BIG; -+ goto out_seq; -+ } -+ } -+ if (unlikely(err)) -+ err = -EFAULT; -+ -+out_seq: -+ au_kfree_rcu(seq); -+out_buf: -+ free_page((unsigned long)buf); -+out: -+ si_read_unlock(sb); -+ return err; -+} -+ -+long au_brinfo_ioctl(struct file *file, unsigned long arg) -+{ -+ return au_brinfo(file->f_path.dentry->d_sb, (void __user *)arg); -+} -+ -+#ifdef CONFIG_COMPAT -+long au_brinfo_compat_ioctl(struct file *file, unsigned long arg) -+{ -+ return au_brinfo(file->f_path.dentry->d_sb, compat_ptr(arg)); -+} -+#endif -+ -+/* ---------------------------------------------------------------------- */ -+ -+void sysaufs_br_init(struct au_branch *br) -+{ -+ int i; -+ struct au_brsysfs *br_sysfs; -+ struct attribute *attr; -+ -+ br_sysfs = br->br_sysfs; -+ for (i = 0; i < ARRAY_SIZE(br->br_sysfs); i++) { -+ attr = &br_sysfs->attr; -+ sysfs_attr_init(attr); -+ attr->name = br_sysfs->name; -+ attr->mode = 0444; -+ br_sysfs++; -+ } -+} -+ -+void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex) -+{ -+ struct au_branch *br; -+ struct kobject *kobj; -+ struct au_brsysfs *br_sysfs; -+ int i; -+ aufs_bindex_t bbot; -+ -+ if (!sysaufs_brs) -+ return; -+ -+ kobj = &au_sbi(sb)->si_kobj; -+ bbot = au_sbbot(sb); -+ for (; bindex <= bbot; bindex++) { -+ br = au_sbr(sb, bindex); -+ br_sysfs = br->br_sysfs; -+ for (i = 0; i < ARRAY_SIZE(br->br_sysfs); i++) { -+ sysfs_remove_file(kobj, &br_sysfs->attr); -+ br_sysfs++; -+ } -+ } -+} -+ -+void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex) -+{ -+ int err, i; -+ aufs_bindex_t bbot; -+ struct kobject *kobj; -+ struct au_branch *br; -+ struct au_brsysfs *br_sysfs; -+ -+ if (!sysaufs_brs) -+ return; -+ -+ kobj = &au_sbi(sb)->si_kobj; -+ bbot = au_sbbot(sb); -+ for (; bindex <= bbot; bindex++) { -+ br = au_sbr(sb, bindex); -+ br_sysfs = br->br_sysfs; -+ snprintf(br_sysfs[AuBrSysfs_BR].name, sizeof(br_sysfs->name), -+ SysaufsBr_PREFIX "%d", bindex); -+ snprintf(br_sysfs[AuBrSysfs_BRID].name, sizeof(br_sysfs->name), -+ SysaufsBrid_PREFIX "%d", bindex); -+ for (i = 0; i < ARRAY_SIZE(br->br_sysfs); i++) { -+ err = sysfs_create_file(kobj, &br_sysfs->attr); -+ if (unlikely(err)) -+ pr_warn("failed %s under sysfs(%d)\n", -+ br_sysfs->name, err); -+ br_sysfs++; -+ } -+ } -+} -diff --git a/fs/aufs/sysrq.c b/fs/aufs/sysrq.c -new file mode 100644 -index 000000000000..d51b95163e24 ---- /dev/null -+++ b/fs/aufs/sysrq.c -@@ -0,0 +1,136 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * magic sysrq handler -+ */ -+ -+/* #include */ -+#include -+#include "aufs.h" -+ -+/* ---------------------------------------------------------------------- */ -+ -+static void sysrq_sb(struct super_block *sb) -+{ -+ char *plevel; -+ struct au_sbinfo *sbinfo; -+ struct file *file; -+ struct hlist_bl_head *files; -+ struct hlist_bl_node *pos; -+ struct au_finfo *finfo; -+ struct inode *i; -+ -+ plevel = au_plevel; -+ au_plevel = KERN_WARNING; -+ -+ /* since we define pr_fmt, call printk directly */ -+#define pr(str) printk(KERN_WARNING AUFS_NAME ": " str) -+ -+ sbinfo = au_sbi(sb); -+ printk(KERN_WARNING "si=%lx\n", sysaufs_si_id(sbinfo)); -+ pr("superblock\n"); -+ au_dpri_sb(sb); -+ -+#if 0 /* reserved */ -+ do { -+ int err, i, j, ndentry; -+ struct au_dcsub_pages dpages; -+ struct au_dpage *dpage; -+ -+ err = au_dpages_init(&dpages, GFP_ATOMIC); -+ if (unlikely(err)) -+ break; -+ err = au_dcsub_pages(&dpages, sb->s_root, NULL, NULL); -+ if (!err) -+ for (i = 0; i < dpages.ndpage; i++) { -+ dpage = dpages.dpages + i; -+ ndentry = dpage->ndentry; -+ for (j = 0; j < ndentry; j++) -+ au_dpri_dentry(dpage->dentries[j]); -+ } -+ au_dpages_free(&dpages); -+ } while (0); -+#endif -+ -+ pr("isolated inode\n"); -+ spin_lock(&sb->s_inode_list_lock); -+ list_for_each_entry(i, &sb->s_inodes, i_sb_list) { -+ spin_lock(&i->i_lock); -+ if (hlist_empty(&i->i_dentry)) -+ au_dpri_inode(i); -+ spin_unlock(&i->i_lock); -+ } -+ spin_unlock(&sb->s_inode_list_lock); -+ -+ pr("files\n"); -+ files = &au_sbi(sb)->si_files; -+ hlist_bl_lock(files); -+ hlist_bl_for_each_entry(finfo, pos, files, fi_hlist) { -+ umode_t mode; -+ -+ file = finfo->fi_file; -+ mode = file_inode(file)->i_mode; -+ if (!special_file(mode)) -+ au_dpri_file(file); -+ } -+ hlist_bl_unlock(files); -+ pr("done\n"); -+ -+#undef pr -+ au_plevel = plevel; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* module parameter */ -+static char *aufs_sysrq_key = "a"; -+module_param_named(sysrq, aufs_sysrq_key, charp, 0444); -+MODULE_PARM_DESC(sysrq, "MagicSysRq key for " AUFS_NAME); -+ -+static void au_sysrq(int key __maybe_unused) -+{ -+ struct au_sbinfo *sbinfo; -+ struct hlist_bl_node *pos; -+ -+ lockdep_off(); -+ au_sbilist_lock(); -+ hlist_bl_for_each_entry(sbinfo, pos, &au_sbilist, si_list) -+ sysrq_sb(sbinfo->si_sb); -+ au_sbilist_unlock(); -+ lockdep_on(); -+} -+ -+static struct sysrq_key_op au_sysrq_op = { -+ .handler = au_sysrq, -+ .help_msg = "Aufs", -+ .action_msg = "Aufs", -+ .enable_mask = SYSRQ_ENABLE_DUMP -+}; -+ -+/* ---------------------------------------------------------------------- */ -+ -+int __init au_sysrq_init(void) -+{ -+ int err; -+ char key; -+ -+ err = -1; -+ key = *aufs_sysrq_key; -+ if ('a' <= key && key <= 'z') -+ err = register_sysrq_key(key, &au_sysrq_op); -+ if (unlikely(err)) -+ pr_err("err %d, sysrq=%c\n", err, key); -+ return err; -+} -+ -+void au_sysrq_fin(void) -+{ -+ int err; -+ -+ err = unregister_sysrq_key(*aufs_sysrq_key, &au_sysrq_op); -+ if (unlikely(err)) -+ pr_err("err %d (ignored)\n", err); -+} -diff --git a/fs/aufs/vdir.c b/fs/aufs/vdir.c -new file mode 100644 -index 000000000000..6cc7ecf0b0e1 ---- /dev/null -+++ b/fs/aufs/vdir.c -@@ -0,0 +1,883 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * virtual or vertical directory -+ */ -+ -+#include -+#include "aufs.h" -+ -+static unsigned int calc_size(int nlen) -+{ -+ return ALIGN(sizeof(struct au_vdir_de) + nlen, sizeof(ino_t)); -+} -+ -+static int set_deblk_end(union au_vdir_deblk_p *p, -+ union au_vdir_deblk_p *deblk_end) -+{ -+ if (calc_size(0) <= deblk_end->deblk - p->deblk) { -+ p->de->de_str.len = 0; -+ /* smp_mb(); */ -+ return 0; -+ } -+ return -1; /* error */ -+} -+ -+/* returns true or false */ -+static int is_deblk_end(union au_vdir_deblk_p *p, -+ union au_vdir_deblk_p *deblk_end) -+{ -+ if (calc_size(0) <= deblk_end->deblk - p->deblk) -+ return !p->de->de_str.len; -+ return 1; -+} -+ -+static unsigned char *last_deblk(struct au_vdir *vdir) -+{ -+ return vdir->vd_deblk[vdir->vd_nblk - 1]; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* estimate the appropriate size for name hash table */ -+unsigned int au_rdhash_est(loff_t sz) -+{ -+ unsigned int n; -+ -+ n = UINT_MAX; -+ sz >>= 10; -+ if (sz < n) -+ n = sz; -+ if (sz < AUFS_RDHASH_DEF) -+ n = AUFS_RDHASH_DEF; -+ /* pr_info("n %u\n", n); */ -+ return n; -+} -+ -+/* -+ * the allocated memory has to be freed by -+ * au_nhash_wh_free() or au_nhash_de_free(). -+ */ -+int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp) -+{ -+ struct hlist_head *head; -+ unsigned int u; -+ size_t sz; -+ -+ sz = sizeof(*nhash->nh_head) * num_hash; -+ head = kmalloc(sz, gfp); -+ if (head) { -+ nhash->nh_num = num_hash; -+ nhash->nh_head = head; -+ for (u = 0; u < num_hash; u++) -+ INIT_HLIST_HEAD(head++); -+ return 0; /* success */ -+ } -+ -+ return -ENOMEM; -+} -+ -+static void nhash_count(struct hlist_head *head) -+{ -+#if 0 /* debugging */ -+ unsigned long n; -+ struct hlist_node *pos; -+ -+ n = 0; -+ hlist_for_each(pos, head) -+ n++; -+ pr_info("%lu\n", n); -+#endif -+} -+ -+static void au_nhash_wh_do_free(struct hlist_head *head) -+{ -+ struct au_vdir_wh *pos; -+ struct hlist_node *node; -+ -+ hlist_for_each_entry_safe(pos, node, head, wh_hash) -+ au_kfree_rcu(pos); -+} -+ -+static void au_nhash_de_do_free(struct hlist_head *head) -+{ -+ struct au_vdir_dehstr *pos; -+ struct hlist_node *node; -+ -+ hlist_for_each_entry_safe(pos, node, head, hash) -+ au_cache_free_vdir_dehstr(pos); -+} -+ -+static void au_nhash_do_free(struct au_nhash *nhash, -+ void (*free)(struct hlist_head *head)) -+{ -+ unsigned int n; -+ struct hlist_head *head; -+ -+ n = nhash->nh_num; -+ if (!n) -+ return; -+ -+ head = nhash->nh_head; -+ while (n-- > 0) { -+ nhash_count(head); -+ free(head++); -+ } -+ au_kfree_try_rcu(nhash->nh_head); -+} -+ -+void au_nhash_wh_free(struct au_nhash *whlist) -+{ -+ au_nhash_do_free(whlist, au_nhash_wh_do_free); -+} -+ -+static void au_nhash_de_free(struct au_nhash *delist) -+{ -+ au_nhash_do_free(delist, au_nhash_de_do_free); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt, -+ int limit) -+{ -+ int num; -+ unsigned int u, n; -+ struct hlist_head *head; -+ struct au_vdir_wh *pos; -+ -+ num = 0; -+ n = whlist->nh_num; -+ head = whlist->nh_head; -+ for (u = 0; u < n; u++, head++) -+ hlist_for_each_entry(pos, head, wh_hash) -+ if (pos->wh_bindex == btgt && ++num > limit) -+ return 1; -+ return 0; -+} -+ -+static struct hlist_head *au_name_hash(struct au_nhash *nhash, -+ unsigned char *name, -+ unsigned int len) -+{ -+ unsigned int v; -+ /* const unsigned int magic_bit = 12; */ -+ -+ AuDebugOn(!nhash->nh_num || !nhash->nh_head); -+ -+ v = 0; -+ if (len > 8) -+ len = 8; -+ while (len--) -+ v += *name++; -+ /* v = hash_long(v, magic_bit); */ -+ v %= nhash->nh_num; -+ return nhash->nh_head + v; -+} -+ -+static int au_nhash_test_name(struct au_vdir_destr *str, const char *name, -+ int nlen) -+{ -+ return str->len == nlen && !memcmp(str->name, name, nlen); -+} -+ -+/* returns found or not */ -+int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen) -+{ -+ struct hlist_head *head; -+ struct au_vdir_wh *pos; -+ struct au_vdir_destr *str; -+ -+ head = au_name_hash(whlist, name, nlen); -+ hlist_for_each_entry(pos, head, wh_hash) { -+ str = &pos->wh_str; -+ AuDbg("%.*s\n", str->len, str->name); -+ if (au_nhash_test_name(str, name, nlen)) -+ return 1; -+ } -+ return 0; -+} -+ -+/* returns found(true) or not */ -+static int test_known(struct au_nhash *delist, char *name, int nlen) -+{ -+ struct hlist_head *head; -+ struct au_vdir_dehstr *pos; -+ struct au_vdir_destr *str; -+ -+ head = au_name_hash(delist, name, nlen); -+ hlist_for_each_entry(pos, head, hash) { -+ str = pos->str; -+ AuDbg("%.*s\n", str->len, str->name); -+ if (au_nhash_test_name(str, name, nlen)) -+ return 1; -+ } -+ return 0; -+} -+ -+static void au_shwh_init_wh(struct au_vdir_wh *wh, ino_t ino, -+ unsigned char d_type) -+{ -+#ifdef CONFIG_AUFS_SHWH -+ wh->wh_ino = ino; -+ wh->wh_type = d_type; -+#endif -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino, -+ unsigned int d_type, aufs_bindex_t bindex, -+ unsigned char shwh) -+{ -+ int err; -+ struct au_vdir_destr *str; -+ struct au_vdir_wh *wh; -+ -+ AuDbg("%.*s\n", nlen, name); -+ AuDebugOn(!whlist->nh_num || !whlist->nh_head); -+ -+ err = -ENOMEM; -+ wh = kmalloc(sizeof(*wh) + nlen, GFP_NOFS); -+ if (unlikely(!wh)) -+ goto out; -+ -+ err = 0; -+ wh->wh_bindex = bindex; -+ if (shwh) -+ au_shwh_init_wh(wh, ino, d_type); -+ str = &wh->wh_str; -+ str->len = nlen; -+ memcpy(str->name, name, nlen); -+ hlist_add_head(&wh->wh_hash, au_name_hash(whlist, name, nlen)); -+ /* smp_mb(); */ -+ -+out: -+ return err; -+} -+ -+static int append_deblk(struct au_vdir *vdir) -+{ -+ int err; -+ unsigned long ul; -+ const unsigned int deblk_sz = vdir->vd_deblk_sz; -+ union au_vdir_deblk_p p, deblk_end; -+ unsigned char **o; -+ -+ err = -ENOMEM; -+ o = au_krealloc(vdir->vd_deblk, sizeof(*o) * (vdir->vd_nblk + 1), -+ GFP_NOFS, /*may_shrink*/0); -+ if (unlikely(!o)) -+ goto out; -+ -+ vdir->vd_deblk = o; -+ p.deblk = kmalloc(deblk_sz, GFP_NOFS); -+ if (p.deblk) { -+ ul = vdir->vd_nblk++; -+ vdir->vd_deblk[ul] = p.deblk; -+ vdir->vd_last.ul = ul; -+ vdir->vd_last.p.deblk = p.deblk; -+ deblk_end.deblk = p.deblk + deblk_sz; -+ err = set_deblk_end(&p, &deblk_end); -+ } -+ -+out: -+ return err; -+} -+ -+static int append_de(struct au_vdir *vdir, char *name, int nlen, ino_t ino, -+ unsigned int d_type, struct au_nhash *delist) -+{ -+ int err; -+ unsigned int sz; -+ const unsigned int deblk_sz = vdir->vd_deblk_sz; -+ union au_vdir_deblk_p p, *room, deblk_end; -+ struct au_vdir_dehstr *dehstr; -+ -+ p.deblk = last_deblk(vdir); -+ deblk_end.deblk = p.deblk + deblk_sz; -+ room = &vdir->vd_last.p; -+ AuDebugOn(room->deblk < p.deblk || deblk_end.deblk <= room->deblk -+ || !is_deblk_end(room, &deblk_end)); -+ -+ sz = calc_size(nlen); -+ if (unlikely(sz > deblk_end.deblk - room->deblk)) { -+ err = append_deblk(vdir); -+ if (unlikely(err)) -+ goto out; -+ -+ p.deblk = last_deblk(vdir); -+ deblk_end.deblk = p.deblk + deblk_sz; -+ /* smp_mb(); */ -+ AuDebugOn(room->deblk != p.deblk); -+ } -+ -+ err = -ENOMEM; -+ dehstr = au_cache_alloc_vdir_dehstr(); -+ if (unlikely(!dehstr)) -+ goto out; -+ -+ dehstr->str = &room->de->de_str; -+ hlist_add_head(&dehstr->hash, au_name_hash(delist, name, nlen)); -+ room->de->de_ino = ino; -+ room->de->de_type = d_type; -+ room->de->de_str.len = nlen; -+ memcpy(room->de->de_str.name, name, nlen); -+ -+ err = 0; -+ room->deblk += sz; -+ if (unlikely(set_deblk_end(room, &deblk_end))) -+ err = append_deblk(vdir); -+ /* smp_mb(); */ -+ -+out: -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+void au_vdir_free(struct au_vdir *vdir) -+{ -+ unsigned char **deblk; -+ -+ deblk = vdir->vd_deblk; -+ while (vdir->vd_nblk--) -+ au_kfree_try_rcu(*deblk++); -+ au_kfree_try_rcu(vdir->vd_deblk); -+ au_cache_free_vdir(vdir); -+} -+ -+static struct au_vdir *alloc_vdir(struct file *file) -+{ -+ struct au_vdir *vdir; -+ struct super_block *sb; -+ int err; -+ -+ sb = file->f_path.dentry->d_sb; -+ SiMustAnyLock(sb); -+ -+ err = -ENOMEM; -+ vdir = au_cache_alloc_vdir(); -+ if (unlikely(!vdir)) -+ goto out; -+ -+ vdir->vd_deblk = kzalloc(sizeof(*vdir->vd_deblk), GFP_NOFS); -+ if (unlikely(!vdir->vd_deblk)) -+ goto out_free; -+ -+ vdir->vd_deblk_sz = au_sbi(sb)->si_rdblk; -+ if (!vdir->vd_deblk_sz) { -+ /* estimate the appropriate size for deblk */ -+ vdir->vd_deblk_sz = au_dir_size(file, /*dentry*/NULL); -+ /* pr_info("vd_deblk_sz %u\n", vdir->vd_deblk_sz); */ -+ } -+ vdir->vd_nblk = 0; -+ vdir->vd_version = 0; -+ vdir->vd_jiffy = 0; -+ err = append_deblk(vdir); -+ if (!err) -+ return vdir; /* success */ -+ -+ au_kfree_try_rcu(vdir->vd_deblk); -+ -+out_free: -+ au_cache_free_vdir(vdir); -+out: -+ vdir = ERR_PTR(err); -+ return vdir; -+} -+ -+static int reinit_vdir(struct au_vdir *vdir) -+{ -+ int err; -+ union au_vdir_deblk_p p, deblk_end; -+ -+ while (vdir->vd_nblk > 1) { -+ au_kfree_try_rcu(vdir->vd_deblk[vdir->vd_nblk - 1]); -+ /* vdir->vd_deblk[vdir->vd_nblk - 1] = NULL; */ -+ vdir->vd_nblk--; -+ } -+ p.deblk = vdir->vd_deblk[0]; -+ deblk_end.deblk = p.deblk + vdir->vd_deblk_sz; -+ err = set_deblk_end(&p, &deblk_end); -+ /* keep vd_dblk_sz */ -+ vdir->vd_last.ul = 0; -+ vdir->vd_last.p.deblk = vdir->vd_deblk[0]; -+ vdir->vd_version = 0; -+ vdir->vd_jiffy = 0; -+ /* smp_mb(); */ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+#define AuFillVdir_CALLED 1 -+#define AuFillVdir_WHABLE (1 << 1) -+#define AuFillVdir_SHWH (1 << 2) -+#define au_ftest_fillvdir(flags, name) ((flags) & AuFillVdir_##name) -+#define au_fset_fillvdir(flags, name) \ -+ do { (flags) |= AuFillVdir_##name; } while (0) -+#define au_fclr_fillvdir(flags, name) \ -+ do { (flags) &= ~AuFillVdir_##name; } while (0) -+ -+#ifndef CONFIG_AUFS_SHWH -+#undef AuFillVdir_SHWH -+#define AuFillVdir_SHWH 0 -+#endif -+ -+struct fillvdir_arg { -+ struct dir_context ctx; -+ struct file *file; -+ struct au_vdir *vdir; -+ struct au_nhash delist; -+ struct au_nhash whlist; -+ aufs_bindex_t bindex; -+ unsigned int flags; -+ int err; -+}; -+ -+static int fillvdir(struct dir_context *ctx, const char *__name, int nlen, -+ loff_t offset __maybe_unused, u64 h_ino, -+ unsigned int d_type) -+{ -+ struct fillvdir_arg *arg = container_of(ctx, struct fillvdir_arg, ctx); -+ char *name = (void *)__name; -+ struct super_block *sb; -+ ino_t ino; -+ const unsigned char shwh = !!au_ftest_fillvdir(arg->flags, SHWH); -+ -+ arg->err = 0; -+ sb = arg->file->f_path.dentry->d_sb; -+ au_fset_fillvdir(arg->flags, CALLED); -+ /* smp_mb(); */ -+ if (nlen <= AUFS_WH_PFX_LEN -+ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) { -+ if (test_known(&arg->delist, name, nlen) -+ || au_nhash_test_known_wh(&arg->whlist, name, nlen)) -+ goto out; /* already exists or whiteouted */ -+ -+ arg->err = au_ino(sb, arg->bindex, h_ino, d_type, &ino); -+ if (!arg->err) { -+ if (unlikely(nlen > AUFS_MAX_NAMELEN)) -+ d_type = DT_UNKNOWN; -+ arg->err = append_de(arg->vdir, name, nlen, ino, -+ d_type, &arg->delist); -+ } -+ } else if (au_ftest_fillvdir(arg->flags, WHABLE)) { -+ name += AUFS_WH_PFX_LEN; -+ nlen -= AUFS_WH_PFX_LEN; -+ if (au_nhash_test_known_wh(&arg->whlist, name, nlen)) -+ goto out; /* already whiteouted */ -+ -+ ino = 0; /* just to suppress a warning */ -+ if (shwh) -+ arg->err = au_wh_ino(sb, arg->bindex, h_ino, d_type, -+ &ino); -+ if (!arg->err) { -+ if (nlen <= AUFS_MAX_NAMELEN + AUFS_WH_PFX_LEN) -+ d_type = DT_UNKNOWN; -+ arg->err = au_nhash_append_wh -+ (&arg->whlist, name, nlen, ino, d_type, -+ arg->bindex, shwh); -+ } -+ } -+ -+out: -+ if (!arg->err) -+ arg->vdir->vd_jiffy = jiffies; -+ /* smp_mb(); */ -+ AuTraceErr(arg->err); -+ return arg->err; -+} -+ -+static int au_handle_shwh(struct super_block *sb, struct au_vdir *vdir, -+ struct au_nhash *whlist, struct au_nhash *delist) -+{ -+#ifdef CONFIG_AUFS_SHWH -+ int err; -+ unsigned int nh, u; -+ struct hlist_head *head; -+ struct au_vdir_wh *pos; -+ struct hlist_node *n; -+ char *p, *o; -+ struct au_vdir_destr *destr; -+ -+ AuDebugOn(!au_opt_test(au_mntflags(sb), SHWH)); -+ -+ err = -ENOMEM; -+ o = p = (void *)__get_free_page(GFP_NOFS); -+ if (unlikely(!p)) -+ goto out; -+ -+ err = 0; -+ nh = whlist->nh_num; -+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN); -+ p += AUFS_WH_PFX_LEN; -+ for (u = 0; u < nh; u++) { -+ head = whlist->nh_head + u; -+ hlist_for_each_entry_safe(pos, n, head, wh_hash) { -+ destr = &pos->wh_str; -+ memcpy(p, destr->name, destr->len); -+ err = append_de(vdir, o, destr->len + AUFS_WH_PFX_LEN, -+ pos->wh_ino, pos->wh_type, delist); -+ if (unlikely(err)) -+ break; -+ } -+ } -+ -+ free_page((unsigned long)o); -+ -+out: -+ AuTraceErr(err); -+ return err; -+#else -+ return 0; -+#endif -+} -+ -+static int au_do_read_vdir(struct fillvdir_arg *arg) -+{ -+ int err; -+ unsigned int rdhash; -+ loff_t offset; -+ aufs_bindex_t bbot, bindex, btop; -+ unsigned char shwh; -+ struct file *hf, *file; -+ struct super_block *sb; -+ -+ file = arg->file; -+ sb = file->f_path.dentry->d_sb; -+ SiMustAnyLock(sb); -+ -+ rdhash = au_sbi(sb)->si_rdhash; -+ if (!rdhash) -+ rdhash = au_rdhash_est(au_dir_size(file, /*dentry*/NULL)); -+ err = au_nhash_alloc(&arg->delist, rdhash, GFP_NOFS); -+ if (unlikely(err)) -+ goto out; -+ err = au_nhash_alloc(&arg->whlist, rdhash, GFP_NOFS); -+ if (unlikely(err)) -+ goto out_delist; -+ -+ err = 0; -+ arg->flags = 0; -+ shwh = 0; -+ if (au_opt_test(au_mntflags(sb), SHWH)) { -+ shwh = 1; -+ au_fset_fillvdir(arg->flags, SHWH); -+ } -+ btop = au_fbtop(file); -+ bbot = au_fbbot_dir(file); -+ for (bindex = btop; !err && bindex <= bbot; bindex++) { -+ hf = au_hf_dir(file, bindex); -+ if (!hf) -+ continue; -+ -+ offset = vfsub_llseek(hf, 0, SEEK_SET); -+ err = offset; -+ if (unlikely(offset)) -+ break; -+ -+ arg->bindex = bindex; -+ au_fclr_fillvdir(arg->flags, WHABLE); -+ if (shwh -+ || (bindex != bbot -+ && au_br_whable(au_sbr_perm(sb, bindex)))) -+ au_fset_fillvdir(arg->flags, WHABLE); -+ do { -+ arg->err = 0; -+ au_fclr_fillvdir(arg->flags, CALLED); -+ /* smp_mb(); */ -+ err = vfsub_iterate_dir(hf, &arg->ctx); -+ if (err >= 0) -+ err = arg->err; -+ } while (!err && au_ftest_fillvdir(arg->flags, CALLED)); -+ -+ /* -+ * dir_relax() may be good for concurrency, but aufs should not -+ * use it since it will cause a lockdep problem. -+ */ -+ } -+ -+ if (!err && shwh) -+ err = au_handle_shwh(sb, arg->vdir, &arg->whlist, &arg->delist); -+ -+ au_nhash_wh_free(&arg->whlist); -+ -+out_delist: -+ au_nhash_de_free(&arg->delist); -+out: -+ return err; -+} -+ -+static int read_vdir(struct file *file, int may_read) -+{ -+ int err; -+ unsigned long expire; -+ unsigned char do_read; -+ struct fillvdir_arg arg = { -+ .ctx = { -+ .actor = fillvdir -+ } -+ }; -+ struct inode *inode; -+ struct au_vdir *vdir, *allocated; -+ -+ err = 0; -+ inode = file_inode(file); -+ IMustLock(inode); -+ IiMustWriteLock(inode); -+ SiMustAnyLock(inode->i_sb); -+ -+ allocated = NULL; -+ do_read = 0; -+ expire = au_sbi(inode->i_sb)->si_rdcache; -+ vdir = au_ivdir(inode); -+ if (!vdir) { -+ do_read = 1; -+ vdir = alloc_vdir(file); -+ err = PTR_ERR(vdir); -+ if (IS_ERR(vdir)) -+ goto out; -+ err = 0; -+ allocated = vdir; -+ } else if (may_read -+ && (!inode_eq_iversion(inode, vdir->vd_version) -+ || time_after(jiffies, vdir->vd_jiffy + expire))) { -+ do_read = 1; -+ err = reinit_vdir(vdir); -+ if (unlikely(err)) -+ goto out; -+ } -+ -+ if (!do_read) -+ return 0; /* success */ -+ -+ arg.file = file; -+ arg.vdir = vdir; -+ err = au_do_read_vdir(&arg); -+ if (!err) { -+ /* file->f_pos = 0; */ /* todo: ctx->pos? */ -+ vdir->vd_version = inode_query_iversion(inode); -+ vdir->vd_last.ul = 0; -+ vdir->vd_last.p.deblk = vdir->vd_deblk[0]; -+ if (allocated) -+ au_set_ivdir(inode, allocated); -+ } else if (allocated) -+ au_vdir_free(allocated); -+ -+out: -+ return err; -+} -+ -+static int copy_vdir(struct au_vdir *tgt, struct au_vdir *src) -+{ -+ int err, rerr; -+ unsigned long ul, n; -+ const unsigned int deblk_sz = src->vd_deblk_sz; -+ -+ AuDebugOn(tgt->vd_nblk != 1); -+ -+ err = -ENOMEM; -+ if (tgt->vd_nblk < src->vd_nblk) { -+ unsigned char **p; -+ -+ p = au_krealloc(tgt->vd_deblk, sizeof(*p) * src->vd_nblk, -+ GFP_NOFS, /*may_shrink*/0); -+ if (unlikely(!p)) -+ goto out; -+ tgt->vd_deblk = p; -+ } -+ -+ if (tgt->vd_deblk_sz != deblk_sz) { -+ unsigned char *p; -+ -+ tgt->vd_deblk_sz = deblk_sz; -+ p = au_krealloc(tgt->vd_deblk[0], deblk_sz, GFP_NOFS, -+ /*may_shrink*/1); -+ if (unlikely(!p)) -+ goto out; -+ tgt->vd_deblk[0] = p; -+ } -+ memcpy(tgt->vd_deblk[0], src->vd_deblk[0], deblk_sz); -+ tgt->vd_version = src->vd_version; -+ tgt->vd_jiffy = src->vd_jiffy; -+ -+ n = src->vd_nblk; -+ for (ul = 1; ul < n; ul++) { -+ tgt->vd_deblk[ul] = kmemdup(src->vd_deblk[ul], deblk_sz, -+ GFP_NOFS); -+ if (unlikely(!tgt->vd_deblk[ul])) -+ goto out; -+ tgt->vd_nblk++; -+ } -+ tgt->vd_nblk = n; -+ tgt->vd_last.ul = tgt->vd_last.ul; -+ tgt->vd_last.p.deblk = tgt->vd_deblk[tgt->vd_last.ul]; -+ tgt->vd_last.p.deblk += src->vd_last.p.deblk -+ - src->vd_deblk[src->vd_last.ul]; -+ /* smp_mb(); */ -+ return 0; /* success */ -+ -+out: -+ rerr = reinit_vdir(tgt); -+ BUG_ON(rerr); -+ return err; -+} -+ -+int au_vdir_init(struct file *file) -+{ -+ int err; -+ struct inode *inode; -+ struct au_vdir *vdir_cache, *allocated; -+ -+ /* test file->f_pos here instead of ctx->pos */ -+ err = read_vdir(file, !file->f_pos); -+ if (unlikely(err)) -+ goto out; -+ -+ allocated = NULL; -+ vdir_cache = au_fvdir_cache(file); -+ if (!vdir_cache) { -+ vdir_cache = alloc_vdir(file); -+ err = PTR_ERR(vdir_cache); -+ if (IS_ERR(vdir_cache)) -+ goto out; -+ allocated = vdir_cache; -+ } else if (!file->f_pos && vdir_cache->vd_version != file->f_version) { -+ /* test file->f_pos here instead of ctx->pos */ -+ err = reinit_vdir(vdir_cache); -+ if (unlikely(err)) -+ goto out; -+ } else -+ return 0; /* success */ -+ -+ inode = file_inode(file); -+ err = copy_vdir(vdir_cache, au_ivdir(inode)); -+ if (!err) { -+ file->f_version = inode_query_iversion(inode); -+ if (allocated) -+ au_set_fvdir_cache(file, allocated); -+ } else if (allocated) -+ au_vdir_free(allocated); -+ -+out: -+ return err; -+} -+ -+static loff_t calc_offset(struct au_vdir *vdir) -+{ -+ loff_t offset; -+ union au_vdir_deblk_p p; -+ -+ p.deblk = vdir->vd_deblk[vdir->vd_last.ul]; -+ offset = vdir->vd_last.p.deblk - p.deblk; -+ offset += vdir->vd_deblk_sz * vdir->vd_last.ul; -+ return offset; -+} -+ -+/* returns true or false */ -+static int seek_vdir(struct file *file, struct dir_context *ctx) -+{ -+ int valid; -+ unsigned int deblk_sz; -+ unsigned long ul, n; -+ loff_t offset; -+ union au_vdir_deblk_p p, deblk_end; -+ struct au_vdir *vdir_cache; -+ -+ valid = 1; -+ vdir_cache = au_fvdir_cache(file); -+ offset = calc_offset(vdir_cache); -+ AuDbg("offset %lld\n", offset); -+ if (ctx->pos == offset) -+ goto out; -+ -+ vdir_cache->vd_last.ul = 0; -+ vdir_cache->vd_last.p.deblk = vdir_cache->vd_deblk[0]; -+ if (!ctx->pos) -+ goto out; -+ -+ valid = 0; -+ deblk_sz = vdir_cache->vd_deblk_sz; -+ ul = div64_u64(ctx->pos, deblk_sz); -+ AuDbg("ul %lu\n", ul); -+ if (ul >= vdir_cache->vd_nblk) -+ goto out; -+ -+ n = vdir_cache->vd_nblk; -+ for (; ul < n; ul++) { -+ p.deblk = vdir_cache->vd_deblk[ul]; -+ deblk_end.deblk = p.deblk + deblk_sz; -+ offset = ul; -+ offset *= deblk_sz; -+ while (!is_deblk_end(&p, &deblk_end) && offset < ctx->pos) { -+ unsigned int l; -+ -+ l = calc_size(p.de->de_str.len); -+ offset += l; -+ p.deblk += l; -+ } -+ if (!is_deblk_end(&p, &deblk_end)) { -+ valid = 1; -+ vdir_cache->vd_last.ul = ul; -+ vdir_cache->vd_last.p = p; -+ break; -+ } -+ } -+ -+out: -+ /* smp_mb(); */ -+ if (!valid) -+ AuDbg("valid %d\n", !valid); -+ return valid; -+} -+ -+int au_vdir_fill_de(struct file *file, struct dir_context *ctx) -+{ -+ unsigned int l, deblk_sz; -+ union au_vdir_deblk_p deblk_end; -+ struct au_vdir *vdir_cache; -+ struct au_vdir_de *de; -+ -+ if (!seek_vdir(file, ctx)) -+ return 0; -+ -+ vdir_cache = au_fvdir_cache(file); -+ deblk_sz = vdir_cache->vd_deblk_sz; -+ while (1) { -+ deblk_end.deblk = vdir_cache->vd_deblk[vdir_cache->vd_last.ul]; -+ deblk_end.deblk += deblk_sz; -+ while (!is_deblk_end(&vdir_cache->vd_last.p, &deblk_end)) { -+ de = vdir_cache->vd_last.p.de; -+ AuDbg("%.*s, off%lld, i%lu, dt%d\n", -+ de->de_str.len, de->de_str.name, ctx->pos, -+ (unsigned long)de->de_ino, de->de_type); -+ if (unlikely(!dir_emit(ctx, de->de_str.name, -+ de->de_str.len, de->de_ino, -+ de->de_type))) { -+ /* todo: ignore the error caused by udba? */ -+ /* return err; */ -+ return 0; -+ } -+ -+ l = calc_size(de->de_str.len); -+ vdir_cache->vd_last.p.deblk += l; -+ ctx->pos += l; -+ } -+ if (vdir_cache->vd_last.ul < vdir_cache->vd_nblk - 1) { -+ vdir_cache->vd_last.ul++; -+ vdir_cache->vd_last.p.deblk -+ = vdir_cache->vd_deblk[vdir_cache->vd_last.ul]; -+ ctx->pos = deblk_sz * vdir_cache->vd_last.ul; -+ continue; -+ } -+ break; -+ } -+ -+ /* smp_mb(); */ -+ return 0; -+} -diff --git a/fs/aufs/vfsub.c b/fs/aufs/vfsub.c -new file mode 100644 -index 000000000000..3217455dc21b ---- /dev/null -+++ b/fs/aufs/vfsub.c -@@ -0,0 +1,882 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * sub-routines for VFS -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include "aufs.h" -+ -+#ifdef CONFIG_AUFS_BR_FUSE -+int vfsub_test_mntns(struct vfsmount *mnt, struct super_block *h_sb) -+{ -+ if (!au_test_fuse(h_sb) || !au_userns) -+ return 0; -+ -+ return is_current_mnt_ns(mnt) ? 0 : -EACCES; -+} -+#endif -+ -+int vfsub_sync_filesystem(struct super_block *h_sb, int wait) -+{ -+ int err; -+ -+ lockdep_off(); -+ down_read(&h_sb->s_umount); -+ err = __sync_filesystem(h_sb, wait); -+ up_read(&h_sb->s_umount); -+ lockdep_on(); -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+int vfsub_update_h_iattr(struct path *h_path, int *did) -+{ -+ int err; -+ struct kstat st; -+ struct super_block *h_sb; -+ -+ /* for remote fs, leave work for its getattr or d_revalidate */ -+ /* for bad i_attr fs, handle them in aufs_getattr() */ -+ /* still some fs may acquire i_mutex. we need to skip them */ -+ err = 0; -+ if (!did) -+ did = &err; -+ h_sb = h_path->dentry->d_sb; -+ *did = (!au_test_fs_remote(h_sb) && au_test_fs_refresh_iattr(h_sb)); -+ if (*did) -+ err = vfsub_getattr(h_path, &st); -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct file *vfsub_dentry_open(struct path *path, int flags) -+{ -+ return dentry_open(path, flags /* | __FMODE_NONOTIFY */, -+ current_cred()); -+} -+ -+struct file *vfsub_filp_open(const char *path, int oflags, int mode) -+{ -+ struct file *file; -+ -+ lockdep_off(); -+ file = filp_open(path, -+ oflags /* | __FMODE_NONOTIFY */, -+ mode); -+ lockdep_on(); -+ if (IS_ERR(file)) -+ goto out; -+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/ -+ -+out: -+ return file; -+} -+ -+/* -+ * Ideally this function should call VFS:do_last() in order to keep all its -+ * checkings. But it is very hard for aufs to regenerate several VFS internal -+ * structure such as nameidata. This is a second (or third) best approach. -+ * cf. linux/fs/namei.c:do_last(), lookup_open() and atomic_open(). -+ */ -+int vfsub_atomic_open(struct inode *dir, struct dentry *dentry, -+ struct vfsub_aopen_args *args) -+{ -+ int err; -+ struct au_branch *br = args->br; -+ struct file *file = args->file; -+ /* copied from linux/fs/namei.c:atomic_open() */ -+ struct dentry *const DENTRY_NOT_SET = (void *)-1UL; -+ -+ IMustLock(dir); -+ AuDebugOn(!dir->i_op->atomic_open); -+ -+ err = au_br_test_oflag(args->open_flag, br); -+ if (unlikely(err)) -+ goto out; -+ -+ au_lcnt_inc(&br->br_nfiles); -+ file->f_path.dentry = DENTRY_NOT_SET; -+ file->f_path.mnt = au_br_mnt(br); -+ AuDbg("%ps\n", dir->i_op->atomic_open); -+ err = dir->i_op->atomic_open(dir, dentry, file, args->open_flag, -+ args->create_mode); -+ if (unlikely(err < 0)) { -+ au_lcnt_dec(&br->br_nfiles); -+ goto out; -+ } -+ -+ /* temporary workaround for nfsv4 branch */ -+ if (au_test_nfs(dir->i_sb)) -+ nfs_mark_for_revalidate(dir); -+ -+ if (file->f_mode & FMODE_CREATED) -+ fsnotify_create(dir, dentry); -+ if (!(file->f_mode & FMODE_OPENED)) { -+ au_lcnt_dec(&br->br_nfiles); -+ goto out; -+ } -+ -+ /* todo: call VFS:may_open() here */ -+ /* todo: ima_file_check() too? */ -+ if (!err && (args->open_flag & __FMODE_EXEC)) -+ err = deny_write_access(file); -+ if (!err) -+ fsnotify_open(file); -+ else -+ au_lcnt_dec(&br->br_nfiles); -+ /* note that the file is created and still opened */ -+ -+out: -+ return err; -+} -+ -+int vfsub_kern_path(const char *name, unsigned int flags, struct path *path) -+{ -+ int err; -+ -+ err = kern_path(name, flags, path); -+ if (!err && d_is_positive(path->dentry)) -+ vfsub_update_h_iattr(path, /*did*/NULL); /*ignore*/ -+ return err; -+} -+ -+struct dentry *vfsub_lookup_one_len_unlocked(const char *name, -+ struct dentry *parent, int len) -+{ -+ struct path path = { -+ .mnt = NULL -+ }; -+ -+ path.dentry = lookup_one_len_unlocked(name, parent, len); -+ if (IS_ERR(path.dentry)) -+ goto out; -+ if (d_is_positive(path.dentry)) -+ vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/ -+ -+out: -+ AuTraceErrPtr(path.dentry); -+ return path.dentry; -+} -+ -+struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent, -+ int len) -+{ -+ struct path path = { -+ .mnt = NULL -+ }; -+ -+ /* VFS checks it too, but by WARN_ON_ONCE() */ -+ IMustLock(d_inode(parent)); -+ -+ path.dentry = lookup_one_len(name, parent, len); -+ if (IS_ERR(path.dentry)) -+ goto out; -+ if (d_is_positive(path.dentry)) -+ vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/ -+ -+out: -+ AuTraceErrPtr(path.dentry); -+ return path.dentry; -+} -+ -+void vfsub_call_lkup_one(void *args) -+{ -+ struct vfsub_lkup_one_args *a = args; -+ *a->errp = vfsub_lkup_one(a->name, a->parent); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1, -+ struct dentry *d2, struct au_hinode *hdir2) -+{ -+ struct dentry *d; -+ -+ lockdep_off(); -+ d = lock_rename(d1, d2); -+ lockdep_on(); -+ au_hn_suspend(hdir1); -+ if (hdir1 != hdir2) -+ au_hn_suspend(hdir2); -+ -+ return d; -+} -+ -+void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1, -+ struct dentry *d2, struct au_hinode *hdir2) -+{ -+ au_hn_resume(hdir1); -+ if (hdir1 != hdir2) -+ au_hn_resume(hdir2); -+ lockdep_off(); -+ unlock_rename(d1, d2); -+ lockdep_on(); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+int vfsub_create(struct inode *dir, struct path *path, int mode, bool want_excl) -+{ -+ int err; -+ struct dentry *d; -+ -+ IMustLock(dir); -+ -+ d = path->dentry; -+ path->dentry = d->d_parent; -+ err = security_path_mknod(path, d, mode, 0); -+ path->dentry = d; -+ if (unlikely(err)) -+ goto out; -+ -+ lockdep_off(); -+ err = vfs_create(dir, path->dentry, mode, want_excl); -+ lockdep_on(); -+ if (!err) { -+ struct path tmp = *path; -+ int did; -+ -+ vfsub_update_h_iattr(&tmp, &did); -+ if (did) { -+ tmp.dentry = path->dentry->d_parent; -+ vfsub_update_h_iattr(&tmp, /*did*/NULL); -+ } -+ /*ignore*/ -+ } -+ -+out: -+ return err; -+} -+ -+int vfsub_symlink(struct inode *dir, struct path *path, const char *symname) -+{ -+ int err; -+ struct dentry *d; -+ -+ IMustLock(dir); -+ -+ d = path->dentry; -+ path->dentry = d->d_parent; -+ err = security_path_symlink(path, d, symname); -+ path->dentry = d; -+ if (unlikely(err)) -+ goto out; -+ -+ lockdep_off(); -+ err = vfs_symlink(dir, path->dentry, symname); -+ lockdep_on(); -+ if (!err) { -+ struct path tmp = *path; -+ int did; -+ -+ vfsub_update_h_iattr(&tmp, &did); -+ if (did) { -+ tmp.dentry = path->dentry->d_parent; -+ vfsub_update_h_iattr(&tmp, /*did*/NULL); -+ } -+ /*ignore*/ -+ } -+ -+out: -+ return err; -+} -+ -+int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev) -+{ -+ int err; -+ struct dentry *d; -+ -+ IMustLock(dir); -+ -+ d = path->dentry; -+ path->dentry = d->d_parent; -+ err = security_path_mknod(path, d, mode, new_encode_dev(dev)); -+ path->dentry = d; -+ if (unlikely(err)) -+ goto out; -+ -+ lockdep_off(); -+ err = vfs_mknod(dir, path->dentry, mode, dev); -+ lockdep_on(); -+ if (!err) { -+ struct path tmp = *path; -+ int did; -+ -+ vfsub_update_h_iattr(&tmp, &did); -+ if (did) { -+ tmp.dentry = path->dentry->d_parent; -+ vfsub_update_h_iattr(&tmp, /*did*/NULL); -+ } -+ /*ignore*/ -+ } -+ -+out: -+ return err; -+} -+ -+static int au_test_nlink(struct inode *inode) -+{ -+ const unsigned int link_max = UINT_MAX >> 1; /* rough margin */ -+ -+ if (!au_test_fs_no_limit_nlink(inode->i_sb) -+ || inode->i_nlink < link_max) -+ return 0; -+ return -EMLINK; -+} -+ -+int vfsub_link(struct dentry *src_dentry, struct inode *dir, struct path *path, -+ struct inode **delegated_inode) -+{ -+ int err; -+ struct dentry *d; -+ -+ IMustLock(dir); -+ -+ err = au_test_nlink(d_inode(src_dentry)); -+ if (unlikely(err)) -+ return err; -+ -+ /* we don't call may_linkat() */ -+ d = path->dentry; -+ path->dentry = d->d_parent; -+ err = security_path_link(src_dentry, path, d); -+ path->dentry = d; -+ if (unlikely(err)) -+ goto out; -+ -+ lockdep_off(); -+ err = vfs_link(src_dentry, dir, path->dentry, delegated_inode); -+ lockdep_on(); -+ if (!err) { -+ struct path tmp = *path; -+ int did; -+ -+ /* fuse has different memory inode for the same inumber */ -+ vfsub_update_h_iattr(&tmp, &did); -+ if (did) { -+ tmp.dentry = path->dentry->d_parent; -+ vfsub_update_h_iattr(&tmp, /*did*/NULL); -+ tmp.dentry = src_dentry; -+ vfsub_update_h_iattr(&tmp, /*did*/NULL); -+ } -+ /*ignore*/ -+ } -+ -+out: -+ return err; -+} -+ -+int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry, -+ struct inode *dir, struct path *path, -+ struct inode **delegated_inode, unsigned int flags) -+{ -+ int err; -+ struct path tmp = { -+ .mnt = path->mnt -+ }; -+ struct dentry *d; -+ -+ IMustLock(dir); -+ IMustLock(src_dir); -+ -+ d = path->dentry; -+ path->dentry = d->d_parent; -+ tmp.dentry = src_dentry->d_parent; -+ err = security_path_rename(&tmp, src_dentry, path, d, /*flags*/0); -+ path->dentry = d; -+ if (unlikely(err)) -+ goto out; -+ -+ lockdep_off(); -+ err = vfs_rename(src_dir, src_dentry, dir, path->dentry, -+ delegated_inode, flags); -+ lockdep_on(); -+ if (!err) { -+ int did; -+ -+ tmp.dentry = d->d_parent; -+ vfsub_update_h_iattr(&tmp, &did); -+ if (did) { -+ tmp.dentry = src_dentry; -+ vfsub_update_h_iattr(&tmp, /*did*/NULL); -+ tmp.dentry = src_dentry->d_parent; -+ vfsub_update_h_iattr(&tmp, /*did*/NULL); -+ } -+ /*ignore*/ -+ } -+ -+out: -+ return err; -+} -+ -+int vfsub_mkdir(struct inode *dir, struct path *path, int mode) -+{ -+ int err; -+ struct dentry *d; -+ -+ IMustLock(dir); -+ -+ d = path->dentry; -+ path->dentry = d->d_parent; -+ err = security_path_mkdir(path, d, mode); -+ path->dentry = d; -+ if (unlikely(err)) -+ goto out; -+ -+ lockdep_off(); -+ err = vfs_mkdir(dir, path->dentry, mode); -+ lockdep_on(); -+ if (!err) { -+ struct path tmp = *path; -+ int did; -+ -+ vfsub_update_h_iattr(&tmp, &did); -+ if (did) { -+ tmp.dentry = path->dentry->d_parent; -+ vfsub_update_h_iattr(&tmp, /*did*/NULL); -+ } -+ /*ignore*/ -+ } -+ -+out: -+ return err; -+} -+ -+int vfsub_rmdir(struct inode *dir, struct path *path) -+{ -+ int err; -+ struct dentry *d; -+ -+ IMustLock(dir); -+ -+ d = path->dentry; -+ path->dentry = d->d_parent; -+ err = security_path_rmdir(path, d); -+ path->dentry = d; -+ if (unlikely(err)) -+ goto out; -+ -+ lockdep_off(); -+ err = vfs_rmdir(dir, path->dentry); -+ lockdep_on(); -+ if (!err) { -+ struct path tmp = { -+ .dentry = path->dentry->d_parent, -+ .mnt = path->mnt -+ }; -+ -+ vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/ -+ } -+ -+out: -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* todo: support mmap_sem? */ -+ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count, -+ loff_t *ppos) -+{ -+ ssize_t err; -+ -+ lockdep_off(); -+ err = vfs_read(file, ubuf, count, ppos); -+ lockdep_on(); -+ if (err >= 0) -+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/ -+ return err; -+} -+ -+/* todo: kernel_read()? */ -+ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count, -+ loff_t *ppos) -+{ -+ ssize_t err; -+ mm_segment_t oldfs; -+ union { -+ void *k; -+ char __user *u; -+ } buf; -+ -+ buf.k = kbuf; -+ oldfs = get_fs(); -+ set_fs(KERNEL_DS); -+ err = vfsub_read_u(file, buf.u, count, ppos); -+ set_fs(oldfs); -+ return err; -+} -+ -+ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count, -+ loff_t *ppos) -+{ -+ ssize_t err; -+ -+ lockdep_off(); -+ err = vfs_write(file, ubuf, count, ppos); -+ lockdep_on(); -+ if (err >= 0) -+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/ -+ return err; -+} -+ -+ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, loff_t *ppos) -+{ -+ ssize_t err; -+ mm_segment_t oldfs; -+ union { -+ void *k; -+ const char __user *u; -+ } buf; -+ -+ buf.k = kbuf; -+ oldfs = get_fs(); -+ set_fs(KERNEL_DS); -+ err = vfsub_write_u(file, buf.u, count, ppos); -+ set_fs(oldfs); -+ return err; -+} -+ -+int vfsub_flush(struct file *file, fl_owner_t id) -+{ -+ int err; -+ -+ err = 0; -+ if (file->f_op->flush) { -+ if (!au_test_nfs(file->f_path.dentry->d_sb)) -+ err = file->f_op->flush(file, id); -+ else { -+ lockdep_off(); -+ err = file->f_op->flush(file, id); -+ lockdep_on(); -+ } -+ if (!err) -+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); -+ /*ignore*/ -+ } -+ return err; -+} -+ -+int vfsub_iterate_dir(struct file *file, struct dir_context *ctx) -+{ -+ int err; -+ -+ AuDbg("%pD, ctx{%ps, %llu}\n", file, ctx->actor, ctx->pos); -+ -+ lockdep_off(); -+ err = iterate_dir(file, ctx); -+ lockdep_on(); -+ if (err >= 0) -+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/ -+ -+ return err; -+} -+ -+long vfsub_splice_to(struct file *in, loff_t *ppos, -+ struct pipe_inode_info *pipe, size_t len, -+ unsigned int flags) -+{ -+ long err; -+ -+ lockdep_off(); -+ err = do_splice_to(in, ppos, pipe, len, flags); -+ lockdep_on(); -+ file_accessed(in); -+ if (err >= 0) -+ vfsub_update_h_iattr(&in->f_path, /*did*/NULL); /*ignore*/ -+ return err; -+} -+ -+long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out, -+ loff_t *ppos, size_t len, unsigned int flags) -+{ -+ long err; -+ -+ lockdep_off(); -+ err = do_splice_from(pipe, out, ppos, len, flags); -+ lockdep_on(); -+ if (err >= 0) -+ vfsub_update_h_iattr(&out->f_path, /*did*/NULL); /*ignore*/ -+ return err; -+} -+ -+int vfsub_fsync(struct file *file, struct path *path, int datasync) -+{ -+ int err; -+ -+ /* file can be NULL */ -+ lockdep_off(); -+ err = vfs_fsync(file, datasync); -+ lockdep_on(); -+ if (!err) { -+ if (!path) { -+ AuDebugOn(!file); -+ path = &file->f_path; -+ } -+ vfsub_update_h_iattr(path, /*did*/NULL); /*ignore*/ -+ } -+ return err; -+} -+ -+/* cf. open.c:do_sys_truncate() and do_sys_ftruncate() */ -+int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr, -+ struct file *h_file) -+{ -+ int err; -+ struct inode *h_inode; -+ struct super_block *h_sb; -+ -+ if (!h_file) { -+ err = vfsub_truncate(h_path, length); -+ goto out; -+ } -+ -+ h_inode = d_inode(h_path->dentry); -+ h_sb = h_inode->i_sb; -+ lockdep_off(); -+ sb_start_write(h_sb); -+ lockdep_on(); -+ err = locks_verify_truncate(h_inode, h_file, length); -+ if (!err) -+ err = security_path_truncate(h_path); -+ if (!err) { -+ lockdep_off(); -+ err = do_truncate(h_path->dentry, length, attr, h_file); -+ lockdep_on(); -+ } -+ lockdep_off(); -+ sb_end_write(h_sb); -+ lockdep_on(); -+ -+out: -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct au_vfsub_mkdir_args { -+ int *errp; -+ struct inode *dir; -+ struct path *path; -+ int mode; -+}; -+ -+static void au_call_vfsub_mkdir(void *args) -+{ -+ struct au_vfsub_mkdir_args *a = args; -+ *a->errp = vfsub_mkdir(a->dir, a->path, a->mode); -+} -+ -+int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode) -+{ -+ int err, do_sio, wkq_err; -+ -+ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE); -+ if (!do_sio) { -+ lockdep_off(); -+ err = vfsub_mkdir(dir, path, mode); -+ lockdep_on(); -+ } else { -+ struct au_vfsub_mkdir_args args = { -+ .errp = &err, -+ .dir = dir, -+ .path = path, -+ .mode = mode -+ }; -+ wkq_err = au_wkq_wait(au_call_vfsub_mkdir, &args); -+ if (unlikely(wkq_err)) -+ err = wkq_err; -+ } -+ -+ return err; -+} -+ -+struct au_vfsub_rmdir_args { -+ int *errp; -+ struct inode *dir; -+ struct path *path; -+}; -+ -+static void au_call_vfsub_rmdir(void *args) -+{ -+ struct au_vfsub_rmdir_args *a = args; -+ *a->errp = vfsub_rmdir(a->dir, a->path); -+} -+ -+int vfsub_sio_rmdir(struct inode *dir, struct path *path) -+{ -+ int err, do_sio, wkq_err; -+ -+ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE); -+ if (!do_sio) { -+ lockdep_off(); -+ err = vfsub_rmdir(dir, path); -+ lockdep_on(); -+ } else { -+ struct au_vfsub_rmdir_args args = { -+ .errp = &err, -+ .dir = dir, -+ .path = path -+ }; -+ wkq_err = au_wkq_wait(au_call_vfsub_rmdir, &args); -+ if (unlikely(wkq_err)) -+ err = wkq_err; -+ } -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct notify_change_args { -+ int *errp; -+ struct path *path; -+ struct iattr *ia; -+ struct inode **delegated_inode; -+}; -+ -+static void call_notify_change(void *args) -+{ -+ struct notify_change_args *a = args; -+ struct inode *h_inode; -+ -+ h_inode = d_inode(a->path->dentry); -+ IMustLock(h_inode); -+ -+ *a->errp = -EPERM; -+ if (!IS_IMMUTABLE(h_inode) && !IS_APPEND(h_inode)) { -+ lockdep_off(); -+ *a->errp = notify_change(a->path->dentry, a->ia, -+ a->delegated_inode); -+ lockdep_on(); -+ if (!*a->errp) -+ vfsub_update_h_iattr(a->path, /*did*/NULL); /*ignore*/ -+ } -+ AuTraceErr(*a->errp); -+} -+ -+int vfsub_notify_change(struct path *path, struct iattr *ia, -+ struct inode **delegated_inode) -+{ -+ int err; -+ struct notify_change_args args = { -+ .errp = &err, -+ .path = path, -+ .ia = ia, -+ .delegated_inode = delegated_inode -+ }; -+ -+ call_notify_change(&args); -+ -+ return err; -+} -+ -+int vfsub_sio_notify_change(struct path *path, struct iattr *ia, -+ struct inode **delegated_inode) -+{ -+ int err, wkq_err; -+ struct notify_change_args args = { -+ .errp = &err, -+ .path = path, -+ .ia = ia, -+ .delegated_inode = delegated_inode -+ }; -+ -+ wkq_err = au_wkq_wait(call_notify_change, &args); -+ if (unlikely(wkq_err)) -+ err = wkq_err; -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct unlink_args { -+ int *errp; -+ struct inode *dir; -+ struct path *path; -+ struct inode **delegated_inode; -+}; -+ -+static void call_unlink(void *args) -+{ -+ struct unlink_args *a = args; -+ struct dentry *d = a->path->dentry; -+ struct inode *h_inode; -+ const int stop_sillyrename = (au_test_nfs(d->d_sb) -+ && au_dcount(d) == 1); -+ -+ IMustLock(a->dir); -+ -+ a->path->dentry = d->d_parent; -+ *a->errp = security_path_unlink(a->path, d); -+ a->path->dentry = d; -+ if (unlikely(*a->errp)) -+ return; -+ -+ if (!stop_sillyrename) -+ dget(d); -+ h_inode = NULL; -+ if (d_is_positive(d)) { -+ h_inode = d_inode(d); -+ ihold(h_inode); -+ } -+ -+ lockdep_off(); -+ *a->errp = vfs_unlink(a->dir, d, a->delegated_inode); -+ lockdep_on(); -+ if (!*a->errp) { -+ struct path tmp = { -+ .dentry = d->d_parent, -+ .mnt = a->path->mnt -+ }; -+ vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/ -+ } -+ -+ if (!stop_sillyrename) -+ dput(d); -+ if (h_inode) -+ iput(h_inode); -+ -+ AuTraceErr(*a->errp); -+} -+ -+/* -+ * @dir: must be locked. -+ * @dentry: target dentry. -+ */ -+int vfsub_unlink(struct inode *dir, struct path *path, -+ struct inode **delegated_inode, int force) -+{ -+ int err; -+ struct unlink_args args = { -+ .errp = &err, -+ .dir = dir, -+ .path = path, -+ .delegated_inode = delegated_inode -+ }; -+ -+ if (!force) -+ call_unlink(&args); -+ else { -+ int wkq_err; -+ -+ wkq_err = au_wkq_wait(call_unlink, &args); -+ if (unlikely(wkq_err)) -+ err = wkq_err; -+ } -+ -+ return err; -+} -diff --git a/fs/aufs/vfsub.h b/fs/aufs/vfsub.h -new file mode 100644 -index 000000000000..7d8993052cd5 ---- /dev/null -+++ b/fs/aufs/vfsub.h -@@ -0,0 +1,341 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * sub-routines for VFS -+ */ -+ -+#ifndef __AUFS_VFSUB_H__ -+#define __AUFS_VFSUB_H__ -+ -+#ifdef __KERNEL__ -+ -+#include -+#include -+#include -+#include -+#include "debug.h" -+ -+/* copied from linux/fs/internal.h */ -+/* todo: BAD approach!! */ -+extern void __mnt_drop_write(struct vfsmount *); -+extern struct file *alloc_empty_file(int, const struct cred *); -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* lock subclass for lower inode */ -+/* default MAX_LOCKDEP_SUBCLASSES(8) is not enough */ -+/* reduce? gave up. */ -+enum { -+ AuLsc_I_Begin = I_MUTEX_PARENT2, /* 5 */ -+ AuLsc_I_PARENT, /* lower inode, parent first */ -+ AuLsc_I_PARENT2, /* copyup dirs */ -+ AuLsc_I_PARENT3, /* copyup wh */ -+ AuLsc_I_CHILD, -+ AuLsc_I_CHILD2, -+ AuLsc_I_End -+}; -+ -+/* to debug easier, do not make them inlined functions */ -+#define MtxMustLock(mtx) AuDebugOn(!mutex_is_locked(mtx)) -+#define IMustLock(i) AuDebugOn(!inode_is_locked(i)) -+ -+/* ---------------------------------------------------------------------- */ -+ -+static inline void vfsub_drop_nlink(struct inode *inode) -+{ -+ AuDebugOn(!inode->i_nlink); -+ drop_nlink(inode); -+} -+ -+static inline void vfsub_dead_dir(struct inode *inode) -+{ -+ AuDebugOn(!S_ISDIR(inode->i_mode)); -+ inode->i_flags |= S_DEAD; -+ clear_nlink(inode); -+} -+ -+static inline int vfsub_native_ro(struct inode *inode) -+{ -+ return sb_rdonly(inode->i_sb) -+ || IS_RDONLY(inode) -+ /* || IS_APPEND(inode) */ -+ || IS_IMMUTABLE(inode); -+} -+ -+#ifdef CONFIG_AUFS_BR_FUSE -+int vfsub_test_mntns(struct vfsmount *mnt, struct super_block *h_sb); -+#else -+AuStubInt0(vfsub_test_mntns, struct vfsmount *mnt, struct super_block *h_sb); -+#endif -+ -+int vfsub_sync_filesystem(struct super_block *h_sb, int wait); -+ -+/* ---------------------------------------------------------------------- */ -+ -+int vfsub_update_h_iattr(struct path *h_path, int *did); -+struct file *vfsub_dentry_open(struct path *path, int flags); -+struct file *vfsub_filp_open(const char *path, int oflags, int mode); -+struct au_branch; -+struct vfsub_aopen_args { -+ struct file *file; -+ unsigned int open_flag; -+ umode_t create_mode; -+ struct au_branch *br; -+}; -+int vfsub_atomic_open(struct inode *dir, struct dentry *dentry, -+ struct vfsub_aopen_args *args); -+int vfsub_kern_path(const char *name, unsigned int flags, struct path *path); -+ -+struct dentry *vfsub_lookup_one_len_unlocked(const char *name, -+ struct dentry *parent, int len); -+struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent, -+ int len); -+ -+struct vfsub_lkup_one_args { -+ struct dentry **errp; -+ struct qstr *name; -+ struct dentry *parent; -+}; -+ -+static inline struct dentry *vfsub_lkup_one(struct qstr *name, -+ struct dentry *parent) -+{ -+ return vfsub_lookup_one_len(name->name, parent, name->len); -+} -+ -+void vfsub_call_lkup_one(void *args); -+ -+/* ---------------------------------------------------------------------- */ -+ -+static inline int vfsub_mnt_want_write(struct vfsmount *mnt) -+{ -+ int err; -+ -+ lockdep_off(); -+ err = mnt_want_write(mnt); -+ lockdep_on(); -+ return err; -+} -+ -+static inline void vfsub_mnt_drop_write(struct vfsmount *mnt) -+{ -+ lockdep_off(); -+ mnt_drop_write(mnt); -+ lockdep_on(); -+} -+ -+#if 0 /* reserved */ -+static inline void vfsub_mnt_drop_write_file(struct file *file) -+{ -+ lockdep_off(); -+ mnt_drop_write_file(file); -+ lockdep_on(); -+} -+#endif -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct au_hinode; -+struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1, -+ struct dentry *d2, struct au_hinode *hdir2); -+void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1, -+ struct dentry *d2, struct au_hinode *hdir2); -+ -+int vfsub_create(struct inode *dir, struct path *path, int mode, -+ bool want_excl); -+int vfsub_symlink(struct inode *dir, struct path *path, -+ const char *symname); -+int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev); -+int vfsub_link(struct dentry *src_dentry, struct inode *dir, -+ struct path *path, struct inode **delegated_inode); -+int vfsub_rename(struct inode *src_hdir, struct dentry *src_dentry, -+ struct inode *hdir, struct path *path, -+ struct inode **delegated_inode, unsigned int flags); -+int vfsub_mkdir(struct inode *dir, struct path *path, int mode); -+int vfsub_rmdir(struct inode *dir, struct path *path); -+ -+/* ---------------------------------------------------------------------- */ -+ -+ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count, -+ loff_t *ppos); -+ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count, -+ loff_t *ppos); -+ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count, -+ loff_t *ppos); -+ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, -+ loff_t *ppos); -+int vfsub_flush(struct file *file, fl_owner_t id); -+int vfsub_iterate_dir(struct file *file, struct dir_context *ctx); -+ -+static inline loff_t vfsub_f_size_read(struct file *file) -+{ -+ return i_size_read(file_inode(file)); -+} -+ -+static inline unsigned int vfsub_file_flags(struct file *file) -+{ -+ unsigned int flags; -+ -+ spin_lock(&file->f_lock); -+ flags = file->f_flags; -+ spin_unlock(&file->f_lock); -+ -+ return flags; -+} -+ -+static inline int vfsub_file_execed(struct file *file) -+{ -+ /* todo: direct access f_flags */ -+ return !!(vfsub_file_flags(file) & __FMODE_EXEC); -+} -+ -+#if 0 /* reserved */ -+static inline void vfsub_file_accessed(struct file *h_file) -+{ -+ file_accessed(h_file); -+ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL); /*ignore*/ -+} -+#endif -+ -+#if 0 /* reserved */ -+static inline void vfsub_touch_atime(struct vfsmount *h_mnt, -+ struct dentry *h_dentry) -+{ -+ struct path h_path = { -+ .dentry = h_dentry, -+ .mnt = h_mnt -+ }; -+ touch_atime(&h_path); -+ vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/ -+} -+#endif -+ -+static inline int vfsub_update_time(struct inode *h_inode, -+ struct timespec64 *ts, int flags) -+{ -+ return update_time(h_inode, ts, flags); -+ /* no vfsub_update_h_iattr() since we don't have struct path */ -+} -+ -+#ifdef CONFIG_FS_POSIX_ACL -+static inline int vfsub_acl_chmod(struct inode *h_inode, umode_t h_mode) -+{ -+ int err; -+ -+ err = posix_acl_chmod(h_inode, h_mode); -+ if (err == -EOPNOTSUPP) -+ err = 0; -+ return err; -+} -+#else -+AuStubInt0(vfsub_acl_chmod, struct inode *h_inode, umode_t h_mode); -+#endif -+ -+long vfsub_splice_to(struct file *in, loff_t *ppos, -+ struct pipe_inode_info *pipe, size_t len, -+ unsigned int flags); -+long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out, -+ loff_t *ppos, size_t len, unsigned int flags); -+ -+static inline long vfsub_truncate(struct path *path, loff_t length) -+{ -+ long err; -+ -+ lockdep_off(); -+ err = vfs_truncate(path, length); -+ lockdep_on(); -+ return err; -+} -+ -+int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr, -+ struct file *h_file); -+int vfsub_fsync(struct file *file, struct path *path, int datasync); -+ -+/* -+ * re-use branch fs's ioctl(FICLONE) while aufs itself doesn't support such -+ * ioctl. -+ */ -+static inline loff_t vfsub_clone_file_range(struct file *src, struct file *dst, -+ loff_t len) -+{ -+ loff_t err; -+ -+ lockdep_off(); -+ err = vfs_clone_file_range(src, 0, dst, 0, len, /*remap_flags*/0); -+ lockdep_on(); -+ -+ return err; -+} -+ -+/* copy_file_range(2) is a systemcall */ -+static inline ssize_t vfsub_copy_file_range(struct file *src, loff_t src_pos, -+ struct file *dst, loff_t dst_pos, -+ size_t len, unsigned int flags) -+{ -+ ssize_t ssz; -+ -+ lockdep_off(); -+ ssz = vfs_copy_file_range(src, src_pos, dst, dst_pos, len, flags); -+ lockdep_on(); -+ -+ return ssz; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static inline loff_t vfsub_llseek(struct file *file, loff_t offset, int origin) -+{ -+ loff_t err; -+ -+ lockdep_off(); -+ err = vfs_llseek(file, offset, origin); -+ lockdep_on(); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode); -+int vfsub_sio_rmdir(struct inode *dir, struct path *path); -+int vfsub_sio_notify_change(struct path *path, struct iattr *ia, -+ struct inode **delegated_inode); -+int vfsub_notify_change(struct path *path, struct iattr *ia, -+ struct inode **delegated_inode); -+int vfsub_unlink(struct inode *dir, struct path *path, -+ struct inode **delegated_inode, int force); -+ -+static inline int vfsub_getattr(const struct path *path, struct kstat *st) -+{ -+ return vfs_getattr(path, st, STATX_BASIC_STATS, AT_STATX_SYNC_AS_STAT); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static inline int vfsub_setxattr(struct dentry *dentry, const char *name, -+ const void *value, size_t size, int flags) -+{ -+ int err; -+ -+ lockdep_off(); -+ err = vfs_setxattr(dentry, name, value, size, flags); -+ lockdep_on(); -+ -+ return err; -+} -+ -+static inline int vfsub_removexattr(struct dentry *dentry, const char *name) -+{ -+ int err; -+ -+ lockdep_off(); -+ err = vfs_removexattr(dentry, name); -+ lockdep_on(); -+ -+ return err; -+} -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_VFSUB_H__ */ -diff --git a/fs/aufs/wbr_policy.c b/fs/aufs/wbr_policy.c -new file mode 100644 -index 000000000000..a18045b12573 ---- /dev/null -+++ b/fs/aufs/wbr_policy.c -@@ -0,0 +1,817 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * policies for selecting one among multiple writable branches -+ */ -+ -+#include -+#include "aufs.h" -+ -+/* subset of cpup_attr() */ -+static noinline_for_stack -+int au_cpdown_attr(struct path *h_path, struct dentry *h_src) -+{ -+ int err, sbits; -+ struct iattr ia; -+ struct inode *h_isrc; -+ -+ h_isrc = d_inode(h_src); -+ ia.ia_valid = ATTR_FORCE | ATTR_MODE | ATTR_UID | ATTR_GID; -+ ia.ia_mode = h_isrc->i_mode; -+ ia.ia_uid = h_isrc->i_uid; -+ ia.ia_gid = h_isrc->i_gid; -+ sbits = !!(ia.ia_mode & (S_ISUID | S_ISGID)); -+ au_cpup_attr_flags(d_inode(h_path->dentry), h_isrc->i_flags); -+ /* no delegation since it is just created */ -+ err = vfsub_sio_notify_change(h_path, &ia, /*delegated*/NULL); -+ -+ /* is this nfs only? */ -+ if (!err && sbits && au_test_nfs(h_path->dentry->d_sb)) { -+ ia.ia_valid = ATTR_FORCE | ATTR_MODE; -+ ia.ia_mode = h_isrc->i_mode; -+ err = vfsub_sio_notify_change(h_path, &ia, /*delegated*/NULL); -+ } -+ -+ return err; -+} -+ -+#define AuCpdown_PARENT_OPQ 1 -+#define AuCpdown_WHED (1 << 1) -+#define AuCpdown_MADE_DIR (1 << 2) -+#define AuCpdown_DIROPQ (1 << 3) -+#define au_ftest_cpdown(flags, name) ((flags) & AuCpdown_##name) -+#define au_fset_cpdown(flags, name) \ -+ do { (flags) |= AuCpdown_##name; } while (0) -+#define au_fclr_cpdown(flags, name) \ -+ do { (flags) &= ~AuCpdown_##name; } while (0) -+ -+static int au_cpdown_dir_opq(struct dentry *dentry, aufs_bindex_t bdst, -+ unsigned int *flags) -+{ -+ int err; -+ struct dentry *opq_dentry; -+ -+ opq_dentry = au_diropq_create(dentry, bdst); -+ err = PTR_ERR(opq_dentry); -+ if (IS_ERR(opq_dentry)) -+ goto out; -+ dput(opq_dentry); -+ au_fset_cpdown(*flags, DIROPQ); -+ -+out: -+ return err; -+} -+ -+static int au_cpdown_dir_wh(struct dentry *dentry, struct dentry *h_parent, -+ struct inode *dir, aufs_bindex_t bdst) -+{ -+ int err; -+ struct path h_path; -+ struct au_branch *br; -+ -+ br = au_sbr(dentry->d_sb, bdst); -+ h_path.dentry = au_wh_lkup(h_parent, &dentry->d_name, br); -+ err = PTR_ERR(h_path.dentry); -+ if (IS_ERR(h_path.dentry)) -+ goto out; -+ -+ err = 0; -+ if (d_is_positive(h_path.dentry)) { -+ h_path.mnt = au_br_mnt(br); -+ err = au_wh_unlink_dentry(au_h_iptr(dir, bdst), &h_path, -+ dentry); -+ } -+ dput(h_path.dentry); -+ -+out: -+ return err; -+} -+ -+static int au_cpdown_dir(struct dentry *dentry, aufs_bindex_t bdst, -+ struct au_pin *pin, -+ struct dentry *h_parent, void *arg) -+{ -+ int err, rerr; -+ aufs_bindex_t bopq, btop; -+ struct path h_path; -+ struct dentry *parent; -+ struct inode *h_dir, *h_inode, *inode, *dir; -+ unsigned int *flags = arg; -+ -+ btop = au_dbtop(dentry); -+ /* dentry is di-locked */ -+ parent = dget_parent(dentry); -+ dir = d_inode(parent); -+ h_dir = d_inode(h_parent); -+ AuDebugOn(h_dir != au_h_iptr(dir, bdst)); -+ IMustLock(h_dir); -+ -+ err = au_lkup_neg(dentry, bdst, /*wh*/0); -+ if (unlikely(err < 0)) -+ goto out; -+ h_path.dentry = au_h_dptr(dentry, bdst); -+ h_path.mnt = au_sbr_mnt(dentry->d_sb, bdst); -+ err = vfsub_sio_mkdir(au_h_iptr(dir, bdst), &h_path, 0755); -+ if (unlikely(err)) -+ goto out_put; -+ au_fset_cpdown(*flags, MADE_DIR); -+ -+ bopq = au_dbdiropq(dentry); -+ au_fclr_cpdown(*flags, WHED); -+ au_fclr_cpdown(*flags, DIROPQ); -+ if (au_dbwh(dentry) == bdst) -+ au_fset_cpdown(*flags, WHED); -+ if (!au_ftest_cpdown(*flags, PARENT_OPQ) && bopq <= bdst) -+ au_fset_cpdown(*flags, PARENT_OPQ); -+ h_inode = d_inode(h_path.dentry); -+ inode_lock_nested(h_inode, AuLsc_I_CHILD); -+ if (au_ftest_cpdown(*flags, WHED)) { -+ err = au_cpdown_dir_opq(dentry, bdst, flags); -+ if (unlikely(err)) { -+ inode_unlock(h_inode); -+ goto out_dir; -+ } -+ } -+ -+ err = au_cpdown_attr(&h_path, au_h_dptr(dentry, btop)); -+ inode_unlock(h_inode); -+ if (unlikely(err)) -+ goto out_opq; -+ -+ if (au_ftest_cpdown(*flags, WHED)) { -+ err = au_cpdown_dir_wh(dentry, h_parent, dir, bdst); -+ if (unlikely(err)) -+ goto out_opq; -+ } -+ -+ inode = d_inode(dentry); -+ if (au_ibbot(inode) < bdst) -+ au_set_ibbot(inode, bdst); -+ au_set_h_iptr(inode, bdst, au_igrab(h_inode), -+ au_hi_flags(inode, /*isdir*/1)); -+ au_fhsm_wrote(dentry->d_sb, bdst, /*force*/0); -+ goto out; /* success */ -+ -+ /* revert */ -+out_opq: -+ if (au_ftest_cpdown(*flags, DIROPQ)) { -+ inode_lock_nested(h_inode, AuLsc_I_CHILD); -+ rerr = au_diropq_remove(dentry, bdst); -+ inode_unlock(h_inode); -+ if (unlikely(rerr)) { -+ AuIOErr("failed removing diropq for %pd b%d (%d)\n", -+ dentry, bdst, rerr); -+ err = -EIO; -+ goto out; -+ } -+ } -+out_dir: -+ if (au_ftest_cpdown(*flags, MADE_DIR)) { -+ rerr = vfsub_sio_rmdir(au_h_iptr(dir, bdst), &h_path); -+ if (unlikely(rerr)) { -+ AuIOErr("failed removing %pd b%d (%d)\n", -+ dentry, bdst, rerr); -+ err = -EIO; -+ } -+ } -+out_put: -+ au_set_h_dptr(dentry, bdst, NULL); -+ if (au_dbbot(dentry) == bdst) -+ au_update_dbbot(dentry); -+out: -+ dput(parent); -+ return err; -+} -+ -+int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst) -+{ -+ int err; -+ unsigned int flags; -+ -+ flags = 0; -+ err = au_cp_dirs(dentry, bdst, au_cpdown_dir, &flags); -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* policies for create */ -+ -+int au_wbr_nonopq(struct dentry *dentry, aufs_bindex_t bindex) -+{ -+ int err, i, j, ndentry; -+ aufs_bindex_t bopq; -+ struct au_dcsub_pages dpages; -+ struct au_dpage *dpage; -+ struct dentry **dentries, *parent, *d; -+ -+ err = au_dpages_init(&dpages, GFP_NOFS); -+ if (unlikely(err)) -+ goto out; -+ parent = dget_parent(dentry); -+ err = au_dcsub_pages_rev_aufs(&dpages, parent, /*do_include*/0); -+ if (unlikely(err)) -+ goto out_free; -+ -+ err = bindex; -+ for (i = 0; i < dpages.ndpage; i++) { -+ dpage = dpages.dpages + i; -+ dentries = dpage->dentries; -+ ndentry = dpage->ndentry; -+ for (j = 0; j < ndentry; j++) { -+ d = dentries[j]; -+ di_read_lock_parent2(d, !AuLock_IR); -+ bopq = au_dbdiropq(d); -+ di_read_unlock(d, !AuLock_IR); -+ if (bopq >= 0 && bopq < err) -+ err = bopq; -+ } -+ } -+ -+out_free: -+ dput(parent); -+ au_dpages_free(&dpages); -+out: -+ return err; -+} -+ -+static int au_wbr_bu(struct super_block *sb, aufs_bindex_t bindex) -+{ -+ for (; bindex >= 0; bindex--) -+ if (!au_br_rdonly(au_sbr(sb, bindex))) -+ return bindex; -+ return -EROFS; -+} -+ -+/* top down parent */ -+static int au_wbr_create_tdp(struct dentry *dentry, -+ unsigned int flags __maybe_unused) -+{ -+ int err; -+ aufs_bindex_t btop, bindex; -+ struct super_block *sb; -+ struct dentry *parent, *h_parent; -+ -+ sb = dentry->d_sb; -+ btop = au_dbtop(dentry); -+ err = btop; -+ if (!au_br_rdonly(au_sbr(sb, btop))) -+ goto out; -+ -+ err = -EROFS; -+ parent = dget_parent(dentry); -+ for (bindex = au_dbtop(parent); bindex < btop; bindex++) { -+ h_parent = au_h_dptr(parent, bindex); -+ if (!h_parent || d_is_negative(h_parent)) -+ continue; -+ -+ if (!au_br_rdonly(au_sbr(sb, bindex))) { -+ err = bindex; -+ break; -+ } -+ } -+ dput(parent); -+ -+ /* bottom up here */ -+ if (unlikely(err < 0)) { -+ err = au_wbr_bu(sb, btop - 1); -+ if (err >= 0) -+ err = au_wbr_nonopq(dentry, err); -+ } -+ -+out: -+ AuDbg("b%d\n", err); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* an exception for the policy other than tdp */ -+static int au_wbr_create_exp(struct dentry *dentry) -+{ -+ int err; -+ aufs_bindex_t bwh, bdiropq; -+ struct dentry *parent; -+ -+ err = -1; -+ bwh = au_dbwh(dentry); -+ parent = dget_parent(dentry); -+ bdiropq = au_dbdiropq(parent); -+ if (bwh >= 0) { -+ if (bdiropq >= 0) -+ err = min(bdiropq, bwh); -+ else -+ err = bwh; -+ AuDbg("%d\n", err); -+ } else if (bdiropq >= 0) { -+ err = bdiropq; -+ AuDbg("%d\n", err); -+ } -+ dput(parent); -+ -+ if (err >= 0) -+ err = au_wbr_nonopq(dentry, err); -+ -+ if (err >= 0 && au_br_rdonly(au_sbr(dentry->d_sb, err))) -+ err = -1; -+ -+ AuDbg("%d\n", err); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* round robin */ -+static int au_wbr_create_init_rr(struct super_block *sb) -+{ -+ int err; -+ -+ err = au_wbr_bu(sb, au_sbbot(sb)); -+ atomic_set(&au_sbi(sb)->si_wbr_rr_next, -err); /* less important */ -+ /* smp_mb(); */ -+ -+ AuDbg("b%d\n", err); -+ return err; -+} -+ -+static int au_wbr_create_rr(struct dentry *dentry, unsigned int flags) -+{ -+ int err, nbr; -+ unsigned int u; -+ aufs_bindex_t bindex, bbot; -+ struct super_block *sb; -+ atomic_t *next; -+ -+ err = au_wbr_create_exp(dentry); -+ if (err >= 0) -+ goto out; -+ -+ sb = dentry->d_sb; -+ next = &au_sbi(sb)->si_wbr_rr_next; -+ bbot = au_sbbot(sb); -+ nbr = bbot + 1; -+ for (bindex = 0; bindex <= bbot; bindex++) { -+ if (!au_ftest_wbr(flags, DIR)) { -+ err = atomic_dec_return(next) + 1; -+ /* modulo for 0 is meaningless */ -+ if (unlikely(!err)) -+ err = atomic_dec_return(next) + 1; -+ } else -+ err = atomic_read(next); -+ AuDbg("%d\n", err); -+ u = err; -+ err = u % nbr; -+ AuDbg("%d\n", err); -+ if (!au_br_rdonly(au_sbr(sb, err))) -+ break; -+ err = -EROFS; -+ } -+ -+ if (err >= 0) -+ err = au_wbr_nonopq(dentry, err); -+ -+out: -+ AuDbg("%d\n", err); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* most free space */ -+static void au_mfs(struct dentry *dentry, struct dentry *parent) -+{ -+ struct super_block *sb; -+ struct au_branch *br; -+ struct au_wbr_mfs *mfs; -+ struct dentry *h_parent; -+ aufs_bindex_t bindex, bbot; -+ int err; -+ unsigned long long b, bavail; -+ struct path h_path; -+ /* reduce the stack usage */ -+ struct kstatfs *st; -+ -+ st = kmalloc(sizeof(*st), GFP_NOFS); -+ if (unlikely(!st)) { -+ AuWarn1("failed updating mfs(%d), ignored\n", -ENOMEM); -+ return; -+ } -+ -+ bavail = 0; -+ sb = dentry->d_sb; -+ mfs = &au_sbi(sb)->si_wbr_mfs; -+ MtxMustLock(&mfs->mfs_lock); -+ mfs->mfs_bindex = -EROFS; -+ mfs->mfsrr_bytes = 0; -+ if (!parent) { -+ bindex = 0; -+ bbot = au_sbbot(sb); -+ } else { -+ bindex = au_dbtop(parent); -+ bbot = au_dbtaildir(parent); -+ } -+ -+ for (; bindex <= bbot; bindex++) { -+ if (parent) { -+ h_parent = au_h_dptr(parent, bindex); -+ if (!h_parent || d_is_negative(h_parent)) -+ continue; -+ } -+ br = au_sbr(sb, bindex); -+ if (au_br_rdonly(br)) -+ continue; -+ -+ /* sb->s_root for NFS is unreliable */ -+ h_path.mnt = au_br_mnt(br); -+ h_path.dentry = h_path.mnt->mnt_root; -+ err = vfs_statfs(&h_path, st); -+ if (unlikely(err)) { -+ AuWarn1("failed statfs, b%d, %d\n", bindex, err); -+ continue; -+ } -+ -+ /* when the available size is equal, select the lower one */ -+ BUILD_BUG_ON(sizeof(b) < sizeof(st->f_bavail) -+ || sizeof(b) < sizeof(st->f_bsize)); -+ b = st->f_bavail * st->f_bsize; -+ br->br_wbr->wbr_bytes = b; -+ if (b >= bavail) { -+ bavail = b; -+ mfs->mfs_bindex = bindex; -+ mfs->mfs_jiffy = jiffies; -+ } -+ } -+ -+ mfs->mfsrr_bytes = bavail; -+ AuDbg("b%d\n", mfs->mfs_bindex); -+ au_kfree_rcu(st); -+} -+ -+static int au_wbr_create_mfs(struct dentry *dentry, unsigned int flags) -+{ -+ int err; -+ struct dentry *parent; -+ struct super_block *sb; -+ struct au_wbr_mfs *mfs; -+ -+ err = au_wbr_create_exp(dentry); -+ if (err >= 0) -+ goto out; -+ -+ sb = dentry->d_sb; -+ parent = NULL; -+ if (au_ftest_wbr(flags, PARENT)) -+ parent = dget_parent(dentry); -+ mfs = &au_sbi(sb)->si_wbr_mfs; -+ mutex_lock(&mfs->mfs_lock); -+ if (time_after(jiffies, mfs->mfs_jiffy + mfs->mfs_expire) -+ || mfs->mfs_bindex < 0 -+ || au_br_rdonly(au_sbr(sb, mfs->mfs_bindex))) -+ au_mfs(dentry, parent); -+ mutex_unlock(&mfs->mfs_lock); -+ err = mfs->mfs_bindex; -+ dput(parent); -+ -+ if (err >= 0) -+ err = au_wbr_nonopq(dentry, err); -+ -+out: -+ AuDbg("b%d\n", err); -+ return err; -+} -+ -+static int au_wbr_create_init_mfs(struct super_block *sb) -+{ -+ struct au_wbr_mfs *mfs; -+ -+ mfs = &au_sbi(sb)->si_wbr_mfs; -+ mutex_init(&mfs->mfs_lock); -+ mfs->mfs_jiffy = 0; -+ mfs->mfs_bindex = -EROFS; -+ -+ return 0; -+} -+ -+static int au_wbr_create_fin_mfs(struct super_block *sb __maybe_unused) -+{ -+ mutex_destroy(&au_sbi(sb)->si_wbr_mfs.mfs_lock); -+ return 0; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* top down regardless parent, and then mfs */ -+static int au_wbr_create_tdmfs(struct dentry *dentry, -+ unsigned int flags __maybe_unused) -+{ -+ int err; -+ aufs_bindex_t bwh, btail, bindex, bfound, bmfs; -+ unsigned long long watermark; -+ struct super_block *sb; -+ struct au_wbr_mfs *mfs; -+ struct au_branch *br; -+ struct dentry *parent; -+ -+ sb = dentry->d_sb; -+ mfs = &au_sbi(sb)->si_wbr_mfs; -+ mutex_lock(&mfs->mfs_lock); -+ if (time_after(jiffies, mfs->mfs_jiffy + mfs->mfs_expire) -+ || mfs->mfs_bindex < 0) -+ au_mfs(dentry, /*parent*/NULL); -+ watermark = mfs->mfsrr_watermark; -+ bmfs = mfs->mfs_bindex; -+ mutex_unlock(&mfs->mfs_lock); -+ -+ /* another style of au_wbr_create_exp() */ -+ bwh = au_dbwh(dentry); -+ parent = dget_parent(dentry); -+ btail = au_dbtaildir(parent); -+ if (bwh >= 0 && bwh < btail) -+ btail = bwh; -+ -+ err = au_wbr_nonopq(dentry, btail); -+ if (unlikely(err < 0)) -+ goto out; -+ btail = err; -+ bfound = -1; -+ for (bindex = 0; bindex <= btail; bindex++) { -+ br = au_sbr(sb, bindex); -+ if (au_br_rdonly(br)) -+ continue; -+ if (br->br_wbr->wbr_bytes > watermark) { -+ bfound = bindex; -+ break; -+ } -+ } -+ err = bfound; -+ if (err < 0) -+ err = bmfs; -+ -+out: -+ dput(parent); -+ AuDbg("b%d\n", err); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* most free space and then round robin */ -+static int au_wbr_create_mfsrr(struct dentry *dentry, unsigned int flags) -+{ -+ int err; -+ struct au_wbr_mfs *mfs; -+ -+ err = au_wbr_create_mfs(dentry, flags); -+ if (err >= 0) { -+ mfs = &au_sbi(dentry->d_sb)->si_wbr_mfs; -+ mutex_lock(&mfs->mfs_lock); -+ if (mfs->mfsrr_bytes < mfs->mfsrr_watermark) -+ err = au_wbr_create_rr(dentry, flags); -+ mutex_unlock(&mfs->mfs_lock); -+ } -+ -+ AuDbg("b%d\n", err); -+ return err; -+} -+ -+static int au_wbr_create_init_mfsrr(struct super_block *sb) -+{ -+ int err; -+ -+ au_wbr_create_init_mfs(sb); /* ignore */ -+ err = au_wbr_create_init_rr(sb); -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* top down parent and most free space */ -+static int au_wbr_create_pmfs(struct dentry *dentry, unsigned int flags) -+{ -+ int err, e2; -+ unsigned long long b; -+ aufs_bindex_t bindex, btop, bbot; -+ struct super_block *sb; -+ struct dentry *parent, *h_parent; -+ struct au_branch *br; -+ -+ err = au_wbr_create_tdp(dentry, flags); -+ if (unlikely(err < 0)) -+ goto out; -+ parent = dget_parent(dentry); -+ btop = au_dbtop(parent); -+ bbot = au_dbtaildir(parent); -+ if (btop == bbot) -+ goto out_parent; /* success */ -+ -+ e2 = au_wbr_create_mfs(dentry, flags); -+ if (e2 < 0) -+ goto out_parent; /* success */ -+ -+ /* when the available size is equal, select upper one */ -+ sb = dentry->d_sb; -+ br = au_sbr(sb, err); -+ b = br->br_wbr->wbr_bytes; -+ AuDbg("b%d, %llu\n", err, b); -+ -+ for (bindex = btop; bindex <= bbot; bindex++) { -+ h_parent = au_h_dptr(parent, bindex); -+ if (!h_parent || d_is_negative(h_parent)) -+ continue; -+ -+ br = au_sbr(sb, bindex); -+ if (!au_br_rdonly(br) && br->br_wbr->wbr_bytes > b) { -+ b = br->br_wbr->wbr_bytes; -+ err = bindex; -+ AuDbg("b%d, %llu\n", err, b); -+ } -+ } -+ -+ if (err >= 0) -+ err = au_wbr_nonopq(dentry, err); -+ -+out_parent: -+ dput(parent); -+out: -+ AuDbg("b%d\n", err); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * - top down parent -+ * - most free space with parent -+ * - most free space round-robin regardless parent -+ */ -+static int au_wbr_create_pmfsrr(struct dentry *dentry, unsigned int flags) -+{ -+ int err; -+ unsigned long long watermark; -+ struct super_block *sb; -+ struct au_branch *br; -+ struct au_wbr_mfs *mfs; -+ -+ err = au_wbr_create_pmfs(dentry, flags | AuWbr_PARENT); -+ if (unlikely(err < 0)) -+ goto out; -+ -+ sb = dentry->d_sb; -+ br = au_sbr(sb, err); -+ mfs = &au_sbi(sb)->si_wbr_mfs; -+ mutex_lock(&mfs->mfs_lock); -+ watermark = mfs->mfsrr_watermark; -+ mutex_unlock(&mfs->mfs_lock); -+ if (br->br_wbr->wbr_bytes < watermark) -+ /* regardless the parent dir */ -+ err = au_wbr_create_mfsrr(dentry, flags); -+ -+out: -+ AuDbg("b%d\n", err); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* policies for copyup */ -+ -+/* top down parent */ -+static int au_wbr_copyup_tdp(struct dentry *dentry) -+{ -+ return au_wbr_create_tdp(dentry, /*flags, anything is ok*/0); -+} -+ -+/* bottom up parent */ -+static int au_wbr_copyup_bup(struct dentry *dentry) -+{ -+ int err; -+ aufs_bindex_t bindex, btop; -+ struct dentry *parent, *h_parent; -+ struct super_block *sb; -+ -+ err = -EROFS; -+ sb = dentry->d_sb; -+ parent = dget_parent(dentry); -+ btop = au_dbtop(parent); -+ for (bindex = au_dbtop(dentry); bindex >= btop; bindex--) { -+ h_parent = au_h_dptr(parent, bindex); -+ if (!h_parent || d_is_negative(h_parent)) -+ continue; -+ -+ if (!au_br_rdonly(au_sbr(sb, bindex))) { -+ err = bindex; -+ break; -+ } -+ } -+ dput(parent); -+ -+ /* bottom up here */ -+ if (unlikely(err < 0)) -+ err = au_wbr_bu(sb, btop - 1); -+ -+ AuDbg("b%d\n", err); -+ return err; -+} -+ -+/* bottom up */ -+int au_wbr_do_copyup_bu(struct dentry *dentry, aufs_bindex_t btop) -+{ -+ int err; -+ -+ err = au_wbr_bu(dentry->d_sb, btop); -+ AuDbg("b%d\n", err); -+ if (err > btop) -+ err = au_wbr_nonopq(dentry, err); -+ -+ AuDbg("b%d\n", err); -+ return err; -+} -+ -+static int au_wbr_copyup_bu(struct dentry *dentry) -+{ -+ int err; -+ aufs_bindex_t btop; -+ -+ btop = au_dbtop(dentry); -+ err = au_wbr_do_copyup_bu(dentry, btop); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct au_wbr_copyup_operations au_wbr_copyup_ops[] = { -+ [AuWbrCopyup_TDP] = { -+ .copyup = au_wbr_copyup_tdp -+ }, -+ [AuWbrCopyup_BUP] = { -+ .copyup = au_wbr_copyup_bup -+ }, -+ [AuWbrCopyup_BU] = { -+ .copyup = au_wbr_copyup_bu -+ } -+}; -+ -+struct au_wbr_create_operations au_wbr_create_ops[] = { -+ [AuWbrCreate_TDP] = { -+ .create = au_wbr_create_tdp -+ }, -+ [AuWbrCreate_RR] = { -+ .create = au_wbr_create_rr, -+ .init = au_wbr_create_init_rr -+ }, -+ [AuWbrCreate_MFS] = { -+ .create = au_wbr_create_mfs, -+ .init = au_wbr_create_init_mfs, -+ .fin = au_wbr_create_fin_mfs -+ }, -+ [AuWbrCreate_MFSV] = { -+ .create = au_wbr_create_mfs, -+ .init = au_wbr_create_init_mfs, -+ .fin = au_wbr_create_fin_mfs -+ }, -+ [AuWbrCreate_MFSRR] = { -+ .create = au_wbr_create_mfsrr, -+ .init = au_wbr_create_init_mfsrr, -+ .fin = au_wbr_create_fin_mfs -+ }, -+ [AuWbrCreate_MFSRRV] = { -+ .create = au_wbr_create_mfsrr, -+ .init = au_wbr_create_init_mfsrr, -+ .fin = au_wbr_create_fin_mfs -+ }, -+ [AuWbrCreate_TDMFS] = { -+ .create = au_wbr_create_tdmfs, -+ .init = au_wbr_create_init_mfs, -+ .fin = au_wbr_create_fin_mfs -+ }, -+ [AuWbrCreate_TDMFSV] = { -+ .create = au_wbr_create_tdmfs, -+ .init = au_wbr_create_init_mfs, -+ .fin = au_wbr_create_fin_mfs -+ }, -+ [AuWbrCreate_PMFS] = { -+ .create = au_wbr_create_pmfs, -+ .init = au_wbr_create_init_mfs, -+ .fin = au_wbr_create_fin_mfs -+ }, -+ [AuWbrCreate_PMFSV] = { -+ .create = au_wbr_create_pmfs, -+ .init = au_wbr_create_init_mfs, -+ .fin = au_wbr_create_fin_mfs -+ }, -+ [AuWbrCreate_PMFSRR] = { -+ .create = au_wbr_create_pmfsrr, -+ .init = au_wbr_create_init_mfsrr, -+ .fin = au_wbr_create_fin_mfs -+ }, -+ [AuWbrCreate_PMFSRRV] = { -+ .create = au_wbr_create_pmfsrr, -+ .init = au_wbr_create_init_mfsrr, -+ .fin = au_wbr_create_fin_mfs -+ } -+}; -diff --git a/fs/aufs/whout.c b/fs/aufs/whout.c -new file mode 100644 -index 000000000000..9363954c4b06 ---- /dev/null -+++ b/fs/aufs/whout.c -@@ -0,0 +1,1049 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * whiteout for logical deletion and opaque directory -+ */ -+ -+#include "aufs.h" -+ -+#define WH_MASK 0444 -+ -+/* -+ * If a directory contains this file, then it is opaque. We start with the -+ * .wh. flag so that it is blocked by lookup. -+ */ -+static struct qstr diropq_name = QSTR_INIT(AUFS_WH_DIROPQ, -+ sizeof(AUFS_WH_DIROPQ) - 1); -+ -+/* -+ * generate whiteout name, which is NOT terminated by NULL. -+ * @name: original d_name.name -+ * @len: original d_name.len -+ * @wh: whiteout qstr -+ * returns zero when succeeds, otherwise error. -+ * succeeded value as wh->name should be freed by kfree(). -+ */ -+int au_wh_name_alloc(struct qstr *wh, const struct qstr *name) -+{ -+ char *p; -+ -+ if (unlikely(name->len > PATH_MAX - AUFS_WH_PFX_LEN)) -+ return -ENAMETOOLONG; -+ -+ wh->len = name->len + AUFS_WH_PFX_LEN; -+ p = kmalloc(wh->len, GFP_NOFS); -+ wh->name = p; -+ if (p) { -+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN); -+ memcpy(p + AUFS_WH_PFX_LEN, name->name, name->len); -+ /* smp_mb(); */ -+ return 0; -+ } -+ return -ENOMEM; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * test if the @wh_name exists under @h_parent. -+ * @try_sio specifies the necessary of super-io. -+ */ -+int au_wh_test(struct dentry *h_parent, struct qstr *wh_name, int try_sio) -+{ -+ int err; -+ struct dentry *wh_dentry; -+ -+ if (!try_sio) -+ wh_dentry = vfsub_lkup_one(wh_name, h_parent); -+ else -+ wh_dentry = au_sio_lkup_one(wh_name, h_parent); -+ err = PTR_ERR(wh_dentry); -+ if (IS_ERR(wh_dentry)) { -+ if (err == -ENAMETOOLONG) -+ err = 0; -+ goto out; -+ } -+ -+ err = 0; -+ if (d_is_negative(wh_dentry)) -+ goto out_wh; /* success */ -+ -+ err = 1; -+ if (d_is_reg(wh_dentry)) -+ goto out_wh; /* success */ -+ -+ err = -EIO; -+ AuIOErr("%pd Invalid whiteout entry type 0%o.\n", -+ wh_dentry, d_inode(wh_dentry)->i_mode); -+ -+out_wh: -+ dput(wh_dentry); -+out: -+ return err; -+} -+ -+/* -+ * test if the @h_dentry sets opaque or not. -+ */ -+int au_diropq_test(struct dentry *h_dentry) -+{ -+ int err; -+ struct inode *h_dir; -+ -+ h_dir = d_inode(h_dentry); -+ err = au_wh_test(h_dentry, &diropq_name, -+ au_test_h_perm_sio(h_dir, MAY_EXEC)); -+ return err; -+} -+ -+/* -+ * returns a negative dentry whose name is unique and temporary. -+ */ -+struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br, -+ struct qstr *prefix) -+{ -+ struct dentry *dentry; -+ int i; -+ char defname[NAME_MAX - AUFS_MAX_NAMELEN + DNAME_INLINE_LEN + 1], -+ *name, *p; -+ /* strict atomic_t is unnecessary here */ -+ static unsigned short cnt; -+ struct qstr qs; -+ -+ BUILD_BUG_ON(sizeof(cnt) * 2 > AUFS_WH_TMP_LEN); -+ -+ name = defname; -+ qs.len = sizeof(defname) - DNAME_INLINE_LEN + prefix->len - 1; -+ if (unlikely(prefix->len > DNAME_INLINE_LEN)) { -+ dentry = ERR_PTR(-ENAMETOOLONG); -+ if (unlikely(qs.len > NAME_MAX)) -+ goto out; -+ dentry = ERR_PTR(-ENOMEM); -+ name = kmalloc(qs.len + 1, GFP_NOFS); -+ if (unlikely(!name)) -+ goto out; -+ } -+ -+ /* doubly whiteout-ed */ -+ memcpy(name, AUFS_WH_PFX AUFS_WH_PFX, AUFS_WH_PFX_LEN * 2); -+ p = name + AUFS_WH_PFX_LEN * 2; -+ memcpy(p, prefix->name, prefix->len); -+ p += prefix->len; -+ *p++ = '.'; -+ AuDebugOn(name + qs.len + 1 - p <= AUFS_WH_TMP_LEN); -+ -+ qs.name = name; -+ for (i = 0; i < 3; i++) { -+ sprintf(p, "%.*x", AUFS_WH_TMP_LEN, cnt++); -+ dentry = au_sio_lkup_one(&qs, h_parent); -+ if (IS_ERR(dentry) || d_is_negative(dentry)) -+ goto out_name; -+ dput(dentry); -+ } -+ /* pr_warn("could not get random name\n"); */ -+ dentry = ERR_PTR(-EEXIST); -+ AuDbg("%.*s\n", AuLNPair(&qs)); -+ BUG(); -+ -+out_name: -+ if (name != defname) -+ au_kfree_try_rcu(name); -+out: -+ AuTraceErrPtr(dentry); -+ return dentry; -+} -+ -+/* -+ * rename the @h_dentry on @br to the whiteouted temporary name. -+ */ -+int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br) -+{ -+ int err; -+ struct path h_path = { -+ .mnt = au_br_mnt(br) -+ }; -+ struct inode *h_dir, *delegated; -+ struct dentry *h_parent; -+ -+ h_parent = h_dentry->d_parent; /* dir inode is locked */ -+ h_dir = d_inode(h_parent); -+ IMustLock(h_dir); -+ -+ h_path.dentry = au_whtmp_lkup(h_parent, br, &h_dentry->d_name); -+ err = PTR_ERR(h_path.dentry); -+ if (IS_ERR(h_path.dentry)) -+ goto out; -+ -+ /* under the same dir, no need to lock_rename() */ -+ delegated = NULL; -+ err = vfsub_rename(h_dir, h_dentry, h_dir, &h_path, &delegated, -+ /*flags*/0); -+ AuTraceErr(err); -+ if (unlikely(err == -EWOULDBLOCK)) { -+ pr_warn("cannot retry for NFSv4 delegation" -+ " for an internal rename\n"); -+ iput(delegated); -+ } -+ dput(h_path.dentry); -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+/* -+ * functions for removing a whiteout -+ */ -+ -+static int do_unlink_wh(struct inode *h_dir, struct path *h_path) -+{ -+ int err, force; -+ struct inode *delegated; -+ -+ /* -+ * forces superio when the dir has a sticky bit. -+ * this may be a violation of unix fs semantics. -+ */ -+ force = (h_dir->i_mode & S_ISVTX) -+ && !uid_eq(current_fsuid(), d_inode(h_path->dentry)->i_uid); -+ delegated = NULL; -+ err = vfsub_unlink(h_dir, h_path, &delegated, force); -+ if (unlikely(err == -EWOULDBLOCK)) { -+ pr_warn("cannot retry for NFSv4 delegation" -+ " for an internal unlink\n"); -+ iput(delegated); -+ } -+ return err; -+} -+ -+int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path, -+ struct dentry *dentry) -+{ -+ int err; -+ -+ err = do_unlink_wh(h_dir, h_path); -+ if (!err && dentry) -+ au_set_dbwh(dentry, -1); -+ -+ return err; -+} -+ -+static int unlink_wh_name(struct dentry *h_parent, struct qstr *wh, -+ struct au_branch *br) -+{ -+ int err; -+ struct path h_path = { -+ .mnt = au_br_mnt(br) -+ }; -+ -+ err = 0; -+ h_path.dentry = vfsub_lkup_one(wh, h_parent); -+ if (IS_ERR(h_path.dentry)) -+ err = PTR_ERR(h_path.dentry); -+ else { -+ if (d_is_reg(h_path.dentry)) -+ err = do_unlink_wh(d_inode(h_parent), &h_path); -+ dput(h_path.dentry); -+ } -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+/* -+ * initialize/clean whiteout for a branch -+ */ -+ -+static void au_wh_clean(struct inode *h_dir, struct path *whpath, -+ const int isdir) -+{ -+ int err; -+ struct inode *delegated; -+ -+ if (d_is_negative(whpath->dentry)) -+ return; -+ -+ if (isdir) -+ err = vfsub_rmdir(h_dir, whpath); -+ else { -+ delegated = NULL; -+ err = vfsub_unlink(h_dir, whpath, &delegated, /*force*/0); -+ if (unlikely(err == -EWOULDBLOCK)) { -+ pr_warn("cannot retry for NFSv4 delegation" -+ " for an internal unlink\n"); -+ iput(delegated); -+ } -+ } -+ if (unlikely(err)) -+ pr_warn("failed removing %pd (%d), ignored.\n", -+ whpath->dentry, err); -+} -+ -+static int test_linkable(struct dentry *h_root) -+{ -+ struct inode *h_dir = d_inode(h_root); -+ -+ if (h_dir->i_op->link) -+ return 0; -+ -+ pr_err("%pd (%s) doesn't support link(2), use noplink and rw+nolwh\n", -+ h_root, au_sbtype(h_root->d_sb)); -+ return -ENOSYS; /* the branch doesn't have its ->link() */ -+} -+ -+/* todo: should this mkdir be done in /sbin/mount.aufs helper? */ -+static int au_whdir(struct inode *h_dir, struct path *path) -+{ -+ int err; -+ -+ err = -EEXIST; -+ if (d_is_negative(path->dentry)) { -+ int mode = 0700; -+ -+ if (au_test_nfs(path->dentry->d_sb)) -+ mode |= 0111; -+ err = vfsub_mkdir(h_dir, path, mode); -+ } else if (d_is_dir(path->dentry)) -+ err = 0; -+ else -+ pr_err("unknown %pd exists\n", path->dentry); -+ -+ return err; -+} -+ -+struct au_wh_base { -+ const struct qstr *name; -+ struct dentry *dentry; -+}; -+ -+static void au_wh_init_ro(struct inode *h_dir, struct au_wh_base base[], -+ struct path *h_path) -+{ -+ h_path->dentry = base[AuBrWh_BASE].dentry; -+ au_wh_clean(h_dir, h_path, /*isdir*/0); -+ h_path->dentry = base[AuBrWh_PLINK].dentry; -+ au_wh_clean(h_dir, h_path, /*isdir*/1); -+ h_path->dentry = base[AuBrWh_ORPH].dentry; -+ au_wh_clean(h_dir, h_path, /*isdir*/1); -+} -+ -+/* -+ * returns tri-state, -+ * minus: error, caller should print the message -+ * zero: success -+ * plus: error, caller should NOT print the message -+ */ -+static int au_wh_init_rw_nolink(struct dentry *h_root, struct au_wbr *wbr, -+ int do_plink, struct au_wh_base base[], -+ struct path *h_path) -+{ -+ int err; -+ struct inode *h_dir; -+ -+ h_dir = d_inode(h_root); -+ h_path->dentry = base[AuBrWh_BASE].dentry; -+ au_wh_clean(h_dir, h_path, /*isdir*/0); -+ h_path->dentry = base[AuBrWh_PLINK].dentry; -+ if (do_plink) { -+ err = test_linkable(h_root); -+ if (unlikely(err)) { -+ err = 1; -+ goto out; -+ } -+ -+ err = au_whdir(h_dir, h_path); -+ if (unlikely(err)) -+ goto out; -+ wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry); -+ } else -+ au_wh_clean(h_dir, h_path, /*isdir*/1); -+ h_path->dentry = base[AuBrWh_ORPH].dentry; -+ err = au_whdir(h_dir, h_path); -+ if (unlikely(err)) -+ goto out; -+ wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry); -+ -+out: -+ return err; -+} -+ -+/* -+ * for the moment, aufs supports the branch filesystem which does not support -+ * link(2). testing on FAT which does not support i_op->setattr() fully either, -+ * copyup failed. finally, such filesystem will not be used as the writable -+ * branch. -+ * -+ * returns tri-state, see above. -+ */ -+static int au_wh_init_rw(struct dentry *h_root, struct au_wbr *wbr, -+ int do_plink, struct au_wh_base base[], -+ struct path *h_path) -+{ -+ int err; -+ struct inode *h_dir; -+ -+ WbrWhMustWriteLock(wbr); -+ -+ err = test_linkable(h_root); -+ if (unlikely(err)) { -+ err = 1; -+ goto out; -+ } -+ -+ /* -+ * todo: should this create be done in /sbin/mount.aufs helper? -+ */ -+ err = -EEXIST; -+ h_dir = d_inode(h_root); -+ if (d_is_negative(base[AuBrWh_BASE].dentry)) { -+ h_path->dentry = base[AuBrWh_BASE].dentry; -+ err = vfsub_create(h_dir, h_path, WH_MASK, /*want_excl*/true); -+ } else if (d_is_reg(base[AuBrWh_BASE].dentry)) -+ err = 0; -+ else -+ pr_err("unknown %pd2 exists\n", base[AuBrWh_BASE].dentry); -+ if (unlikely(err)) -+ goto out; -+ -+ h_path->dentry = base[AuBrWh_PLINK].dentry; -+ if (do_plink) { -+ err = au_whdir(h_dir, h_path); -+ if (unlikely(err)) -+ goto out; -+ wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry); -+ } else -+ au_wh_clean(h_dir, h_path, /*isdir*/1); -+ wbr->wbr_whbase = dget(base[AuBrWh_BASE].dentry); -+ -+ h_path->dentry = base[AuBrWh_ORPH].dentry; -+ err = au_whdir(h_dir, h_path); -+ if (unlikely(err)) -+ goto out; -+ wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry); -+ -+out: -+ return err; -+} -+ -+/* -+ * initialize the whiteout base file/dir for @br. -+ */ -+int au_wh_init(struct au_branch *br, struct super_block *sb) -+{ -+ int err, i; -+ const unsigned char do_plink -+ = !!au_opt_test(au_mntflags(sb), PLINK); -+ struct inode *h_dir; -+ struct path path = br->br_path; -+ struct dentry *h_root = path.dentry; -+ struct au_wbr *wbr = br->br_wbr; -+ static const struct qstr base_name[] = { -+ [AuBrWh_BASE] = QSTR_INIT(AUFS_BASE_NAME, -+ sizeof(AUFS_BASE_NAME) - 1), -+ [AuBrWh_PLINK] = QSTR_INIT(AUFS_PLINKDIR_NAME, -+ sizeof(AUFS_PLINKDIR_NAME) - 1), -+ [AuBrWh_ORPH] = QSTR_INIT(AUFS_ORPHDIR_NAME, -+ sizeof(AUFS_ORPHDIR_NAME) - 1) -+ }; -+ struct au_wh_base base[] = { -+ [AuBrWh_BASE] = { -+ .name = base_name + AuBrWh_BASE, -+ .dentry = NULL -+ }, -+ [AuBrWh_PLINK] = { -+ .name = base_name + AuBrWh_PLINK, -+ .dentry = NULL -+ }, -+ [AuBrWh_ORPH] = { -+ .name = base_name + AuBrWh_ORPH, -+ .dentry = NULL -+ } -+ }; -+ -+ if (wbr) -+ WbrWhMustWriteLock(wbr); -+ -+ for (i = 0; i < AuBrWh_Last; i++) { -+ /* doubly whiteouted */ -+ struct dentry *d; -+ -+ d = au_wh_lkup(h_root, (void *)base[i].name, br); -+ err = PTR_ERR(d); -+ if (IS_ERR(d)) -+ goto out; -+ -+ base[i].dentry = d; -+ AuDebugOn(wbr -+ && wbr->wbr_wh[i] -+ && wbr->wbr_wh[i] != base[i].dentry); -+ } -+ -+ if (wbr) -+ for (i = 0; i < AuBrWh_Last; i++) { -+ dput(wbr->wbr_wh[i]); -+ wbr->wbr_wh[i] = NULL; -+ } -+ -+ err = 0; -+ if (!au_br_writable(br->br_perm)) { -+ h_dir = d_inode(h_root); -+ au_wh_init_ro(h_dir, base, &path); -+ } else if (!au_br_wh_linkable(br->br_perm)) { -+ err = au_wh_init_rw_nolink(h_root, wbr, do_plink, base, &path); -+ if (err > 0) -+ goto out; -+ else if (err) -+ goto out_err; -+ } else { -+ err = au_wh_init_rw(h_root, wbr, do_plink, base, &path); -+ if (err > 0) -+ goto out; -+ else if (err) -+ goto out_err; -+ } -+ goto out; /* success */ -+ -+out_err: -+ pr_err("an error(%d) on the writable branch %pd(%s)\n", -+ err, h_root, au_sbtype(h_root->d_sb)); -+out: -+ for (i = 0; i < AuBrWh_Last; i++) -+ dput(base[i].dentry); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+/* -+ * whiteouts are all hard-linked usually. -+ * when its link count reaches a ceiling, we create a new whiteout base -+ * asynchronously. -+ */ -+ -+struct reinit_br_wh { -+ struct super_block *sb; -+ struct au_branch *br; -+}; -+ -+static void reinit_br_wh(void *arg) -+{ -+ int err; -+ aufs_bindex_t bindex; -+ struct path h_path; -+ struct reinit_br_wh *a = arg; -+ struct au_wbr *wbr; -+ struct inode *dir, *delegated; -+ struct dentry *h_root; -+ struct au_hinode *hdir; -+ -+ err = 0; -+ wbr = a->br->br_wbr; -+ /* big aufs lock */ -+ si_noflush_write_lock(a->sb); -+ if (!au_br_writable(a->br->br_perm)) -+ goto out; -+ bindex = au_br_index(a->sb, a->br->br_id); -+ if (unlikely(bindex < 0)) -+ goto out; -+ -+ di_read_lock_parent(a->sb->s_root, AuLock_IR); -+ dir = d_inode(a->sb->s_root); -+ hdir = au_hi(dir, bindex); -+ h_root = au_h_dptr(a->sb->s_root, bindex); -+ AuDebugOn(h_root != au_br_dentry(a->br)); -+ -+ au_hn_inode_lock_nested(hdir, AuLsc_I_PARENT); -+ wbr_wh_write_lock(wbr); -+ err = au_h_verify(wbr->wbr_whbase, au_opt_udba(a->sb), hdir->hi_inode, -+ h_root, a->br); -+ if (!err) { -+ h_path.dentry = wbr->wbr_whbase; -+ h_path.mnt = au_br_mnt(a->br); -+ delegated = NULL; -+ err = vfsub_unlink(hdir->hi_inode, &h_path, &delegated, -+ /*force*/0); -+ if (unlikely(err == -EWOULDBLOCK)) { -+ pr_warn("cannot retry for NFSv4 delegation" -+ " for an internal unlink\n"); -+ iput(delegated); -+ } -+ } else { -+ pr_warn("%pd is moved, ignored\n", wbr->wbr_whbase); -+ err = 0; -+ } -+ dput(wbr->wbr_whbase); -+ wbr->wbr_whbase = NULL; -+ if (!err) -+ err = au_wh_init(a->br, a->sb); -+ wbr_wh_write_unlock(wbr); -+ au_hn_inode_unlock(hdir); -+ di_read_unlock(a->sb->s_root, AuLock_IR); -+ if (!err) -+ au_fhsm_wrote(a->sb, bindex, /*force*/0); -+ -+out: -+ if (wbr) -+ atomic_dec(&wbr->wbr_wh_running); -+ au_lcnt_dec(&a->br->br_count); -+ si_write_unlock(a->sb); -+ au_nwt_done(&au_sbi(a->sb)->si_nowait); -+ au_kfree_rcu(a); -+ if (unlikely(err)) -+ AuIOErr("err %d\n", err); -+} -+ -+static void kick_reinit_br_wh(struct super_block *sb, struct au_branch *br) -+{ -+ int do_dec, wkq_err; -+ struct reinit_br_wh *arg; -+ -+ do_dec = 1; -+ if (atomic_inc_return(&br->br_wbr->wbr_wh_running) != 1) -+ goto out; -+ -+ /* ignore ENOMEM */ -+ arg = kmalloc(sizeof(*arg), GFP_NOFS); -+ if (arg) { -+ /* -+ * dec(wh_running), kfree(arg) and dec(br_count) -+ * in reinit function -+ */ -+ arg->sb = sb; -+ arg->br = br; -+ au_lcnt_inc(&br->br_count); -+ wkq_err = au_wkq_nowait(reinit_br_wh, arg, sb, /*flags*/0); -+ if (unlikely(wkq_err)) { -+ atomic_dec(&br->br_wbr->wbr_wh_running); -+ au_lcnt_dec(&br->br_count); -+ au_kfree_rcu(arg); -+ } -+ do_dec = 0; -+ } -+ -+out: -+ if (do_dec) -+ atomic_dec(&br->br_wbr->wbr_wh_running); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * create the whiteout @wh. -+ */ -+static int link_or_create_wh(struct super_block *sb, aufs_bindex_t bindex, -+ struct dentry *wh) -+{ -+ int err; -+ struct path h_path = { -+ .dentry = wh -+ }; -+ struct au_branch *br; -+ struct au_wbr *wbr; -+ struct dentry *h_parent; -+ struct inode *h_dir, *delegated; -+ -+ h_parent = wh->d_parent; /* dir inode is locked */ -+ h_dir = d_inode(h_parent); -+ IMustLock(h_dir); -+ -+ br = au_sbr(sb, bindex); -+ h_path.mnt = au_br_mnt(br); -+ wbr = br->br_wbr; -+ wbr_wh_read_lock(wbr); -+ if (wbr->wbr_whbase) { -+ delegated = NULL; -+ err = vfsub_link(wbr->wbr_whbase, h_dir, &h_path, &delegated); -+ if (unlikely(err == -EWOULDBLOCK)) { -+ pr_warn("cannot retry for NFSv4 delegation" -+ " for an internal link\n"); -+ iput(delegated); -+ } -+ if (!err || err != -EMLINK) -+ goto out; -+ -+ /* link count full. re-initialize br_whbase. */ -+ kick_reinit_br_wh(sb, br); -+ } -+ -+ /* return this error in this context */ -+ err = vfsub_create(h_dir, &h_path, WH_MASK, /*want_excl*/true); -+ if (!err) -+ au_fhsm_wrote(sb, bindex, /*force*/0); -+ -+out: -+ wbr_wh_read_unlock(wbr); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * create or remove the diropq. -+ */ -+static struct dentry *do_diropq(struct dentry *dentry, aufs_bindex_t bindex, -+ unsigned int flags) -+{ -+ struct dentry *opq_dentry, *h_dentry; -+ struct super_block *sb; -+ struct au_branch *br; -+ int err; -+ -+ sb = dentry->d_sb; -+ br = au_sbr(sb, bindex); -+ h_dentry = au_h_dptr(dentry, bindex); -+ opq_dentry = vfsub_lkup_one(&diropq_name, h_dentry); -+ if (IS_ERR(opq_dentry)) -+ goto out; -+ -+ if (au_ftest_diropq(flags, CREATE)) { -+ err = link_or_create_wh(sb, bindex, opq_dentry); -+ if (!err) { -+ au_set_dbdiropq(dentry, bindex); -+ goto out; /* success */ -+ } -+ } else { -+ struct path tmp = { -+ .dentry = opq_dentry, -+ .mnt = au_br_mnt(br) -+ }; -+ err = do_unlink_wh(au_h_iptr(d_inode(dentry), bindex), &tmp); -+ if (!err) -+ au_set_dbdiropq(dentry, -1); -+ } -+ dput(opq_dentry); -+ opq_dentry = ERR_PTR(err); -+ -+out: -+ return opq_dentry; -+} -+ -+struct do_diropq_args { -+ struct dentry **errp; -+ struct dentry *dentry; -+ aufs_bindex_t bindex; -+ unsigned int flags; -+}; -+ -+static void call_do_diropq(void *args) -+{ -+ struct do_diropq_args *a = args; -+ *a->errp = do_diropq(a->dentry, a->bindex, a->flags); -+} -+ -+struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex, -+ unsigned int flags) -+{ -+ struct dentry *diropq, *h_dentry; -+ -+ h_dentry = au_h_dptr(dentry, bindex); -+ if (!au_test_h_perm_sio(d_inode(h_dentry), MAY_EXEC | MAY_WRITE)) -+ diropq = do_diropq(dentry, bindex, flags); -+ else { -+ int wkq_err; -+ struct do_diropq_args args = { -+ .errp = &diropq, -+ .dentry = dentry, -+ .bindex = bindex, -+ .flags = flags -+ }; -+ -+ wkq_err = au_wkq_wait(call_do_diropq, &args); -+ if (unlikely(wkq_err)) -+ diropq = ERR_PTR(wkq_err); -+ } -+ -+ return diropq; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * lookup whiteout dentry. -+ * @h_parent: lower parent dentry which must exist and be locked -+ * @base_name: name of dentry which will be whiteouted -+ * returns dentry for whiteout. -+ */ -+struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name, -+ struct au_branch *br) -+{ -+ int err; -+ struct qstr wh_name; -+ struct dentry *wh_dentry; -+ -+ err = au_wh_name_alloc(&wh_name, base_name); -+ wh_dentry = ERR_PTR(err); -+ if (!err) { -+ wh_dentry = vfsub_lkup_one(&wh_name, h_parent); -+ au_kfree_try_rcu(wh_name.name); -+ } -+ return wh_dentry; -+} -+ -+/* -+ * link/create a whiteout for @dentry on @bindex. -+ */ -+struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex, -+ struct dentry *h_parent) -+{ -+ struct dentry *wh_dentry; -+ struct super_block *sb; -+ int err; -+ -+ sb = dentry->d_sb; -+ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, au_sbr(sb, bindex)); -+ if (!IS_ERR(wh_dentry) && d_is_negative(wh_dentry)) { -+ err = link_or_create_wh(sb, bindex, wh_dentry); -+ if (!err) { -+ au_set_dbwh(dentry, bindex); -+ au_fhsm_wrote(sb, bindex, /*force*/0); -+ } else { -+ dput(wh_dentry); -+ wh_dentry = ERR_PTR(err); -+ } -+ } -+ -+ return wh_dentry; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* Delete all whiteouts in this directory on branch bindex. */ -+static int del_wh_children(struct dentry *h_dentry, struct au_nhash *whlist, -+ aufs_bindex_t bindex, struct au_branch *br) -+{ -+ int err; -+ unsigned long ul, n; -+ struct qstr wh_name; -+ char *p; -+ struct hlist_head *head; -+ struct au_vdir_wh *pos; -+ struct au_vdir_destr *str; -+ -+ err = -ENOMEM; -+ p = (void *)__get_free_page(GFP_NOFS); -+ wh_name.name = p; -+ if (unlikely(!wh_name.name)) -+ goto out; -+ -+ err = 0; -+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN); -+ p += AUFS_WH_PFX_LEN; -+ n = whlist->nh_num; -+ head = whlist->nh_head; -+ for (ul = 0; !err && ul < n; ul++, head++) { -+ hlist_for_each_entry(pos, head, wh_hash) { -+ if (pos->wh_bindex != bindex) -+ continue; -+ -+ str = &pos->wh_str; -+ if (str->len + AUFS_WH_PFX_LEN <= PATH_MAX) { -+ memcpy(p, str->name, str->len); -+ wh_name.len = AUFS_WH_PFX_LEN + str->len; -+ err = unlink_wh_name(h_dentry, &wh_name, br); -+ if (!err) -+ continue; -+ break; -+ } -+ AuIOErr("whiteout name too long %.*s\n", -+ str->len, str->name); -+ err = -EIO; -+ break; -+ } -+ } -+ free_page((unsigned long)wh_name.name); -+ -+out: -+ return err; -+} -+ -+struct del_wh_children_args { -+ int *errp; -+ struct dentry *h_dentry; -+ struct au_nhash *whlist; -+ aufs_bindex_t bindex; -+ struct au_branch *br; -+}; -+ -+static void call_del_wh_children(void *args) -+{ -+ struct del_wh_children_args *a = args; -+ *a->errp = del_wh_children(a->h_dentry, a->whlist, a->bindex, a->br); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp) -+{ -+ struct au_whtmp_rmdir *whtmp; -+ int err; -+ unsigned int rdhash; -+ -+ SiMustAnyLock(sb); -+ -+ whtmp = kzalloc(sizeof(*whtmp), gfp); -+ if (unlikely(!whtmp)) { -+ whtmp = ERR_PTR(-ENOMEM); -+ goto out; -+ } -+ -+ /* no estimation for dir size */ -+ rdhash = au_sbi(sb)->si_rdhash; -+ if (!rdhash) -+ rdhash = AUFS_RDHASH_DEF; -+ err = au_nhash_alloc(&whtmp->whlist, rdhash, gfp); -+ if (unlikely(err)) { -+ au_kfree_rcu(whtmp); -+ whtmp = ERR_PTR(err); -+ } -+ -+out: -+ return whtmp; -+} -+ -+void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp) -+{ -+ if (whtmp->br) -+ au_lcnt_dec(&whtmp->br->br_count); -+ dput(whtmp->wh_dentry); -+ iput(whtmp->dir); -+ au_nhash_wh_free(&whtmp->whlist); -+ au_kfree_rcu(whtmp); -+} -+ -+/* -+ * rmdir the whiteouted temporary named dir @h_dentry. -+ * @whlist: whiteouted children. -+ */ -+int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex, -+ struct dentry *wh_dentry, struct au_nhash *whlist) -+{ -+ int err; -+ unsigned int h_nlink; -+ struct path h_tmp; -+ struct inode *wh_inode, *h_dir; -+ struct au_branch *br; -+ -+ h_dir = d_inode(wh_dentry->d_parent); /* dir inode is locked */ -+ IMustLock(h_dir); -+ -+ br = au_sbr(dir->i_sb, bindex); -+ wh_inode = d_inode(wh_dentry); -+ inode_lock_nested(wh_inode, AuLsc_I_CHILD); -+ -+ /* -+ * someone else might change some whiteouts while we were sleeping. -+ * it means this whlist may have an obsoleted entry. -+ */ -+ if (!au_test_h_perm_sio(wh_inode, MAY_EXEC | MAY_WRITE)) -+ err = del_wh_children(wh_dentry, whlist, bindex, br); -+ else { -+ int wkq_err; -+ struct del_wh_children_args args = { -+ .errp = &err, -+ .h_dentry = wh_dentry, -+ .whlist = whlist, -+ .bindex = bindex, -+ .br = br -+ }; -+ -+ wkq_err = au_wkq_wait(call_del_wh_children, &args); -+ if (unlikely(wkq_err)) -+ err = wkq_err; -+ } -+ inode_unlock(wh_inode); -+ -+ if (!err) { -+ h_tmp.dentry = wh_dentry; -+ h_tmp.mnt = au_br_mnt(br); -+ h_nlink = h_dir->i_nlink; -+ err = vfsub_rmdir(h_dir, &h_tmp); -+ /* some fs doesn't change the parent nlink in some cases */ -+ h_nlink -= h_dir->i_nlink; -+ } -+ -+ if (!err) { -+ if (au_ibtop(dir) == bindex) { -+ /* todo: dir->i_mutex is necessary */ -+ au_cpup_attr_timesizes(dir); -+ if (h_nlink) -+ vfsub_drop_nlink(dir); -+ } -+ return 0; /* success */ -+ } -+ -+ pr_warn("failed removing %pd(%d), ignored\n", wh_dentry, err); -+ return err; -+} -+ -+static void call_rmdir_whtmp(void *args) -+{ -+ int err; -+ aufs_bindex_t bindex; -+ struct au_whtmp_rmdir *a = args; -+ struct super_block *sb; -+ struct dentry *h_parent; -+ struct inode *h_dir; -+ struct au_hinode *hdir; -+ -+ /* rmdir by nfsd may cause deadlock with this i_mutex */ -+ /* inode_lock(a->dir); */ -+ err = -EROFS; -+ sb = a->dir->i_sb; -+ si_read_lock(sb, !AuLock_FLUSH); -+ if (!au_br_writable(a->br->br_perm)) -+ goto out; -+ bindex = au_br_index(sb, a->br->br_id); -+ if (unlikely(bindex < 0)) -+ goto out; -+ -+ err = -EIO; -+ ii_write_lock_parent(a->dir); -+ h_parent = dget_parent(a->wh_dentry); -+ h_dir = d_inode(h_parent); -+ hdir = au_hi(a->dir, bindex); -+ err = vfsub_mnt_want_write(au_br_mnt(a->br)); -+ if (unlikely(err)) -+ goto out_mnt; -+ au_hn_inode_lock_nested(hdir, AuLsc_I_PARENT); -+ err = au_h_verify(a->wh_dentry, au_opt_udba(sb), h_dir, h_parent, -+ a->br); -+ if (!err) -+ err = au_whtmp_rmdir(a->dir, bindex, a->wh_dentry, &a->whlist); -+ au_hn_inode_unlock(hdir); -+ vfsub_mnt_drop_write(au_br_mnt(a->br)); -+ -+out_mnt: -+ dput(h_parent); -+ ii_write_unlock(a->dir); -+out: -+ /* inode_unlock(a->dir); */ -+ au_whtmp_rmdir_free(a); -+ si_read_unlock(sb); -+ au_nwt_done(&au_sbi(sb)->si_nowait); -+ if (unlikely(err)) -+ AuIOErr("err %d\n", err); -+} -+ -+void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex, -+ struct dentry *wh_dentry, struct au_whtmp_rmdir *args) -+{ -+ int wkq_err; -+ struct super_block *sb; -+ -+ IMustLock(dir); -+ -+ /* all post-process will be done in do_rmdir_whtmp(). */ -+ sb = dir->i_sb; -+ args->dir = au_igrab(dir); -+ args->br = au_sbr(sb, bindex); -+ au_lcnt_inc(&args->br->br_count); -+ args->wh_dentry = dget(wh_dentry); -+ wkq_err = au_wkq_nowait(call_rmdir_whtmp, args, sb, /*flags*/0); -+ if (unlikely(wkq_err)) { -+ pr_warn("rmdir error %pd (%d), ignored\n", wh_dentry, wkq_err); -+ au_whtmp_rmdir_free(args); -+ } -+} -diff --git a/fs/aufs/whout.h b/fs/aufs/whout.h -new file mode 100644 -index 000000000000..dc4eb41e70dd ---- /dev/null -+++ b/fs/aufs/whout.h -@@ -0,0 +1,73 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * whiteout for logical deletion and opaque directory -+ */ -+ -+#ifndef __AUFS_WHOUT_H__ -+#define __AUFS_WHOUT_H__ -+ -+#ifdef __KERNEL__ -+ -+#include "dir.h" -+ -+/* whout.c */ -+int au_wh_name_alloc(struct qstr *wh, const struct qstr *name); -+int au_wh_test(struct dentry *h_parent, struct qstr *wh_name, int try_sio); -+int au_diropq_test(struct dentry *h_dentry); -+struct au_branch; -+struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br, -+ struct qstr *prefix); -+int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br); -+int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path, -+ struct dentry *dentry); -+int au_wh_init(struct au_branch *br, struct super_block *sb); -+ -+/* diropq flags */ -+#define AuDiropq_CREATE 1 -+#define au_ftest_diropq(flags, name) ((flags) & AuDiropq_##name) -+#define au_fset_diropq(flags, name) \ -+ do { (flags) |= AuDiropq_##name; } while (0) -+#define au_fclr_diropq(flags, name) \ -+ do { (flags) &= ~AuDiropq_##name; } while (0) -+ -+struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex, -+ unsigned int flags); -+struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name, -+ struct au_branch *br); -+struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex, -+ struct dentry *h_parent); -+ -+/* real rmdir for the whiteout-ed dir */ -+struct au_whtmp_rmdir { -+ struct inode *dir; -+ struct au_branch *br; -+ struct dentry *wh_dentry; -+ struct au_nhash whlist; -+}; -+ -+struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp); -+void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp); -+int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex, -+ struct dentry *wh_dentry, struct au_nhash *whlist); -+void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex, -+ struct dentry *wh_dentry, struct au_whtmp_rmdir *args); -+ -+/* ---------------------------------------------------------------------- */ -+ -+static inline struct dentry *au_diropq_create(struct dentry *dentry, -+ aufs_bindex_t bindex) -+{ -+ return au_diropq_sio(dentry, bindex, AuDiropq_CREATE); -+} -+ -+static inline int au_diropq_remove(struct dentry *dentry, aufs_bindex_t bindex) -+{ -+ return PTR_ERR(au_diropq_sio(dentry, bindex, !AuDiropq_CREATE)); -+} -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_WHOUT_H__ */ -diff --git a/fs/aufs/wkq.c b/fs/aufs/wkq.c -new file mode 100644 -index 000000000000..288f5cf4b200 ---- /dev/null -+++ b/fs/aufs/wkq.c -@@ -0,0 +1,359 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * workqueue for asynchronous/super-io operations -+ * todo: try new credential scheme -+ */ -+ -+#include -+#include "aufs.h" -+ -+/* internal workqueue named AUFS_WKQ_NAME */ -+ -+static struct workqueue_struct *au_wkq; -+ -+struct au_wkinfo { -+ struct work_struct wk; -+ struct kobject *kobj; -+ -+ unsigned int flags; /* see wkq.h */ -+ -+ au_wkq_func_t func; -+ void *args; -+ -+#ifdef CONFIG_LOCKDEP -+ int dont_check; -+ struct held_lock **hlock; -+#endif -+ -+ struct completion *comp; -+}; -+ -+/* ---------------------------------------------------------------------- */ -+/* -+ * Aufs passes some operations to the workqueue such as the internal copyup. -+ * This scheme looks rather unnatural for LOCKDEP debugging feature, since the -+ * job run by workqueue depends upon the locks acquired in the other task. -+ * Delegating a small operation to the workqueue, aufs passes its lockdep -+ * information too. And the job in the workqueue restores the info in order to -+ * pretend as if it acquired those locks. This is just to make LOCKDEP work -+ * correctly and expectedly. -+ */ -+ -+#ifndef CONFIG_LOCKDEP -+AuStubInt0(au_wkq_lockdep_alloc, struct au_wkinfo *wkinfo); -+AuStubVoid(au_wkq_lockdep_free, struct au_wkinfo *wkinfo); -+AuStubVoid(au_wkq_lockdep_pre, struct au_wkinfo *wkinfo); -+AuStubVoid(au_wkq_lockdep_post, struct au_wkinfo *wkinfo); -+AuStubVoid(au_wkq_lockdep_init, struct au_wkinfo *wkinfo); -+#else -+static void au_wkq_lockdep_init(struct au_wkinfo *wkinfo) -+{ -+ wkinfo->hlock = NULL; -+ wkinfo->dont_check = 0; -+} -+ -+/* -+ * 1: matched -+ * 0: unmatched -+ */ -+static int au_wkq_lockdep_test(struct lock_class_key *key, const char *name) -+{ -+ static DEFINE_SPINLOCK(spin); -+ static struct { -+ char *name; -+ struct lock_class_key *key; -+ } a[] = { -+ { .name = "&sbinfo->si_rwsem" }, -+ { .name = "&finfo->fi_rwsem" }, -+ { .name = "&dinfo->di_rwsem" }, -+ { .name = "&iinfo->ii_rwsem" } -+ }; -+ static int set; -+ int i; -+ -+ /* lockless read from 'set.' see below */ -+ if (set == ARRAY_SIZE(a)) { -+ for (i = 0; i < ARRAY_SIZE(a); i++) -+ if (a[i].key == key) -+ goto match; -+ goto unmatch; -+ } -+ -+ spin_lock(&spin); -+ if (set) -+ for (i = 0; i < ARRAY_SIZE(a); i++) -+ if (a[i].key == key) { -+ spin_unlock(&spin); -+ goto match; -+ } -+ for (i = 0; i < ARRAY_SIZE(a); i++) { -+ if (a[i].key) { -+ if (unlikely(a[i].key == key)) { /* rare but possible */ -+ spin_unlock(&spin); -+ goto match; -+ } else -+ continue; -+ } -+ if (strstr(a[i].name, name)) { -+ /* -+ * the order of these three lines is important for the -+ * lockless read above. -+ */ -+ a[i].key = key; -+ spin_unlock(&spin); -+ set++; -+ /* AuDbg("%d, %s\n", set, name); */ -+ goto match; -+ } -+ } -+ spin_unlock(&spin); -+ goto unmatch; -+ -+match: -+ return 1; -+unmatch: -+ return 0; -+} -+ -+static int au_wkq_lockdep_alloc(struct au_wkinfo *wkinfo) -+{ -+ int err, n; -+ struct task_struct *curr; -+ struct held_lock **hl, *held_locks, *p; -+ -+ err = 0; -+ curr = current; -+ wkinfo->dont_check = lockdep_recursing(curr); -+ if (wkinfo->dont_check) -+ goto out; -+ n = curr->lockdep_depth; -+ if (!n) -+ goto out; -+ -+ err = -ENOMEM; -+ wkinfo->hlock = kmalloc_array(n + 1, sizeof(*wkinfo->hlock), GFP_NOFS); -+ if (unlikely(!wkinfo->hlock)) -+ goto out; -+ -+ err = 0; -+#if 0 /* left for debugging */ -+ if (0 && au_debug_test()) -+ lockdep_print_held_locks(curr); -+#endif -+ held_locks = curr->held_locks; -+ hl = wkinfo->hlock; -+ while (n--) { -+ p = held_locks++; -+ if (au_wkq_lockdep_test(p->instance->key, p->instance->name)) -+ *hl++ = p; -+ } -+ *hl = NULL; -+ -+out: -+ return err; -+} -+ -+static void au_wkq_lockdep_free(struct au_wkinfo *wkinfo) -+{ -+ au_kfree_try_rcu(wkinfo->hlock); -+} -+ -+static void au_wkq_lockdep_pre(struct au_wkinfo *wkinfo) -+{ -+ struct held_lock *p, **hl = wkinfo->hlock; -+ int subclass; -+ -+ if (wkinfo->dont_check) -+ lockdep_off(); -+ if (!hl) -+ return; -+ while ((p = *hl++)) { /* assignment */ -+ subclass = lockdep_hlock_class(p)->subclass; -+ /* AuDbg("%s, %d\n", p->instance->name, subclass); */ -+ if (p->read) -+ rwsem_acquire_read(p->instance, subclass, 0, -+ /*p->acquire_ip*/_RET_IP_); -+ else -+ rwsem_acquire(p->instance, subclass, 0, -+ /*p->acquire_ip*/_RET_IP_); -+ } -+} -+ -+static void au_wkq_lockdep_post(struct au_wkinfo *wkinfo) -+{ -+ struct held_lock *p, **hl = wkinfo->hlock; -+ -+ if (wkinfo->dont_check) -+ lockdep_on(); -+ if (!hl) -+ return; -+ while ((p = *hl++)) /* assignment */ -+ rwsem_release(p->instance, /*p->acquire_ip*/_RET_IP_); -+} -+#endif -+ -+static void wkq_func(struct work_struct *wk) -+{ -+ struct au_wkinfo *wkinfo = container_of(wk, struct au_wkinfo, wk); -+ -+ AuDebugOn(!uid_eq(current_fsuid(), GLOBAL_ROOT_UID)); -+ AuDebugOn(rlimit(RLIMIT_FSIZE) != RLIM_INFINITY); -+ -+ au_wkq_lockdep_pre(wkinfo); -+ wkinfo->func(wkinfo->args); -+ au_wkq_lockdep_post(wkinfo); -+ if (au_ftest_wkq(wkinfo->flags, WAIT)) -+ complete(wkinfo->comp); -+ else { -+ kobject_put(wkinfo->kobj); -+ module_put(THIS_MODULE); /* todo: ?? */ -+ au_kfree_rcu(wkinfo); -+ } -+} -+ -+/* -+ * Since struct completion is large, try allocating it dynamically. -+ */ -+#define AuWkqCompDeclare(name) struct completion *comp = NULL -+ -+static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp) -+{ -+ *comp = kmalloc(sizeof(**comp), GFP_NOFS); -+ if (*comp) { -+ init_completion(*comp); -+ wkinfo->comp = *comp; -+ return 0; -+ } -+ return -ENOMEM; -+} -+ -+static void au_wkq_comp_free(struct completion *comp) -+{ -+ au_kfree_rcu(comp); -+} -+ -+static void au_wkq_run(struct au_wkinfo *wkinfo) -+{ -+ if (au_ftest_wkq(wkinfo->flags, NEST)) { -+ if (au_wkq_test()) { -+ AuWarn1("wkq from wkq, unless silly-rename on NFS," -+ " due to a dead dir by UDBA," -+ " or async xino write?\n"); -+ AuDebugOn(au_ftest_wkq(wkinfo->flags, WAIT)); -+ } -+ } else -+ au_dbg_verify_kthread(); -+ -+ if (au_ftest_wkq(wkinfo->flags, WAIT)) { -+ INIT_WORK_ONSTACK(&wkinfo->wk, wkq_func); -+ queue_work(au_wkq, &wkinfo->wk); -+ } else { -+ INIT_WORK(&wkinfo->wk, wkq_func); -+ schedule_work(&wkinfo->wk); -+ } -+} -+ -+/* -+ * Be careful. It is easy to make deadlock happen. -+ * processA: lock, wkq and wait -+ * processB: wkq and wait, lock in wkq -+ * --> deadlock -+ */ -+int au_wkq_do_wait(unsigned int flags, au_wkq_func_t func, void *args) -+{ -+ int err; -+ AuWkqCompDeclare(comp); -+ struct au_wkinfo wkinfo = { -+ .flags = flags, -+ .func = func, -+ .args = args -+ }; -+ -+ err = au_wkq_comp_alloc(&wkinfo, &comp); -+ if (unlikely(err)) -+ goto out; -+ err = au_wkq_lockdep_alloc(&wkinfo); -+ if (unlikely(err)) -+ goto out_comp; -+ if (!err) { -+ au_wkq_run(&wkinfo); -+ /* no timeout, no interrupt */ -+ wait_for_completion(wkinfo.comp); -+ } -+ au_wkq_lockdep_free(&wkinfo); -+ -+out_comp: -+ au_wkq_comp_free(comp); -+out: -+ destroy_work_on_stack(&wkinfo.wk); -+ return err; -+} -+ -+/* -+ * Note: dget/dput() in func for aufs dentries are not supported. It will be a -+ * problem in a concurrent umounting. -+ */ -+int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb, -+ unsigned int flags) -+{ -+ int err; -+ struct au_wkinfo *wkinfo; -+ -+ atomic_inc(&au_sbi(sb)->si_nowait.nw_len); -+ -+ /* -+ * wkq_func() must free this wkinfo. -+ * it highly depends upon the implementation of workqueue. -+ */ -+ err = 0; -+ wkinfo = kmalloc(sizeof(*wkinfo), GFP_NOFS); -+ if (wkinfo) { -+ wkinfo->kobj = &au_sbi(sb)->si_kobj; -+ wkinfo->flags = flags & ~AuWkq_WAIT; -+ wkinfo->func = func; -+ wkinfo->args = args; -+ wkinfo->comp = NULL; -+ au_wkq_lockdep_init(wkinfo); -+ kobject_get(wkinfo->kobj); -+ __module_get(THIS_MODULE); /* todo: ?? */ -+ -+ au_wkq_run(wkinfo); -+ } else { -+ err = -ENOMEM; -+ au_nwt_done(&au_sbi(sb)->si_nowait); -+ } -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+void au_nwt_init(struct au_nowait_tasks *nwt) -+{ -+ atomic_set(&nwt->nw_len, 0); -+ /* smp_mb(); */ /* atomic_set */ -+ init_waitqueue_head(&nwt->nw_wq); -+} -+ -+void au_wkq_fin(void) -+{ -+ destroy_workqueue(au_wkq); -+} -+ -+int __init au_wkq_init(void) -+{ -+ int err; -+ -+ err = 0; -+ au_wkq = alloc_workqueue(AUFS_WKQ_NAME, 0, WQ_DFL_ACTIVE); -+ if (IS_ERR(au_wkq)) -+ err = PTR_ERR(au_wkq); -+ else if (!au_wkq) -+ err = -ENOMEM; -+ -+ return err; -+} -diff --git a/fs/aufs/wkq.h b/fs/aufs/wkq.h -new file mode 100644 -index 000000000000..850085fdd2d2 ---- /dev/null -+++ b/fs/aufs/wkq.h -@@ -0,0 +1,76 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * workqueue for asynchronous/super-io operations -+ * todo: try new credentials management scheme -+ */ -+ -+#ifndef __AUFS_WKQ_H__ -+#define __AUFS_WKQ_H__ -+ -+#ifdef __KERNEL__ -+ -+#include -+ -+struct super_block; -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * in the next operation, wait for the 'nowait' tasks in system-wide workqueue -+ */ -+struct au_nowait_tasks { -+ atomic_t nw_len; -+ wait_queue_head_t nw_wq; -+}; -+ -+/* ---------------------------------------------------------------------- */ -+ -+typedef void (*au_wkq_func_t)(void *args); -+ -+/* wkq flags */ -+#define AuWkq_WAIT 1 -+#define AuWkq_NEST (1 << 1) -+#define au_ftest_wkq(flags, name) ((flags) & AuWkq_##name) -+#define au_fset_wkq(flags, name) \ -+ do { (flags) |= AuWkq_##name; } while (0) -+#define au_fclr_wkq(flags, name) \ -+ do { (flags) &= ~AuWkq_##name; } while (0) -+ -+/* wkq.c */ -+int au_wkq_do_wait(unsigned int flags, au_wkq_func_t func, void *args); -+int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb, -+ unsigned int flags); -+void au_nwt_init(struct au_nowait_tasks *nwt); -+int __init au_wkq_init(void); -+void au_wkq_fin(void); -+ -+/* ---------------------------------------------------------------------- */ -+ -+static inline int au_wkq_test(void) -+{ -+ return current->flags & PF_WQ_WORKER; -+} -+ -+static inline int au_wkq_wait(au_wkq_func_t func, void *args) -+{ -+ return au_wkq_do_wait(AuWkq_WAIT, func, args); -+} -+ -+static inline void au_nwt_done(struct au_nowait_tasks *nwt) -+{ -+ if (atomic_dec_and_test(&nwt->nw_len)) -+ wake_up_all(&nwt->nw_wq); -+} -+ -+static inline int au_nwt_flush(struct au_nowait_tasks *nwt) -+{ -+ wait_event(nwt->nw_wq, !atomic_read(&nwt->nw_len)); -+ return 0; -+} -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_WKQ_H__ */ -diff --git a/fs/aufs/xattr.c b/fs/aufs/xattr.c -new file mode 100644 -index 000000000000..a71145b741b1 ---- /dev/null -+++ b/fs/aufs/xattr.c -@@ -0,0 +1,343 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2014-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * handling xattr functions -+ */ -+ -+#include -+#include -+#include -+#include "aufs.h" -+ -+static int au_xattr_ignore(int err, char *name, unsigned int ignore_flags) -+{ -+ if (!ignore_flags) -+ goto out; -+ switch (err) { -+ case -ENOMEM: -+ case -EDQUOT: -+ goto out; -+ } -+ -+ if ((ignore_flags & AuBrAttr_ICEX) == AuBrAttr_ICEX) { -+ err = 0; -+ goto out; -+ } -+ -+#define cmp(brattr, prefix) do { \ -+ if (!strncmp(name, XATTR_##prefix##_PREFIX, \ -+ XATTR_##prefix##_PREFIX_LEN)) { \ -+ if (ignore_flags & AuBrAttr_ICEX_##brattr) \ -+ err = 0; \ -+ goto out; \ -+ } \ -+ } while (0) -+ -+ cmp(SEC, SECURITY); -+ cmp(SYS, SYSTEM); -+ cmp(TR, TRUSTED); -+ cmp(USR, USER); -+#undef cmp -+ -+ if (ignore_flags & AuBrAttr_ICEX_OTH) -+ err = 0; -+ -+out: -+ return err; -+} -+ -+static const int au_xattr_out_of_list = AuBrAttr_ICEX_OTH << 1; -+ -+static int au_do_cpup_xattr(struct dentry *h_dst, struct dentry *h_src, -+ char *name, char **buf, unsigned int ignore_flags, -+ unsigned int verbose) -+{ -+ int err; -+ ssize_t ssz; -+ struct inode *h_idst; -+ -+ ssz = vfs_getxattr_alloc(h_src, name, buf, 0, GFP_NOFS); -+ err = ssz; -+ if (unlikely(err <= 0)) { -+ if (err == -ENODATA -+ || (err == -EOPNOTSUPP -+ && ((ignore_flags & au_xattr_out_of_list) -+ || (au_test_nfs_noacl(d_inode(h_src)) -+ && (!strcmp(name, XATTR_NAME_POSIX_ACL_ACCESS) -+ || !strcmp(name, -+ XATTR_NAME_POSIX_ACL_DEFAULT)))) -+ )) -+ err = 0; -+ if (err && (verbose || au_debug_test())) -+ pr_err("%s, err %d\n", name, err); -+ goto out; -+ } -+ -+ /* unlock it temporary */ -+ h_idst = d_inode(h_dst); -+ inode_unlock(h_idst); -+ err = vfsub_setxattr(h_dst, name, *buf, ssz, /*flags*/0); -+ inode_lock_nested(h_idst, AuLsc_I_CHILD2); -+ if (unlikely(err)) { -+ if (verbose || au_debug_test()) -+ pr_err("%s, err %d\n", name, err); -+ err = au_xattr_ignore(err, name, ignore_flags); -+ } -+ -+out: -+ return err; -+} -+ -+int au_cpup_xattr(struct dentry *h_dst, struct dentry *h_src, int ignore_flags, -+ unsigned int verbose) -+{ -+ int err, unlocked, acl_access, acl_default; -+ ssize_t ssz; -+ struct inode *h_isrc, *h_idst; -+ char *value, *p, *o, *e; -+ -+ /* try stopping to update the source inode while we are referencing */ -+ /* there should not be the parent-child relationship between them */ -+ h_isrc = d_inode(h_src); -+ h_idst = d_inode(h_dst); -+ inode_unlock(h_idst); -+ inode_lock_shared_nested(h_isrc, AuLsc_I_CHILD); -+ inode_lock_nested(h_idst, AuLsc_I_CHILD2); -+ unlocked = 0; -+ -+ /* some filesystems don't list POSIX ACL, for example tmpfs */ -+ ssz = vfs_listxattr(h_src, NULL, 0); -+ err = ssz; -+ if (unlikely(err < 0)) { -+ AuTraceErr(err); -+ if (err == -ENODATA -+ || err == -EOPNOTSUPP) -+ err = 0; /* ignore */ -+ goto out; -+ } -+ -+ err = 0; -+ p = NULL; -+ o = NULL; -+ if (ssz) { -+ err = -ENOMEM; -+ p = kmalloc(ssz, GFP_NOFS); -+ o = p; -+ if (unlikely(!p)) -+ goto out; -+ err = vfs_listxattr(h_src, p, ssz); -+ } -+ inode_unlock_shared(h_isrc); -+ unlocked = 1; -+ AuDbg("err %d, ssz %zd\n", err, ssz); -+ if (unlikely(err < 0)) -+ goto out_free; -+ -+ err = 0; -+ e = p + ssz; -+ value = NULL; -+ acl_access = 0; -+ acl_default = 0; -+ while (!err && p < e) { -+ acl_access |= !strncmp(p, XATTR_NAME_POSIX_ACL_ACCESS, -+ sizeof(XATTR_NAME_POSIX_ACL_ACCESS) - 1); -+ acl_default |= !strncmp(p, XATTR_NAME_POSIX_ACL_DEFAULT, -+ sizeof(XATTR_NAME_POSIX_ACL_DEFAULT) -+ - 1); -+ err = au_do_cpup_xattr(h_dst, h_src, p, &value, ignore_flags, -+ verbose); -+ p += strlen(p) + 1; -+ } -+ AuTraceErr(err); -+ ignore_flags |= au_xattr_out_of_list; -+ if (!err && !acl_access) { -+ err = au_do_cpup_xattr(h_dst, h_src, -+ XATTR_NAME_POSIX_ACL_ACCESS, &value, -+ ignore_flags, verbose); -+ AuTraceErr(err); -+ } -+ if (!err && !acl_default) { -+ err = au_do_cpup_xattr(h_dst, h_src, -+ XATTR_NAME_POSIX_ACL_DEFAULT, &value, -+ ignore_flags, verbose); -+ AuTraceErr(err); -+ } -+ -+ au_kfree_try_rcu(value); -+ -+out_free: -+ au_kfree_try_rcu(o); -+out: -+ if (!unlocked) -+ inode_unlock_shared(h_isrc); -+ AuTraceErr(err); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int au_smack_reentering(struct super_block *sb) -+{ -+#if IS_ENABLED(CONFIG_SECURITY_SMACK) || IS_ENABLED(CONFIG_SECURITY_SELINUX) -+ /* -+ * as a part of lookup, smack_d_instantiate() is called, and it calls -+ * i_op->getxattr(). ouch. -+ */ -+ return si_pid_test(sb); -+#else -+ return 0; -+#endif -+} -+ -+enum { -+ AU_XATTR_LIST, -+ AU_XATTR_GET -+}; -+ -+struct au_lgxattr { -+ int type; -+ union { -+ struct { -+ char *list; -+ size_t size; -+ } list; -+ struct { -+ const char *name; -+ void *value; -+ size_t size; -+ } get; -+ } u; -+}; -+ -+static ssize_t au_lgxattr(struct dentry *dentry, struct inode *inode, -+ struct au_lgxattr *arg) -+{ -+ ssize_t err; -+ int reenter; -+ struct path h_path; -+ struct super_block *sb; -+ -+ sb = dentry->d_sb; -+ reenter = au_smack_reentering(sb); -+ if (!reenter) { -+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM); -+ if (unlikely(err)) -+ goto out; -+ } -+ err = au_h_path_getattr(dentry, inode, /*force*/1, &h_path, reenter); -+ if (unlikely(err)) -+ goto out_si; -+ if (unlikely(!h_path.dentry)) -+ /* illegally overlapped or something */ -+ goto out_di; /* pretending success */ -+ -+ /* always topmost entry only */ -+ switch (arg->type) { -+ case AU_XATTR_LIST: -+ err = vfs_listxattr(h_path.dentry, -+ arg->u.list.list, arg->u.list.size); -+ break; -+ case AU_XATTR_GET: -+ AuDebugOn(d_is_negative(h_path.dentry)); -+ err = vfs_getxattr(h_path.dentry, -+ arg->u.get.name, arg->u.get.value, -+ arg->u.get.size); -+ break; -+ } -+ -+out_di: -+ if (!reenter) -+ di_read_unlock(dentry, AuLock_IR); -+out_si: -+ if (!reenter) -+ si_read_unlock(sb); -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+ssize_t aufs_listxattr(struct dentry *dentry, char *list, size_t size) -+{ -+ struct au_lgxattr arg = { -+ .type = AU_XATTR_LIST, -+ .u.list = { -+ .list = list, -+ .size = size -+ }, -+ }; -+ -+ return au_lgxattr(dentry, /*inode*/NULL, &arg); -+} -+ -+static ssize_t au_getxattr(struct dentry *dentry, struct inode *inode, -+ const char *name, void *value, size_t size) -+{ -+ struct au_lgxattr arg = { -+ .type = AU_XATTR_GET, -+ .u.get = { -+ .name = name, -+ .value = value, -+ .size = size -+ }, -+ }; -+ -+ return au_lgxattr(dentry, inode, &arg); -+} -+ -+static int au_setxattr(struct dentry *dentry, struct inode *inode, -+ const char *name, const void *value, size_t size, -+ int flags) -+{ -+ struct au_sxattr arg = { -+ .type = AU_XATTR_SET, -+ .u.set = { -+ .name = name, -+ .value = value, -+ .size = size, -+ .flags = flags -+ }, -+ }; -+ -+ return au_sxattr(dentry, inode, &arg); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int au_xattr_get(const struct xattr_handler *handler, -+ struct dentry *dentry, struct inode *inode, -+ const char *name, void *buffer, size_t size) -+{ -+ return au_getxattr(dentry, inode, name, buffer, size); -+} -+ -+static int au_xattr_set(const struct xattr_handler *handler, -+ struct dentry *dentry, struct inode *inode, -+ const char *name, const void *value, size_t size, -+ int flags) -+{ -+ return au_setxattr(dentry, inode, name, value, size, flags); -+} -+ -+static const struct xattr_handler au_xattr_handler = { -+ .name = "", -+ .prefix = "", -+ .get = au_xattr_get, -+ .set = au_xattr_set -+}; -+ -+static const struct xattr_handler *au_xattr_handlers[] = { -+#ifdef CONFIG_FS_POSIX_ACL -+ &posix_acl_access_xattr_handler, -+ &posix_acl_default_xattr_handler, -+#endif -+ &au_xattr_handler, /* must be last */ -+ NULL -+}; -+ -+void au_xattr_init(struct super_block *sb) -+{ -+ sb->s_xattr = au_xattr_handlers; -+} -diff --git a/fs/aufs/xino.c b/fs/aufs/xino.c -new file mode 100644 -index 000000000000..ad2895dd6055 ---- /dev/null -+++ b/fs/aufs/xino.c -@@ -0,0 +1,1953 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * external inode number translation table and bitmap -+ * -+ * things to consider -+ * - the lifetime -+ * + au_xino object -+ * + XINO files (xino, xib, xigen) -+ * + dynamic debugfs entries (xiN) -+ * + static debugfs entries (xib, xigen) -+ * + static sysfs entry (xi_path) -+ * - several entry points to handle them. -+ * + mount(2) without xino option (default) -+ * + mount(2) with xino option -+ * + mount(2) with noxino option -+ * + umount(2) -+ * + remount with add/del branches -+ * + remount with xino/noxino options -+ */ -+ -+#include -+#include -+#include "aufs.h" -+ -+static aufs_bindex_t sbr_find_shared(struct super_block *sb, aufs_bindex_t btop, -+ aufs_bindex_t bbot, -+ struct super_block *h_sb) -+{ -+ /* todo: try binary-search if the branches are many */ -+ for (; btop <= bbot; btop++) -+ if (h_sb == au_sbr_sb(sb, btop)) -+ return btop; -+ return -1; -+} -+ -+/* -+ * find another branch who is on the same filesystem of the specified -+ * branch{@btgt}. search until @bbot. -+ */ -+static aufs_bindex_t is_sb_shared(struct super_block *sb, aufs_bindex_t btgt, -+ aufs_bindex_t bbot) -+{ -+ aufs_bindex_t bindex; -+ struct super_block *tgt_sb; -+ -+ tgt_sb = au_sbr_sb(sb, btgt); -+ bindex = sbr_find_shared(sb, /*btop*/0, btgt - 1, tgt_sb); -+ if (bindex < 0) -+ bindex = sbr_find_shared(sb, btgt + 1, bbot, tgt_sb); -+ -+ return bindex; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * stop unnecessary notify events at creating xino files -+ */ -+ -+aufs_bindex_t au_xi_root(struct super_block *sb, struct dentry *dentry) -+{ -+ aufs_bindex_t bfound, bindex, bbot; -+ struct dentry *parent; -+ struct au_branch *br; -+ -+ bfound = -1; -+ parent = dentry->d_parent; /* safe d_parent access */ -+ bbot = au_sbbot(sb); -+ for (bindex = 0; bindex <= bbot; bindex++) { -+ br = au_sbr(sb, bindex); -+ if (au_br_dentry(br) == parent) { -+ bfound = bindex; -+ break; -+ } -+ } -+ -+ AuDbg("bfound b%d\n", bfound); -+ return bfound; -+} -+ -+struct au_xino_lock_dir { -+ struct au_hinode *hdir; -+ struct dentry *parent; -+ struct inode *dir; -+}; -+ -+static struct dentry *au_dget_parent_lock(struct dentry *dentry, -+ unsigned int lsc) -+{ -+ struct dentry *parent; -+ struct inode *dir; -+ -+ parent = dget_parent(dentry); -+ dir = d_inode(parent); -+ inode_lock_nested(dir, lsc); -+#if 0 /* it should not happen */ -+ spin_lock(&dentry->d_lock); -+ if (unlikely(dentry->d_parent != parent)) { -+ spin_unlock(&dentry->d_lock); -+ inode_unlock(dir); -+ dput(parent); -+ parent = NULL; -+ goto out; -+ } -+ spin_unlock(&dentry->d_lock); -+ -+out: -+#endif -+ return parent; -+} -+ -+static void au_xino_lock_dir(struct super_block *sb, struct path *xipath, -+ struct au_xino_lock_dir *ldir) -+{ -+ aufs_bindex_t bindex; -+ -+ ldir->hdir = NULL; -+ bindex = au_xi_root(sb, xipath->dentry); -+ if (bindex >= 0) { -+ /* rw branch root */ -+ ldir->hdir = au_hi(d_inode(sb->s_root), bindex); -+ au_hn_inode_lock_nested(ldir->hdir, AuLsc_I_PARENT); -+ } else { -+ /* other */ -+ ldir->parent = au_dget_parent_lock(xipath->dentry, -+ AuLsc_I_PARENT); -+ ldir->dir = d_inode(ldir->parent); -+ } -+} -+ -+static void au_xino_unlock_dir(struct au_xino_lock_dir *ldir) -+{ -+ if (ldir->hdir) -+ au_hn_inode_unlock(ldir->hdir); -+ else { -+ inode_unlock(ldir->dir); -+ dput(ldir->parent); -+ } -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * create and set a new xino file -+ */ -+struct file *au_xino_create(struct super_block *sb, char *fpath, int silent, -+ int wbrtop) -+{ -+ struct file *file; -+ struct dentry *h_parent, *d; -+ struct inode *h_dir, *inode; -+ int err; -+ static DEFINE_MUTEX(mtx); -+ -+ /* -+ * at mount-time, and the xino file is the default path, -+ * hnotify is disabled so we have no notify events to ignore. -+ * when a user specified the xino, we cannot get au_hdir to be ignored. -+ */ -+ if (!wbrtop) -+ mutex_lock(&mtx); -+ file = vfsub_filp_open(fpath, O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE -+ /* | __FMODE_NONOTIFY */, -+ 0666); -+ if (IS_ERR(file)) { -+ if (!wbrtop) -+ mutex_unlock(&mtx); -+ if (!silent) -+ pr_err("open %s(%ld)\n", fpath, PTR_ERR(file)); -+ return file; -+ } -+ -+ /* keep file count */ -+ err = 0; -+ d = file->f_path.dentry; -+ h_parent = au_dget_parent_lock(d, AuLsc_I_PARENT); -+ if (!wbrtop) -+ mutex_unlock(&mtx); -+ /* mnt_want_write() is unnecessary here */ -+ h_dir = d_inode(h_parent); -+ inode = file_inode(file); -+ /* no delegation since it is just created */ -+ if (inode->i_nlink) -+ err = vfsub_unlink(h_dir, &file->f_path, /*delegated*/NULL, -+ /*force*/0); -+ inode_unlock(h_dir); -+ dput(h_parent); -+ if (unlikely(err)) { -+ if (!silent) -+ pr_err("unlink %s(%d)\n", fpath, err); -+ goto out; -+ } -+ -+ err = -EINVAL; -+ if (unlikely(sb == d->d_sb)) { -+ if (!silent) -+ pr_err("%s must be outside\n", fpath); -+ goto out; -+ } -+ if (unlikely(au_test_fs_bad_xino(d->d_sb))) { -+ if (!silent) -+ pr_err("xino doesn't support %s(%s)\n", -+ fpath, au_sbtype(d->d_sb)); -+ goto out; -+ } -+ return file; /* success */ -+ -+out: -+ fput(file); -+ file = ERR_PTR(err); -+ return file; -+} -+ -+/* -+ * create a new xinofile at the same place/path as @base. -+ */ -+struct file *au_xino_create2(struct super_block *sb, struct path *base, -+ struct file *copy_src) -+{ -+ struct file *file; -+ struct dentry *dentry, *parent; -+ struct inode *dir, *delegated; -+ struct qstr *name; -+ struct path path; -+ int err, do_unlock; -+ struct au_xino_lock_dir ldir; -+ -+ do_unlock = 1; -+ au_xino_lock_dir(sb, base, &ldir); -+ dentry = base->dentry; -+ parent = dentry->d_parent; /* dir inode is locked */ -+ dir = d_inode(parent); -+ IMustLock(dir); -+ -+ name = &dentry->d_name; -+ path.dentry = vfsub_lookup_one_len(name->name, parent, name->len); -+ if (IS_ERR(path.dentry)) { -+ file = (void *)path.dentry; -+ pr_err("%pd lookup err %ld\n", dentry, PTR_ERR(path.dentry)); -+ goto out; -+ } -+ -+ /* no need to mnt_want_write() since we call dentry_open() later */ -+ err = vfs_create(dir, path.dentry, 0666, NULL); -+ if (unlikely(err)) { -+ file = ERR_PTR(err); -+ pr_err("%pd create err %d\n", dentry, err); -+ goto out_dput; -+ } -+ -+ path.mnt = base->mnt; -+ file = vfsub_dentry_open(&path, -+ O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE -+ /* | __FMODE_NONOTIFY */); -+ if (IS_ERR(file)) { -+ pr_err("%pd open err %ld\n", dentry, PTR_ERR(file)); -+ goto out_dput; -+ } -+ -+ delegated = NULL; -+ err = vfsub_unlink(dir, &file->f_path, &delegated, /*force*/0); -+ au_xino_unlock_dir(&ldir); -+ do_unlock = 0; -+ if (unlikely(err == -EWOULDBLOCK)) { -+ pr_warn("cannot retry for NFSv4 delegation" -+ " for an internal unlink\n"); -+ iput(delegated); -+ } -+ if (unlikely(err)) { -+ pr_err("%pd unlink err %d\n", dentry, err); -+ goto out_fput; -+ } -+ -+ if (copy_src) { -+ /* no one can touch copy_src xino */ -+ err = au_copy_file(file, copy_src, vfsub_f_size_read(copy_src)); -+ if (unlikely(err)) { -+ pr_err("%pd copy err %d\n", dentry, err); -+ goto out_fput; -+ } -+ } -+ goto out_dput; /* success */ -+ -+out_fput: -+ fput(file); -+ file = ERR_PTR(err); -+out_dput: -+ dput(path.dentry); -+out: -+ if (do_unlock) -+ au_xino_unlock_dir(&ldir); -+ return file; -+} -+ -+struct file *au_xino_file1(struct au_xino *xi) -+{ -+ struct file *file; -+ unsigned int u, nfile; -+ -+ file = NULL; -+ nfile = xi->xi_nfile; -+ for (u = 0; u < nfile; u++) { -+ file = xi->xi_file[u]; -+ if (file) -+ break; -+ } -+ -+ return file; -+} -+ -+static int au_xino_file_set(struct au_xino *xi, int idx, struct file *file) -+{ -+ int err; -+ struct file *f; -+ void *p; -+ -+ if (file) -+ get_file(file); -+ -+ err = 0; -+ f = NULL; -+ if (idx < xi->xi_nfile) { -+ f = xi->xi_file[idx]; -+ if (f) -+ fput(f); -+ } else { -+ p = au_kzrealloc(xi->xi_file, -+ sizeof(*xi->xi_file) * xi->xi_nfile, -+ sizeof(*xi->xi_file) * (idx + 1), -+ GFP_NOFS, /*may_shrink*/0); -+ if (p) { -+ MtxMustLock(&xi->xi_mtx); -+ xi->xi_file = p; -+ xi->xi_nfile = idx + 1; -+ } else { -+ err = -ENOMEM; -+ if (file) -+ fput(file); -+ goto out; -+ } -+ } -+ xi->xi_file[idx] = file; -+ -+out: -+ return err; -+} -+ -+/* -+ * if @xinew->xi is not set, then create new xigen file. -+ */ -+struct file *au_xi_new(struct super_block *sb, struct au_xi_new *xinew) -+{ -+ struct file *file; -+ int err; -+ -+ SiMustAnyLock(sb); -+ -+ file = au_xino_create2(sb, xinew->base, xinew->copy_src); -+ if (IS_ERR(file)) { -+ err = PTR_ERR(file); -+ pr_err("%s[%d], err %d\n", -+ xinew->xi ? "xino" : "xigen", -+ xinew->idx, err); -+ goto out; -+ } -+ -+ if (xinew->xi) -+ err = au_xino_file_set(xinew->xi, xinew->idx, file); -+ else { -+ BUG(); -+ /* todo: make xigen file an array */ -+ /* err = au_xigen_file_set(sb, xinew->idx, file); */ -+ } -+ fput(file); -+ if (unlikely(err)) -+ file = ERR_PTR(err); -+ -+out: -+ return file; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * truncate xino files -+ */ -+static int au_xino_do_trunc(struct super_block *sb, aufs_bindex_t bindex, -+ int idx, struct kstatfs *st) -+{ -+ int err; -+ blkcnt_t blocks; -+ struct file *file, *new_xino; -+ struct au_xi_new xinew = { -+ .idx = idx -+ }; -+ -+ err = 0; -+ xinew.xi = au_sbr(sb, bindex)->br_xino; -+ file = au_xino_file(xinew.xi, idx); -+ if (!file) -+ goto out; -+ -+ xinew.base = &file->f_path; -+ err = vfs_statfs(xinew.base, st); -+ if (unlikely(err)) { -+ AuErr1("statfs err %d, ignored\n", err); -+ err = 0; -+ goto out; -+ } -+ -+ blocks = file_inode(file)->i_blocks; -+ pr_info("begin truncating xino(b%d-%d), ib%llu, %llu/%llu free blks\n", -+ bindex, idx, (u64)blocks, st->f_bfree, st->f_blocks); -+ -+ xinew.copy_src = file; -+ new_xino = au_xi_new(sb, &xinew); -+ if (IS_ERR(new_xino)) { -+ err = PTR_ERR(new_xino); -+ pr_err("xino(b%d-%d), err %d, ignored\n", bindex, idx, err); -+ goto out; -+ } -+ -+ err = vfs_statfs(&new_xino->f_path, st); -+ if (!err) -+ pr_info("end truncating xino(b%d-%d), ib%llu, %llu/%llu free blks\n", -+ bindex, idx, (u64)file_inode(new_xino)->i_blocks, -+ st->f_bfree, st->f_blocks); -+ else { -+ AuErr1("statfs err %d, ignored\n", err); -+ err = 0; -+ } -+ -+out: -+ return err; -+} -+ -+int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex, int idx_begin) -+{ -+ int err, i; -+ unsigned long jiffy; -+ aufs_bindex_t bbot; -+ struct kstatfs *st; -+ struct au_branch *br; -+ struct au_xino *xi; -+ -+ err = -ENOMEM; -+ st = kmalloc(sizeof(*st), GFP_NOFS); -+ if (unlikely(!st)) -+ goto out; -+ -+ err = -EINVAL; -+ bbot = au_sbbot(sb); -+ if (unlikely(bindex < 0 || bbot < bindex)) -+ goto out_st; -+ -+ err = 0; -+ jiffy = jiffies; -+ br = au_sbr(sb, bindex); -+ xi = br->br_xino; -+ for (i = idx_begin; !err && i < xi->xi_nfile; i++) -+ err = au_xino_do_trunc(sb, bindex, i, st); -+ if (!err) -+ au_sbi(sb)->si_xino_jiffy = jiffy; -+ -+out_st: -+ au_kfree_rcu(st); -+out: -+ return err; -+} -+ -+struct xino_do_trunc_args { -+ struct super_block *sb; -+ struct au_branch *br; -+ int idx; -+}; -+ -+static void xino_do_trunc(void *_args) -+{ -+ struct xino_do_trunc_args *args = _args; -+ struct super_block *sb; -+ struct au_branch *br; -+ struct inode *dir; -+ int err, idx; -+ aufs_bindex_t bindex; -+ -+ err = 0; -+ sb = args->sb; -+ dir = d_inode(sb->s_root); -+ br = args->br; -+ idx = args->idx; -+ -+ si_noflush_write_lock(sb); -+ ii_read_lock_parent(dir); -+ bindex = au_br_index(sb, br->br_id); -+ err = au_xino_trunc(sb, bindex, idx); -+ ii_read_unlock(dir); -+ if (unlikely(err)) -+ pr_warn("err b%d, (%d)\n", bindex, err); -+ atomic_dec(&br->br_xino->xi_truncating); -+ au_lcnt_dec(&br->br_count); -+ si_write_unlock(sb); -+ au_nwt_done(&au_sbi(sb)->si_nowait); -+ au_kfree_rcu(args); -+} -+ -+/* -+ * returns the index in the xi_file array whose corresponding file is necessary -+ * to truncate, or -1 which means no need to truncate. -+ */ -+static int xino_trunc_test(struct super_block *sb, struct au_branch *br) -+{ -+ int err; -+ unsigned int u; -+ struct kstatfs st; -+ struct au_sbinfo *sbinfo; -+ struct au_xino *xi; -+ struct file *file; -+ -+ /* todo: si_xino_expire and the ratio should be customizable */ -+ sbinfo = au_sbi(sb); -+ if (time_before(jiffies, -+ sbinfo->si_xino_jiffy + sbinfo->si_xino_expire)) -+ return -1; -+ -+ /* truncation border */ -+ xi = br->br_xino; -+ for (u = 0; u < xi->xi_nfile; u++) { -+ file = au_xino_file(xi, u); -+ if (!file) -+ continue; -+ -+ err = vfs_statfs(&file->f_path, &st); -+ if (unlikely(err)) { -+ AuErr1("statfs err %d, ignored\n", err); -+ return -1; -+ } -+ if (div64_u64(st.f_bfree * 100, st.f_blocks) -+ >= AUFS_XINO_DEF_TRUNC) -+ return u; -+ } -+ -+ return -1; -+} -+ -+static void xino_try_trunc(struct super_block *sb, struct au_branch *br) -+{ -+ int idx; -+ struct xino_do_trunc_args *args; -+ int wkq_err; -+ -+ idx = xino_trunc_test(sb, br); -+ if (idx < 0) -+ return; -+ -+ if (atomic_inc_return(&br->br_xino->xi_truncating) > 1) -+ goto out; -+ -+ /* lock and kfree() will be called in trunc_xino() */ -+ args = kmalloc(sizeof(*args), GFP_NOFS); -+ if (unlikely(!args)) { -+ AuErr1("no memory\n"); -+ goto out; -+ } -+ -+ au_lcnt_inc(&br->br_count); -+ args->sb = sb; -+ args->br = br; -+ args->idx = idx; -+ wkq_err = au_wkq_nowait(xino_do_trunc, args, sb, /*flags*/0); -+ if (!wkq_err) -+ return; /* success */ -+ -+ pr_err("wkq %d\n", wkq_err); -+ au_lcnt_dec(&br->br_count); -+ au_kfree_rcu(args); -+ -+out: -+ atomic_dec(&br->br_xino->xi_truncating); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct au_xi_calc { -+ int idx; -+ loff_t pos; -+}; -+ -+static void au_xi_calc(struct super_block *sb, ino_t h_ino, -+ struct au_xi_calc *calc) -+{ -+ loff_t maxent; -+ -+ maxent = au_xi_maxent(sb); -+ calc->idx = div64_u64_rem(h_ino, maxent, &calc->pos); -+ calc->pos *= sizeof(ino_t); -+} -+ -+static int au_xino_do_new_async(struct super_block *sb, struct au_branch *br, -+ struct au_xi_calc *calc) -+{ -+ int err; -+ struct file *file; -+ struct au_xino *xi = br->br_xino; -+ struct au_xi_new xinew = { -+ .xi = xi -+ }; -+ -+ SiMustAnyLock(sb); -+ -+ err = 0; -+ if (!xi) -+ goto out; -+ -+ mutex_lock(&xi->xi_mtx); -+ file = au_xino_file(xi, calc->idx); -+ if (file) -+ goto out_mtx; -+ -+ file = au_xino_file(xi, /*idx*/-1); -+ AuDebugOn(!file); -+ xinew.idx = calc->idx; -+ xinew.base = &file->f_path; -+ /* xinew.copy_src = NULL; */ -+ file = au_xi_new(sb, &xinew); -+ if (IS_ERR(file)) -+ err = PTR_ERR(file); -+ -+out_mtx: -+ mutex_unlock(&xi->xi_mtx); -+out: -+ return err; -+} -+ -+struct au_xino_do_new_async_args { -+ struct super_block *sb; -+ struct au_branch *br; -+ struct au_xi_calc calc; -+ ino_t ino; -+}; -+ -+struct au_xi_writing { -+ struct hlist_bl_node node; -+ ino_t h_ino, ino; -+}; -+ -+static int au_xino_do_write(vfs_writef_t write, struct file *file, -+ struct au_xi_calc *calc, ino_t ino); -+ -+static void au_xino_call_do_new_async(void *args) -+{ -+ struct au_xino_do_new_async_args *a = args; -+ struct au_branch *br; -+ struct super_block *sb; -+ struct au_sbinfo *sbi; -+ struct inode *root; -+ struct file *file; -+ struct au_xi_writing *del, *p; -+ struct hlist_bl_head *hbl; -+ struct hlist_bl_node *pos; -+ int err; -+ -+ br = a->br; -+ sb = a->sb; -+ sbi = au_sbi(sb); -+ si_noflush_read_lock(sb); -+ root = d_inode(sb->s_root); -+ ii_read_lock_child(root); -+ err = au_xino_do_new_async(sb, br, &a->calc); -+ if (unlikely(err)) { -+ AuIOErr("err %d\n", err); -+ goto out; -+ } -+ -+ file = au_xino_file(br->br_xino, a->calc.idx); -+ AuDebugOn(!file); -+ err = au_xino_do_write(sbi->si_xwrite, file, &a->calc, a->ino); -+ if (unlikely(err)) { -+ AuIOErr("err %d\n", err); -+ goto out; -+ } -+ -+ del = NULL; -+ hbl = &br->br_xino->xi_writing; -+ hlist_bl_lock(hbl); -+ au_hbl_for_each(pos, hbl) { -+ p = container_of(pos, struct au_xi_writing, node); -+ if (p->ino == a->ino) { -+ del = p; -+ hlist_bl_del(&p->node); -+ break; -+ } -+ } -+ hlist_bl_unlock(hbl); -+ au_kfree_rcu(del); -+ -+out: -+ au_lcnt_dec(&br->br_count); -+ ii_read_unlock(root); -+ si_read_unlock(sb); -+ au_nwt_done(&sbi->si_nowait); -+ au_kfree_rcu(a); -+} -+ -+/* -+ * create a new xino file asynchronously -+ */ -+static int au_xino_new_async(struct super_block *sb, struct au_branch *br, -+ struct au_xi_calc *calc, ino_t ino) -+{ -+ int err; -+ struct au_xino_do_new_async_args *arg; -+ -+ err = -ENOMEM; -+ arg = kmalloc(sizeof(*arg), GFP_NOFS); -+ if (unlikely(!arg)) -+ goto out; -+ -+ arg->sb = sb; -+ arg->br = br; -+ arg->calc = *calc; -+ arg->ino = ino; -+ au_lcnt_inc(&br->br_count); -+ err = au_wkq_nowait(au_xino_call_do_new_async, arg, sb, AuWkq_NEST); -+ if (unlikely(err)) { -+ pr_err("wkq %d\n", err); -+ au_lcnt_dec(&br->br_count); -+ au_kfree_rcu(arg); -+ } -+ -+out: -+ return err; -+} -+ -+/* -+ * read @ino from xinofile for the specified branch{@sb, @bindex} -+ * at the position of @h_ino. -+ */ -+int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, -+ ino_t *ino) -+{ -+ int err; -+ ssize_t sz; -+ struct au_xi_calc calc; -+ struct au_sbinfo *sbinfo; -+ struct file *file; -+ struct au_xino *xi; -+ struct hlist_bl_head *hbl; -+ struct hlist_bl_node *pos; -+ struct au_xi_writing *p; -+ -+ *ino = 0; -+ if (!au_opt_test(au_mntflags(sb), XINO)) -+ return 0; /* no xino */ -+ -+ err = 0; -+ au_xi_calc(sb, h_ino, &calc); -+ xi = au_sbr(sb, bindex)->br_xino; -+ file = au_xino_file(xi, calc.idx); -+ if (!file) { -+ hbl = &xi->xi_writing; -+ hlist_bl_lock(hbl); -+ au_hbl_for_each(pos, hbl) { -+ p = container_of(pos, struct au_xi_writing, node); -+ if (p->h_ino == h_ino) { -+ AuDbg("hi%llu, i%llu, found\n", -+ (u64)p->h_ino, (u64)p->ino); -+ *ino = p->ino; -+ break; -+ } -+ } -+ hlist_bl_unlock(hbl); -+ return 0; -+ } else if (vfsub_f_size_read(file) < calc.pos + sizeof(*ino)) -+ return 0; /* no xino */ -+ -+ sbinfo = au_sbi(sb); -+ sz = xino_fread(sbinfo->si_xread, file, ino, sizeof(*ino), &calc.pos); -+ if (sz == sizeof(*ino)) -+ return 0; /* success */ -+ -+ err = sz; -+ if (unlikely(sz >= 0)) { -+ err = -EIO; -+ AuIOErr("xino read error (%zd)\n", sz); -+ } -+ return err; -+} -+ -+static int au_xino_do_write(vfs_writef_t write, struct file *file, -+ struct au_xi_calc *calc, ino_t ino) -+{ -+ ssize_t sz; -+ -+ sz = xino_fwrite(write, file, &ino, sizeof(ino), &calc->pos); -+ if (sz == sizeof(ino)) -+ return 0; /* success */ -+ -+ AuIOErr("write failed (%zd)\n", sz); -+ return -EIO; -+} -+ -+/* -+ * write @ino to the xinofile for the specified branch{@sb, @bindex} -+ * at the position of @h_ino. -+ * even if @ino is zero, it is written to the xinofile and means no entry. -+ * if the size of the xino file on a specific filesystem exceeds the watermark, -+ * try truncating it. -+ */ -+int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, -+ ino_t ino) -+{ -+ int err; -+ unsigned int mnt_flags; -+ struct au_xi_calc calc; -+ struct file *file; -+ struct au_branch *br; -+ struct au_xino *xi; -+ struct au_xi_writing *p; -+ -+ SiMustAnyLock(sb); -+ -+ mnt_flags = au_mntflags(sb); -+ if (!au_opt_test(mnt_flags, XINO)) -+ return 0; -+ -+ au_xi_calc(sb, h_ino, &calc); -+ br = au_sbr(sb, bindex); -+ xi = br->br_xino; -+ file = au_xino_file(xi, calc.idx); -+ if (!file) { -+ /* store the inum pair into the list */ -+ p = kmalloc(sizeof(*p), GFP_NOFS | __GFP_NOFAIL); -+ p->h_ino = h_ino; -+ p->ino = ino; -+ au_hbl_add(&p->node, &xi->xi_writing); -+ -+ /* create and write a new xino file asynchronously */ -+ err = au_xino_new_async(sb, br, &calc, ino); -+ if (!err) -+ return 0; /* success */ -+ goto out; -+ } -+ -+ err = au_xino_do_write(au_sbi(sb)->si_xwrite, file, &calc, ino); -+ if (!err) { -+ br = au_sbr(sb, bindex); -+ if (au_opt_test(mnt_flags, TRUNC_XINO) -+ && au_test_fs_trunc_xino(au_br_sb(br))) -+ xino_try_trunc(sb, br); -+ return 0; /* success */ -+ } -+ -+out: -+ AuIOErr("write failed (%d)\n", err); -+ return -EIO; -+} -+ -+static ssize_t xino_fread_wkq(vfs_readf_t func, struct file *file, void *buf, -+ size_t size, loff_t *pos); -+ -+/* todo: unnecessary to support mmap_sem since kernel-space? */ -+ssize_t xino_fread(vfs_readf_t func, struct file *file, void *kbuf, size_t size, -+ loff_t *pos) -+{ -+ ssize_t err; -+ mm_segment_t oldfs; -+ union { -+ void *k; -+ char __user *u; -+ } buf; -+ int i; -+ const int prevent_endless = 10; -+ -+ i = 0; -+ buf.k = kbuf; -+ oldfs = get_fs(); -+ set_fs(KERNEL_DS); -+ do { -+ err = func(file, buf.u, size, pos); -+ if (err == -EINTR -+ && !au_wkq_test() -+ && fatal_signal_pending(current)) { -+ set_fs(oldfs); -+ err = xino_fread_wkq(func, file, kbuf, size, pos); -+ BUG_ON(err == -EINTR); -+ oldfs = get_fs(); -+ set_fs(KERNEL_DS); -+ } -+ } while (i++ < prevent_endless -+ && (err == -EAGAIN || err == -EINTR)); -+ set_fs(oldfs); -+ -+#if 0 /* reserved for future use */ -+ if (err > 0) -+ fsnotify_access(file->f_path.dentry); -+#endif -+ -+ return err; -+} -+ -+struct xino_fread_args { -+ ssize_t *errp; -+ vfs_readf_t func; -+ struct file *file; -+ void *buf; -+ size_t size; -+ loff_t *pos; -+}; -+ -+static void call_xino_fread(void *args) -+{ -+ struct xino_fread_args *a = args; -+ *a->errp = xino_fread(a->func, a->file, a->buf, a->size, a->pos); -+} -+ -+static ssize_t xino_fread_wkq(vfs_readf_t func, struct file *file, void *buf, -+ size_t size, loff_t *pos) -+{ -+ ssize_t err; -+ int wkq_err; -+ struct xino_fread_args args = { -+ .errp = &err, -+ .func = func, -+ .file = file, -+ .buf = buf, -+ .size = size, -+ .pos = pos -+ }; -+ -+ wkq_err = au_wkq_wait(call_xino_fread, &args); -+ if (unlikely(wkq_err)) -+ err = wkq_err; -+ -+ return err; -+} -+ -+static ssize_t xino_fwrite_wkq(vfs_writef_t func, struct file *file, void *buf, -+ size_t size, loff_t *pos); -+ -+static ssize_t do_xino_fwrite(vfs_writef_t func, struct file *file, void *kbuf, -+ size_t size, loff_t *pos) -+{ -+ ssize_t err; -+ mm_segment_t oldfs; -+ union { -+ void *k; -+ const char __user *u; -+ } buf; -+ int i; -+ const int prevent_endless = 10; -+ -+ i = 0; -+ buf.k = kbuf; -+ oldfs = get_fs(); -+ set_fs(KERNEL_DS); -+ do { -+ err = func(file, buf.u, size, pos); -+ if (err == -EINTR -+ && !au_wkq_test() -+ && fatal_signal_pending(current)) { -+ set_fs(oldfs); -+ err = xino_fwrite_wkq(func, file, kbuf, size, pos); -+ BUG_ON(err == -EINTR); -+ oldfs = get_fs(); -+ set_fs(KERNEL_DS); -+ } -+ } while (i++ < prevent_endless -+ && (err == -EAGAIN || err == -EINTR)); -+ set_fs(oldfs); -+ -+#if 0 /* reserved for future use */ -+ if (err > 0) -+ fsnotify_modify(file->f_path.dentry); -+#endif -+ -+ return err; -+} -+ -+struct do_xino_fwrite_args { -+ ssize_t *errp; -+ vfs_writef_t func; -+ struct file *file; -+ void *buf; -+ size_t size; -+ loff_t *pos; -+}; -+ -+static void call_do_xino_fwrite(void *args) -+{ -+ struct do_xino_fwrite_args *a = args; -+ *a->errp = do_xino_fwrite(a->func, a->file, a->buf, a->size, a->pos); -+} -+ -+static ssize_t xino_fwrite_wkq(vfs_writef_t func, struct file *file, void *buf, -+ size_t size, loff_t *pos) -+{ -+ ssize_t err; -+ int wkq_err; -+ struct do_xino_fwrite_args args = { -+ .errp = &err, -+ .func = func, -+ .file = file, -+ .buf = buf, -+ .size = size, -+ .pos = pos -+ }; -+ -+ /* -+ * it breaks RLIMIT_FSIZE and normal user's limit, -+ * users should care about quota and real 'filesystem full.' -+ */ -+ wkq_err = au_wkq_wait(call_do_xino_fwrite, &args); -+ if (unlikely(wkq_err)) -+ err = wkq_err; -+ -+ return err; -+} -+ -+ssize_t xino_fwrite(vfs_writef_t func, struct file *file, void *buf, -+ size_t size, loff_t *pos) -+{ -+ ssize_t err; -+ -+ if (rlimit(RLIMIT_FSIZE) == RLIM_INFINITY) { -+ lockdep_off(); -+ err = do_xino_fwrite(func, file, buf, size, pos); -+ lockdep_on(); -+ } else { -+ lockdep_off(); -+ err = xino_fwrite_wkq(func, file, buf, size, pos); -+ lockdep_on(); -+ } -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * inode number bitmap -+ */ -+static const int page_bits = (int)PAGE_SIZE * BITS_PER_BYTE; -+static ino_t xib_calc_ino(unsigned long pindex, int bit) -+{ -+ ino_t ino; -+ -+ AuDebugOn(bit < 0 || page_bits <= bit); -+ ino = AUFS_FIRST_INO + pindex * page_bits + bit; -+ return ino; -+} -+ -+static void xib_calc_bit(ino_t ino, unsigned long *pindex, int *bit) -+{ -+ AuDebugOn(ino < AUFS_FIRST_INO); -+ ino -= AUFS_FIRST_INO; -+ *pindex = ino / page_bits; -+ *bit = ino % page_bits; -+} -+ -+static int xib_pindex(struct super_block *sb, unsigned long pindex) -+{ -+ int err; -+ loff_t pos; -+ ssize_t sz; -+ struct au_sbinfo *sbinfo; -+ struct file *xib; -+ unsigned long *p; -+ -+ sbinfo = au_sbi(sb); -+ MtxMustLock(&sbinfo->si_xib_mtx); -+ AuDebugOn(pindex > ULONG_MAX / PAGE_SIZE -+ || !au_opt_test(sbinfo->si_mntflags, XINO)); -+ -+ if (pindex == sbinfo->si_xib_last_pindex) -+ return 0; -+ -+ xib = sbinfo->si_xib; -+ p = sbinfo->si_xib_buf; -+ pos = sbinfo->si_xib_last_pindex; -+ pos *= PAGE_SIZE; -+ sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos); -+ if (unlikely(sz != PAGE_SIZE)) -+ goto out; -+ -+ pos = pindex; -+ pos *= PAGE_SIZE; -+ if (vfsub_f_size_read(xib) >= pos + PAGE_SIZE) -+ sz = xino_fread(sbinfo->si_xread, xib, p, PAGE_SIZE, &pos); -+ else { -+ memset(p, 0, PAGE_SIZE); -+ sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos); -+ } -+ if (sz == PAGE_SIZE) { -+ sbinfo->si_xib_last_pindex = pindex; -+ return 0; /* success */ -+ } -+ -+out: -+ AuIOErr1("write failed (%zd)\n", sz); -+ err = sz; -+ if (sz >= 0) -+ err = -EIO; -+ return err; -+} -+ -+static void au_xib_clear_bit(struct inode *inode) -+{ -+ int err, bit; -+ unsigned long pindex; -+ struct super_block *sb; -+ struct au_sbinfo *sbinfo; -+ -+ AuDebugOn(inode->i_nlink); -+ -+ sb = inode->i_sb; -+ xib_calc_bit(inode->i_ino, &pindex, &bit); -+ AuDebugOn(page_bits <= bit); -+ sbinfo = au_sbi(sb); -+ mutex_lock(&sbinfo->si_xib_mtx); -+ err = xib_pindex(sb, pindex); -+ if (!err) { -+ clear_bit(bit, sbinfo->si_xib_buf); -+ sbinfo->si_xib_next_bit = bit; -+ } -+ mutex_unlock(&sbinfo->si_xib_mtx); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * truncate a xino bitmap file -+ */ -+ -+/* todo: slow */ -+static int do_xib_restore(struct super_block *sb, struct file *file, void *page) -+{ -+ int err, bit; -+ ssize_t sz; -+ unsigned long pindex; -+ loff_t pos, pend; -+ struct au_sbinfo *sbinfo; -+ vfs_readf_t func; -+ ino_t *ino; -+ unsigned long *p; -+ -+ err = 0; -+ sbinfo = au_sbi(sb); -+ MtxMustLock(&sbinfo->si_xib_mtx); -+ p = sbinfo->si_xib_buf; -+ func = sbinfo->si_xread; -+ pend = vfsub_f_size_read(file); -+ pos = 0; -+ while (pos < pend) { -+ sz = xino_fread(func, file, page, PAGE_SIZE, &pos); -+ err = sz; -+ if (unlikely(sz <= 0)) -+ goto out; -+ -+ err = 0; -+ for (ino = page; sz > 0; ino++, sz -= sizeof(ino)) { -+ if (unlikely(*ino < AUFS_FIRST_INO)) -+ continue; -+ -+ xib_calc_bit(*ino, &pindex, &bit); -+ AuDebugOn(page_bits <= bit); -+ err = xib_pindex(sb, pindex); -+ if (!err) -+ set_bit(bit, p); -+ else -+ goto out; -+ } -+ } -+ -+out: -+ return err; -+} -+ -+static int xib_restore(struct super_block *sb) -+{ -+ int err, i; -+ unsigned int nfile; -+ aufs_bindex_t bindex, bbot; -+ void *page; -+ struct au_branch *br; -+ struct au_xino *xi; -+ struct file *file; -+ -+ err = -ENOMEM; -+ page = (void *)__get_free_page(GFP_NOFS); -+ if (unlikely(!page)) -+ goto out; -+ -+ err = 0; -+ bbot = au_sbbot(sb); -+ for (bindex = 0; !err && bindex <= bbot; bindex++) -+ if (!bindex || is_sb_shared(sb, bindex, bindex - 1) < 0) { -+ br = au_sbr(sb, bindex); -+ xi = br->br_xino; -+ nfile = xi->xi_nfile; -+ for (i = 0; i < nfile; i++) { -+ file = au_xino_file(xi, i); -+ if (file) -+ err = do_xib_restore(sb, file, page); -+ } -+ } else -+ AuDbg("skip shared b%d\n", bindex); -+ free_page((unsigned long)page); -+ -+out: -+ return err; -+} -+ -+int au_xib_trunc(struct super_block *sb) -+{ -+ int err; -+ ssize_t sz; -+ loff_t pos; -+ struct au_sbinfo *sbinfo; -+ unsigned long *p; -+ struct file *file; -+ -+ SiMustWriteLock(sb); -+ -+ err = 0; -+ sbinfo = au_sbi(sb); -+ if (!au_opt_test(sbinfo->si_mntflags, XINO)) -+ goto out; -+ -+ file = sbinfo->si_xib; -+ if (vfsub_f_size_read(file) <= PAGE_SIZE) -+ goto out; -+ -+ file = au_xino_create2(sb, &sbinfo->si_xib->f_path, NULL); -+ err = PTR_ERR(file); -+ if (IS_ERR(file)) -+ goto out; -+ fput(sbinfo->si_xib); -+ sbinfo->si_xib = file; -+ -+ p = sbinfo->si_xib_buf; -+ memset(p, 0, PAGE_SIZE); -+ pos = 0; -+ sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xib, p, PAGE_SIZE, &pos); -+ if (unlikely(sz != PAGE_SIZE)) { -+ err = sz; -+ AuIOErr("err %d\n", err); -+ if (sz >= 0) -+ err = -EIO; -+ goto out; -+ } -+ -+ mutex_lock(&sbinfo->si_xib_mtx); -+ /* mnt_want_write() is unnecessary here */ -+ err = xib_restore(sb); -+ mutex_unlock(&sbinfo->si_xib_mtx); -+ -+out: -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct au_xino *au_xino_alloc(unsigned int nfile) -+{ -+ struct au_xino *xi; -+ -+ xi = kzalloc(sizeof(*xi), GFP_NOFS); -+ if (unlikely(!xi)) -+ goto out; -+ xi->xi_nfile = nfile; -+ xi->xi_file = kcalloc(nfile, sizeof(*xi->xi_file), GFP_NOFS); -+ if (unlikely(!xi->xi_file)) -+ goto out_free; -+ -+ xi->xi_nondir.total = 8; /* initial size */ -+ xi->xi_nondir.array = kcalloc(xi->xi_nondir.total, sizeof(ino_t), -+ GFP_NOFS); -+ if (unlikely(!xi->xi_nondir.array)) -+ goto out_file; -+ -+ spin_lock_init(&xi->xi_nondir.spin); -+ init_waitqueue_head(&xi->xi_nondir.wqh); -+ mutex_init(&xi->xi_mtx); -+ INIT_HLIST_BL_HEAD(&xi->xi_writing); -+ atomic_set(&xi->xi_truncating, 0); -+ kref_init(&xi->xi_kref); -+ goto out; /* success */ -+ -+out_file: -+ au_kfree_try_rcu(xi->xi_file); -+out_free: -+ au_kfree_rcu(xi); -+ xi = NULL; -+out: -+ return xi; -+} -+ -+static int au_xino_init(struct au_branch *br, int idx, struct file *file) -+{ -+ int err; -+ struct au_xino *xi; -+ -+ err = 0; -+ xi = au_xino_alloc(idx + 1); -+ if (unlikely(!xi)) { -+ err = -ENOMEM; -+ goto out; -+ } -+ -+ if (file) -+ get_file(file); -+ xi->xi_file[idx] = file; -+ AuDebugOn(br->br_xino); -+ br->br_xino = xi; -+ -+out: -+ return err; -+} -+ -+static void au_xino_release(struct kref *kref) -+{ -+ struct au_xino *xi; -+ int i; -+ unsigned long ul; -+ struct hlist_bl_head *hbl; -+ struct hlist_bl_node *pos, *n; -+ struct au_xi_writing *p; -+ -+ xi = container_of(kref, struct au_xino, xi_kref); -+ for (i = 0; i < xi->xi_nfile; i++) -+ if (xi->xi_file[i]) -+ fput(xi->xi_file[i]); -+ for (i = xi->xi_nondir.total - 1; i >= 0; i--) -+ AuDebugOn(xi->xi_nondir.array[i]); -+ mutex_destroy(&xi->xi_mtx); -+ hbl = &xi->xi_writing; -+ ul = au_hbl_count(hbl); -+ if (unlikely(ul)) { -+ pr_warn("xi_writing %lu\n", ul); -+ hlist_bl_lock(hbl); -+ hlist_bl_for_each_entry_safe(p, pos, n, hbl, node) { -+ hlist_bl_del(&p->node); -+ /* kmemleak reported au_kfree_rcu() doesn't free it */ -+ kfree(p); -+ } -+ hlist_bl_unlock(hbl); -+ } -+ au_kfree_try_rcu(xi->xi_file); -+ au_kfree_try_rcu(xi->xi_nondir.array); -+ au_kfree_rcu(xi); -+} -+ -+int au_xino_put(struct au_branch *br) -+{ -+ int ret; -+ struct au_xino *xi; -+ -+ ret = 0; -+ xi = br->br_xino; -+ if (xi) { -+ br->br_xino = NULL; -+ ret = kref_put(&xi->xi_kref, au_xino_release); -+ } -+ -+ return ret; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * xino mount option handlers -+ */ -+ -+/* xino bitmap */ -+static void xino_clear_xib(struct super_block *sb) -+{ -+ struct au_sbinfo *sbinfo; -+ -+ SiMustWriteLock(sb); -+ -+ sbinfo = au_sbi(sb); -+ /* unnecessary to clear sbinfo->si_xread and ->si_xwrite */ -+ if (sbinfo->si_xib) -+ fput(sbinfo->si_xib); -+ sbinfo->si_xib = NULL; -+ if (sbinfo->si_xib_buf) -+ free_page((unsigned long)sbinfo->si_xib_buf); -+ sbinfo->si_xib_buf = NULL; -+} -+ -+static int au_xino_set_xib(struct super_block *sb, struct path *path) -+{ -+ int err; -+ loff_t pos; -+ struct au_sbinfo *sbinfo; -+ struct file *file; -+ struct super_block *xi_sb; -+ -+ SiMustWriteLock(sb); -+ -+ sbinfo = au_sbi(sb); -+ file = au_xino_create2(sb, path, sbinfo->si_xib); -+ err = PTR_ERR(file); -+ if (IS_ERR(file)) -+ goto out; -+ if (sbinfo->si_xib) -+ fput(sbinfo->si_xib); -+ sbinfo->si_xib = file; -+ sbinfo->si_xread = vfs_readf(file); -+ sbinfo->si_xwrite = vfs_writef(file); -+ xi_sb = file_inode(file)->i_sb; -+ sbinfo->si_ximaxent = xi_sb->s_maxbytes; -+ if (unlikely(sbinfo->si_ximaxent < PAGE_SIZE)) { -+ err = -EIO; -+ pr_err("s_maxbytes(%llu) on %s is too small\n", -+ (u64)sbinfo->si_ximaxent, au_sbtype(xi_sb)); -+ goto out_unset; -+ } -+ sbinfo->si_ximaxent /= sizeof(ino_t); -+ -+ err = -ENOMEM; -+ if (!sbinfo->si_xib_buf) -+ sbinfo->si_xib_buf = (void *)get_zeroed_page(GFP_NOFS); -+ if (unlikely(!sbinfo->si_xib_buf)) -+ goto out_unset; -+ -+ sbinfo->si_xib_last_pindex = 0; -+ sbinfo->si_xib_next_bit = 0; -+ if (vfsub_f_size_read(file) < PAGE_SIZE) { -+ pos = 0; -+ err = xino_fwrite(sbinfo->si_xwrite, file, sbinfo->si_xib_buf, -+ PAGE_SIZE, &pos); -+ if (unlikely(err != PAGE_SIZE)) -+ goto out_free; -+ } -+ err = 0; -+ goto out; /* success */ -+ -+out_free: -+ if (sbinfo->si_xib_buf) -+ free_page((unsigned long)sbinfo->si_xib_buf); -+ sbinfo->si_xib_buf = NULL; -+ if (err >= 0) -+ err = -EIO; -+out_unset: -+ fput(sbinfo->si_xib); -+ sbinfo->si_xib = NULL; -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+/* xino for each branch */ -+static void xino_clear_br(struct super_block *sb) -+{ -+ aufs_bindex_t bindex, bbot; -+ struct au_branch *br; -+ -+ bbot = au_sbbot(sb); -+ for (bindex = 0; bindex <= bbot; bindex++) { -+ br = au_sbr(sb, bindex); -+ AuDebugOn(!br); -+ au_xino_put(br); -+ } -+} -+ -+static void au_xino_set_br_shared(struct super_block *sb, struct au_branch *br, -+ aufs_bindex_t bshared) -+{ -+ struct au_branch *brshared; -+ -+ brshared = au_sbr(sb, bshared); -+ AuDebugOn(!brshared->br_xino); -+ AuDebugOn(!brshared->br_xino->xi_file); -+ if (br->br_xino != brshared->br_xino) { -+ au_xino_get(brshared); -+ au_xino_put(br); -+ br->br_xino = brshared->br_xino; -+ } -+} -+ -+struct au_xino_do_set_br { -+ vfs_writef_t writef; -+ struct au_branch *br; -+ ino_t h_ino; -+ aufs_bindex_t bshared; -+}; -+ -+static int au_xino_do_set_br(struct super_block *sb, struct path *path, -+ struct au_xino_do_set_br *args) -+{ -+ int err; -+ struct au_xi_calc calc; -+ struct file *file; -+ struct au_branch *br; -+ struct au_xi_new xinew = { -+ .base = path -+ }; -+ -+ br = args->br; -+ xinew.xi = br->br_xino; -+ au_xi_calc(sb, args->h_ino, &calc); -+ xinew.copy_src = au_xino_file(xinew.xi, calc.idx); -+ if (args->bshared >= 0) -+ /* shared xino */ -+ au_xino_set_br_shared(sb, br, args->bshared); -+ else if (!xinew.xi) { -+ /* new xino */ -+ err = au_xino_init(br, calc.idx, xinew.copy_src); -+ if (unlikely(err)) -+ goto out; -+ } -+ -+ /* force re-creating */ -+ xinew.xi = br->br_xino; -+ xinew.idx = calc.idx; -+ mutex_lock(&xinew.xi->xi_mtx); -+ file = au_xi_new(sb, &xinew); -+ mutex_unlock(&xinew.xi->xi_mtx); -+ err = PTR_ERR(file); -+ if (IS_ERR(file)) -+ goto out; -+ AuDebugOn(!file); -+ -+ err = au_xino_do_write(args->writef, file, &calc, AUFS_ROOT_INO); -+ if (unlikely(err)) -+ au_xino_put(br); -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+static int au_xino_set_br(struct super_block *sb, struct path *path) -+{ -+ int err; -+ aufs_bindex_t bindex, bbot; -+ struct au_xino_do_set_br args; -+ struct inode *inode; -+ -+ SiMustWriteLock(sb); -+ -+ bbot = au_sbbot(sb); -+ inode = d_inode(sb->s_root); -+ args.writef = au_sbi(sb)->si_xwrite; -+ for (bindex = 0; bindex <= bbot; bindex++) { -+ args.h_ino = au_h_iptr(inode, bindex)->i_ino; -+ args.br = au_sbr(sb, bindex); -+ args.bshared = is_sb_shared(sb, bindex, bindex - 1); -+ err = au_xino_do_set_br(sb, path, &args); -+ if (unlikely(err)) -+ break; -+ } -+ -+ AuTraceErr(err); -+ return err; -+} -+ -+void au_xino_clr(struct super_block *sb) -+{ -+ struct au_sbinfo *sbinfo; -+ -+ au_xigen_clr(sb); -+ xino_clear_xib(sb); -+ xino_clear_br(sb); -+ dbgaufs_brs_del(sb, 0); -+ sbinfo = au_sbi(sb); -+ /* lvalue, do not call au_mntflags() */ -+ au_opt_clr(sbinfo->si_mntflags, XINO); -+} -+ -+int au_xino_set(struct super_block *sb, struct au_opt_xino *xiopt, int remount) -+{ -+ int err, skip; -+ struct dentry *dentry, *parent, *cur_dentry, *cur_parent; -+ struct qstr *dname, *cur_name; -+ struct file *cur_xino; -+ struct au_sbinfo *sbinfo; -+ struct path *path, *cur_path; -+ -+ SiMustWriteLock(sb); -+ -+ err = 0; -+ sbinfo = au_sbi(sb); -+ path = &xiopt->file->f_path; -+ dentry = path->dentry; -+ parent = dget_parent(dentry); -+ if (remount) { -+ skip = 0; -+ cur_xino = sbinfo->si_xib; -+ if (cur_xino) { -+ cur_path = &cur_xino->f_path; -+ cur_dentry = cur_path->dentry; -+ cur_parent = dget_parent(cur_dentry); -+ cur_name = &cur_dentry->d_name; -+ dname = &dentry->d_name; -+ skip = (cur_parent == parent -+ && au_qstreq(dname, cur_name)); -+ dput(cur_parent); -+ } -+ if (skip) -+ goto out; -+ } -+ -+ au_opt_set(sbinfo->si_mntflags, XINO); -+ err = au_xino_set_xib(sb, path); -+ /* si_x{read,write} are set */ -+ if (!err) -+ err = au_xigen_set(sb, path); -+ if (!err) -+ err = au_xino_set_br(sb, path); -+ if (!err) { -+ dbgaufs_brs_add(sb, 0, /*topdown*/1); -+ goto out; /* success */ -+ } -+ -+ /* reset all */ -+ AuIOErr("failed setting xino(%d).\n", err); -+ au_xino_clr(sb); -+ -+out: -+ dput(parent); -+ return err; -+} -+ -+/* -+ * create a xinofile at the default place/path. -+ */ -+struct file *au_xino_def(struct super_block *sb) -+{ -+ struct file *file; -+ char *page, *p; -+ struct au_branch *br; -+ struct super_block *h_sb; -+ struct path path; -+ aufs_bindex_t bbot, bindex, bwr; -+ -+ br = NULL; -+ bbot = au_sbbot(sb); -+ bwr = -1; -+ for (bindex = 0; bindex <= bbot; bindex++) { -+ br = au_sbr(sb, bindex); -+ if (au_br_writable(br->br_perm) -+ && !au_test_fs_bad_xino(au_br_sb(br))) { -+ bwr = bindex; -+ break; -+ } -+ } -+ -+ if (bwr >= 0) { -+ file = ERR_PTR(-ENOMEM); -+ page = (void *)__get_free_page(GFP_NOFS); -+ if (unlikely(!page)) -+ goto out; -+ path.mnt = au_br_mnt(br); -+ path.dentry = au_h_dptr(sb->s_root, bwr); -+ p = d_path(&path, page, PATH_MAX - sizeof(AUFS_XINO_FNAME)); -+ file = (void *)p; -+ if (!IS_ERR(p)) { -+ strcat(p, "/" AUFS_XINO_FNAME); -+ AuDbg("%s\n", p); -+ file = au_xino_create(sb, p, /*silent*/0, /*wbrtop*/1); -+ } -+ free_page((unsigned long)page); -+ } else { -+ file = au_xino_create(sb, AUFS_XINO_DEFPATH, /*silent*/0, -+ /*wbrtop*/0); -+ if (IS_ERR(file)) -+ goto out; -+ h_sb = file->f_path.dentry->d_sb; -+ if (unlikely(au_test_fs_bad_xino(h_sb))) { -+ pr_err("xino doesn't support %s(%s)\n", -+ AUFS_XINO_DEFPATH, au_sbtype(h_sb)); -+ fput(file); -+ file = ERR_PTR(-EINVAL); -+ } -+ } -+ -+out: -+ return file; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * initialize the xinofile for the specified branch @br -+ * at the place/path where @base_file indicates. -+ * test whether another branch is on the same filesystem or not, -+ * if found then share the xinofile with another branch. -+ */ -+int au_xino_init_br(struct super_block *sb, struct au_branch *br, ino_t h_ino, -+ struct path *base) -+{ -+ int err; -+ struct au_xino_do_set_br args = { -+ .h_ino = h_ino, -+ .br = br -+ }; -+ -+ args.writef = au_sbi(sb)->si_xwrite; -+ args.bshared = sbr_find_shared(sb, /*btop*/0, au_sbbot(sb), -+ au_br_sb(br)); -+ err = au_xino_do_set_br(sb, base, &args); -+ if (unlikely(err)) -+ au_xino_put(br); -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * get an unused inode number from bitmap -+ */ -+ino_t au_xino_new_ino(struct super_block *sb) -+{ -+ ino_t ino; -+ unsigned long *p, pindex, ul, pend; -+ struct au_sbinfo *sbinfo; -+ struct file *file; -+ int free_bit, err; -+ -+ if (!au_opt_test(au_mntflags(sb), XINO)) -+ return iunique(sb, AUFS_FIRST_INO); -+ -+ sbinfo = au_sbi(sb); -+ mutex_lock(&sbinfo->si_xib_mtx); -+ p = sbinfo->si_xib_buf; -+ free_bit = sbinfo->si_xib_next_bit; -+ if (free_bit < page_bits && !test_bit(free_bit, p)) -+ goto out; /* success */ -+ free_bit = find_first_zero_bit(p, page_bits); -+ if (free_bit < page_bits) -+ goto out; /* success */ -+ -+ pindex = sbinfo->si_xib_last_pindex; -+ for (ul = pindex - 1; ul < ULONG_MAX; ul--) { -+ err = xib_pindex(sb, ul); -+ if (unlikely(err)) -+ goto out_err; -+ free_bit = find_first_zero_bit(p, page_bits); -+ if (free_bit < page_bits) -+ goto out; /* success */ -+ } -+ -+ file = sbinfo->si_xib; -+ pend = vfsub_f_size_read(file) / PAGE_SIZE; -+ for (ul = pindex + 1; ul <= pend; ul++) { -+ err = xib_pindex(sb, ul); -+ if (unlikely(err)) -+ goto out_err; -+ free_bit = find_first_zero_bit(p, page_bits); -+ if (free_bit < page_bits) -+ goto out; /* success */ -+ } -+ BUG(); -+ -+out: -+ set_bit(free_bit, p); -+ sbinfo->si_xib_next_bit = free_bit + 1; -+ pindex = sbinfo->si_xib_last_pindex; -+ mutex_unlock(&sbinfo->si_xib_mtx); -+ ino = xib_calc_ino(pindex, free_bit); -+ AuDbg("i%lu\n", (unsigned long)ino); -+ return ino; -+out_err: -+ mutex_unlock(&sbinfo->si_xib_mtx); -+ AuDbg("i0\n"); -+ return 0; -+} -+ -+/* for s_op->delete_inode() */ -+void au_xino_delete_inode(struct inode *inode, const int unlinked) -+{ -+ int err; -+ unsigned int mnt_flags; -+ aufs_bindex_t bindex, bbot, bi; -+ unsigned char try_trunc; -+ struct au_iinfo *iinfo; -+ struct super_block *sb; -+ struct au_hinode *hi; -+ struct inode *h_inode; -+ struct au_branch *br; -+ vfs_writef_t xwrite; -+ struct au_xi_calc calc; -+ struct file *file; -+ -+ AuDebugOn(au_is_bad_inode(inode)); -+ -+ sb = inode->i_sb; -+ mnt_flags = au_mntflags(sb); -+ if (!au_opt_test(mnt_flags, XINO) -+ || inode->i_ino == AUFS_ROOT_INO) -+ return; -+ -+ if (unlinked) { -+ au_xigen_inc(inode); -+ au_xib_clear_bit(inode); -+ } -+ -+ iinfo = au_ii(inode); -+ bindex = iinfo->ii_btop; -+ if (bindex < 0) -+ return; -+ -+ xwrite = au_sbi(sb)->si_xwrite; -+ try_trunc = !!au_opt_test(mnt_flags, TRUNC_XINO); -+ hi = au_hinode(iinfo, bindex); -+ bbot = iinfo->ii_bbot; -+ for (; bindex <= bbot; bindex++, hi++) { -+ h_inode = hi->hi_inode; -+ if (!h_inode -+ || (!unlinked && h_inode->i_nlink)) -+ continue; -+ -+ /* inode may not be revalidated */ -+ bi = au_br_index(sb, hi->hi_id); -+ if (bi < 0) -+ continue; -+ -+ br = au_sbr(sb, bi); -+ au_xi_calc(sb, h_inode->i_ino, &calc); -+ file = au_xino_file(br->br_xino, calc.idx); -+ if (IS_ERR_OR_NULL(file)) -+ continue; -+ -+ err = au_xino_do_write(xwrite, file, &calc, /*ino*/0); -+ if (!err && try_trunc -+ && au_test_fs_trunc_xino(au_br_sb(br))) -+ xino_try_trunc(sb, br); -+ } -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int au_xinondir_find(struct au_xino *xi, ino_t h_ino) -+{ -+ int found, total, i; -+ -+ found = -1; -+ total = xi->xi_nondir.total; -+ for (i = 0; i < total; i++) { -+ if (xi->xi_nondir.array[i] != h_ino) -+ continue; -+ found = i; -+ break; -+ } -+ -+ return found; -+} -+ -+static int au_xinondir_expand(struct au_xino *xi) -+{ -+ int err, sz; -+ ino_t *p; -+ -+ BUILD_BUG_ON(KMALLOC_MAX_SIZE > INT_MAX); -+ -+ err = -ENOMEM; -+ sz = xi->xi_nondir.total * sizeof(ino_t); -+ if (unlikely(sz > KMALLOC_MAX_SIZE / 2)) -+ goto out; -+ p = au_kzrealloc(xi->xi_nondir.array, sz, sz << 1, GFP_ATOMIC, -+ /*may_shrink*/0); -+ if (p) { -+ xi->xi_nondir.array = p; -+ xi->xi_nondir.total <<= 1; -+ AuDbg("xi_nondir.total %d\n", xi->xi_nondir.total); -+ err = 0; -+ } -+ -+out: -+ return err; -+} -+ -+void au_xinondir_leave(struct super_block *sb, aufs_bindex_t bindex, -+ ino_t h_ino, int idx) -+{ -+ struct au_xino *xi; -+ -+ AuDebugOn(!au_opt_test(au_mntflags(sb), XINO)); -+ xi = au_sbr(sb, bindex)->br_xino; -+ AuDebugOn(idx < 0 || xi->xi_nondir.total <= idx); -+ -+ spin_lock(&xi->xi_nondir.spin); -+ AuDebugOn(xi->xi_nondir.array[idx] != h_ino); -+ xi->xi_nondir.array[idx] = 0; -+ spin_unlock(&xi->xi_nondir.spin); -+ wake_up_all(&xi->xi_nondir.wqh); -+} -+ -+int au_xinondir_enter(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, -+ int *idx) -+{ -+ int err, found, empty; -+ struct au_xino *xi; -+ -+ err = 0; -+ *idx = -1; -+ if (!au_opt_test(au_mntflags(sb), XINO)) -+ goto out; /* no xino */ -+ -+ xi = au_sbr(sb, bindex)->br_xino; -+ -+again: -+ spin_lock(&xi->xi_nondir.spin); -+ found = au_xinondir_find(xi, h_ino); -+ if (found == -1) { -+ empty = au_xinondir_find(xi, /*h_ino*/0); -+ if (empty == -1) { -+ empty = xi->xi_nondir.total; -+ err = au_xinondir_expand(xi); -+ if (unlikely(err)) -+ goto out_unlock; -+ } -+ xi->xi_nondir.array[empty] = h_ino; -+ *idx = empty; -+ } else { -+ spin_unlock(&xi->xi_nondir.spin); -+ wait_event(xi->xi_nondir.wqh, -+ xi->xi_nondir.array[found] != h_ino); -+ goto again; -+ } -+ -+out_unlock: -+ spin_unlock(&xi->xi_nondir.spin); -+out: -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+int au_xino_path(struct seq_file *seq, struct file *file) -+{ -+ int err; -+ -+ err = au_seq_path(seq, &file->f_path); -+ if (unlikely(err)) -+ goto out; -+ -+#define Deleted "\\040(deleted)" -+ seq->count -= sizeof(Deleted) - 1; -+ AuDebugOn(memcmp(seq->buf + seq->count, Deleted, -+ sizeof(Deleted) - 1)); -+#undef Deleted -+ -+out: -+ return err; -+} -diff --git a/fs/dcache.c b/fs/dcache.c -index 361ea7ab30ea..e6e467c9e86c 100644 ---- a/fs/dcache.c -+++ b/fs/dcache.c -@@ -1285,7 +1285,7 @@ enum d_walk_ret { - * - * The @enter() callbacks are called with d_lock held. - */ --static void d_walk(struct dentry *parent, void *data, -+void d_walk(struct dentry *parent, void *data, - enum d_walk_ret (*enter)(void *, struct dentry *)) - { - struct dentry *this_parent; -@@ -1390,6 +1390,7 @@ static void d_walk(struct dentry *parent, void *data, - seq = 1; - goto again; - } -+EXPORT_SYMBOL_GPL(d_walk); - - struct check_mount { - struct vfsmount *mnt; -@@ -2935,6 +2936,7 @@ void d_exchange(struct dentry *dentry1, struct dentry *dentry2) - - write_sequnlock(&rename_lock); - } -+EXPORT_SYMBOL_GPL(d_exchange); - - /** - * d_ancestor - search for an ancestor -diff --git a/fs/exec.c b/fs/exec.c -index e6e8a9a70327..a72a0dbfcc45 100644 ---- a/fs/exec.c -+++ b/fs/exec.c -@@ -111,6 +111,7 @@ bool path_noexec(const struct path *path) - return (path->mnt->mnt_flags & MNT_NOEXEC) || - (path->mnt->mnt_sb->s_iflags & SB_I_NOEXEC); - } -+EXPORT_SYMBOL_GPL(path_noexec); - - #ifdef CONFIG_USELIB - /* -diff --git a/fs/fcntl.c b/fs/fcntl.c -index 2e4c0fa2074b..f2c90a416b75 100644 ---- a/fs/fcntl.c -+++ b/fs/fcntl.c -@@ -32,7 +32,7 @@ - - #define SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | O_DIRECT | O_NOATIME) - --static int setfl(int fd, struct file * filp, unsigned long arg) -+int setfl(int fd, struct file *filp, unsigned long arg) - { - struct inode * inode = file_inode(filp); - int error = 0; -@@ -63,6 +63,8 @@ static int setfl(int fd, struct file * filp, unsigned long arg) - - if (filp->f_op->check_flags) - error = filp->f_op->check_flags(arg); -+ if (!error && filp->f_op->setfl) -+ error = filp->f_op->setfl(filp, arg); - if (error) - return error; - -@@ -83,6 +85,7 @@ static int setfl(int fd, struct file * filp, unsigned long arg) - out: - return error; - } -+EXPORT_SYMBOL_GPL(setfl); - - static void f_modown(struct file *filp, struct pid *pid, enum pid_type type, - int force) -diff --git a/fs/file_table.c b/fs/file_table.c -index 656647f9575a..6e11f3dc333f 100644 ---- a/fs/file_table.c -+++ b/fs/file_table.c -@@ -162,6 +162,7 @@ struct file *alloc_empty_file(int flags, const struct cred *cred) - } - return ERR_PTR(-ENFILE); - } -+EXPORT_SYMBOL_GPL(alloc_empty_file); - - /* - * Variant of alloc_empty_file() that doesn't check and modify nr_files. -@@ -376,6 +377,7 @@ void __fput_sync(struct file *file) - } - - EXPORT_SYMBOL(fput); -+EXPORT_SYMBOL_GPL(__fput_sync); - - void __init files_init(void) - { -diff --git a/fs/inode.c b/fs/inode.c -index 72c4c347afb7..07d0cb8d5c98 100644 ---- a/fs/inode.c -+++ b/fs/inode.c -@@ -1768,12 +1768,13 @@ EXPORT_SYMBOL(generic_update_time); - * This does the actual work of updating an inodes time or version. Must have - * had called mnt_want_write() before calling this. - */ --static int update_time(struct inode *inode, struct timespec64 *time, int flags) -+int update_time(struct inode *inode, struct timespec64 *time, int flags) - { - if (inode->i_op->update_time) - return inode->i_op->update_time(inode, time, flags); - return generic_update_time(inode, time, flags); - } -+EXPORT_SYMBOL_GPL(update_time); - - /** - * touch_atime - update the access time -diff --git a/fs/namespace.c b/fs/namespace.c -index 4a0f600a3328..2b7e1ac8c4c5 100644 ---- a/fs/namespace.c -+++ b/fs/namespace.c -@@ -431,6 +431,7 @@ void __mnt_drop_write(struct vfsmount *mnt) - mnt_dec_writers(real_mount(mnt)); - preempt_enable(); - } -+EXPORT_SYMBOL_GPL(__mnt_drop_write); - - /** - * mnt_drop_write - give up write access to a mount -@@ -792,6 +793,13 @@ static inline int check_mnt(struct mount *mnt) - return mnt->mnt_ns == current->nsproxy->mnt_ns; - } - -+/* for aufs, CONFIG_AUFS_BR_FUSE */ -+int is_current_mnt_ns(struct vfsmount *mnt) -+{ -+ return check_mnt(real_mount(mnt)); -+} -+EXPORT_SYMBOL_GPL(is_current_mnt_ns); -+ - /* - * vfsmount lock must be held for write - */ -@@ -1955,6 +1963,7 @@ int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg, - } - return 0; - } -+EXPORT_SYMBOL_GPL(iterate_mounts); - - static void lock_mnt_tree(struct mount *mnt) - { -diff --git a/fs/notify/group.c b/fs/notify/group.c -index a4a4b1c64d32..86dc2efb1850 100644 ---- a/fs/notify/group.c -+++ b/fs/notify/group.c -@@ -100,6 +100,7 @@ void fsnotify_get_group(struct fsnotify_group *group) - { - refcount_inc(&group->refcnt); - } -+EXPORT_SYMBOL_GPL(fsnotify_get_group); - - /* - * Drop a reference to a group. Free it if it's through. -diff --git a/fs/open.c b/fs/open.c -index 6cd48a61cda3..bb623ca6397e 100644 ---- a/fs/open.c -+++ b/fs/open.c -@@ -65,6 +65,7 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs, - inode_unlock(dentry->d_inode); - return ret; - } -+EXPORT_SYMBOL_GPL(do_truncate); - - long vfs_truncate(const struct path *path, loff_t length) - { -diff --git a/fs/proc/base.c b/fs/proc/base.c -index d86c0afc8a85..ae484a4d2070 100644 ---- a/fs/proc/base.c -+++ b/fs/proc/base.c -@@ -2170,7 +2170,7 @@ static int map_files_get_link(struct dentry *dentry, struct path *path) - rc = -ENOENT; - vma = find_exact_vma(mm, vm_start, vm_end); - if (vma && vma->vm_file) { -- *path = vma->vm_file->f_path; -+ *path = vma_pr_or_file(vma)->f_path; - path_get(path); - rc = 0; - } -diff --git a/fs/proc/nommu.c b/fs/proc/nommu.c -index 13452b32e2bd..38acccfef9d4 100644 ---- a/fs/proc/nommu.c -+++ b/fs/proc/nommu.c -@@ -40,7 +40,10 @@ static int nommu_region_show(struct seq_file *m, struct vm_region *region) - file = region->vm_file; - - if (file) { -- struct inode *inode = file_inode(region->vm_file); -+ struct inode *inode; -+ -+ file = vmr_pr_or_file(region); -+ inode = file_inode(file); - dev = inode->i_sb->s_dev; - ino = inode->i_ino; - } -diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c -index dbda4499a859..5f6fdf574d83 100644 ---- a/fs/proc/task_mmu.c -+++ b/fs/proc/task_mmu.c -@@ -280,7 +280,10 @@ show_map_vma(struct seq_file *m, struct vm_area_struct *vma) - const char *name = NULL; - - if (file) { -- struct inode *inode = file_inode(vma->vm_file); -+ struct inode *inode; -+ -+ file = vma_pr_or_file(vma); -+ inode = file_inode(file); - dev = inode->i_sb->s_dev; - ino = inode->i_ino; - pgoff = ((loff_t)vma->vm_pgoff) << PAGE_SHIFT; -@@ -1793,7 +1796,7 @@ static int show_numa_map(struct seq_file *m, void *v) - struct proc_maps_private *proc_priv = &numa_priv->proc_maps; - struct vm_area_struct *vma = v; - struct numa_maps *md = &numa_priv->md; -- struct file *file = vma->vm_file; -+ struct file *file = vma_pr_or_file(vma); - struct mm_struct *mm = vma->vm_mm; - struct mempolicy *pol; - char buffer[64]; -diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c -index a6d21fc0033c..02c2de31196e 100644 ---- a/fs/proc/task_nommu.c -+++ b/fs/proc/task_nommu.c -@@ -155,7 +155,10 @@ static int nommu_vma_show(struct seq_file *m, struct vm_area_struct *vma) - file = vma->vm_file; - - if (file) { -- struct inode *inode = file_inode(vma->vm_file); -+ struct inode *inode; -+ -+ file = vma_pr_or_file(vma); -+ inode = file_inode(file); - dev = inode->i_sb->s_dev; - ino = inode->i_ino; - pgoff = (loff_t)vma->vm_pgoff << PAGE_SHIFT; -diff --git a/fs/read_write.c b/fs/read_write.c -index 4fb797822567..71397019587a 100644 ---- a/fs/read_write.c -+++ b/fs/read_write.c -@@ -488,6 +488,7 @@ ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos) - inc_syscr(current); - return ret; - } -+EXPORT_SYMBOL_GPL(vfs_read); - - static ssize_t new_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos) - { -@@ -508,6 +509,30 @@ static ssize_t new_sync_write(struct file *filp, const char __user *buf, size_t - } - - /* caller is responsible for file_start_write/file_end_write */ -+vfs_readf_t vfs_readf(struct file *file) -+{ -+ const struct file_operations *fop = file->f_op; -+ -+ if (fop->read) -+ return fop->read; -+ if (fop->read_iter) -+ return new_sync_read; -+ return ERR_PTR(-ENOSYS); /* doesn't have ->read(|_iter)() op */ -+} -+EXPORT_SYMBOL_GPL(vfs_readf); -+ -+vfs_writef_t vfs_writef(struct file *file) -+{ -+ const struct file_operations *fop = file->f_op; -+ -+ if (fop->write) -+ return fop->write; -+ if (fop->write_iter) -+ return new_sync_write; -+ return ERR_PTR(-ENOSYS); /* doesn't have ->write(|_iter)() op */ -+} -+EXPORT_SYMBOL_GPL(vfs_writef); -+ - ssize_t __kernel_write(struct file *file, const void *buf, size_t count, loff_t *pos) - { - mm_segment_t old_fs; -@@ -586,6 +611,7 @@ ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_ - file_end_write(file); - return ret; - } -+EXPORT_SYMBOL_GPL(vfs_write); - - /* file_ppos returns &file->f_pos or NULL if file is stream */ - static inline loff_t *file_ppos(struct file *file) -diff --git a/fs/splice.c b/fs/splice.c -index d7c8a7c4db07..663e01ab2779 100644 ---- a/fs/splice.c -+++ b/fs/splice.c -@@ -839,8 +839,8 @@ EXPORT_SYMBOL(generic_splice_sendpage); - /* - * Attempt to initiate a splice from pipe to file. - */ --static long do_splice_from(struct pipe_inode_info *pipe, struct file *out, -- loff_t *ppos, size_t len, unsigned int flags) -+long do_splice_from(struct pipe_inode_info *pipe, struct file *out, -+ loff_t *ppos, size_t len, unsigned int flags) - { - if (out->f_op->splice_write) - return out->f_op->splice_write(pipe, out, ppos, len, flags); -@@ -850,9 +850,9 @@ static long do_splice_from(struct pipe_inode_info *pipe, struct file *out, - /* - * 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) - { - int ret; - -@@ -870,6 +870,7 @@ static long do_splice_to(struct file *in, loff_t *ppos, - return in->f_op->splice_read(in, ppos, pipe, len, flags); - return default_file_splice_read(in, ppos, pipe, len, flags); - } -+EXPORT_SYMBOL_GPL(do_splice_from); - - /** - * splice_direct_to_actor - splices data directly between two non-pipes -@@ -1016,6 +1017,7 @@ static int direct_splice_actor(struct pipe_inode_info *pipe, - return do_splice_from(pipe, file, sd->opos, sd->total_len, - sd->flags); - } -+EXPORT_SYMBOL_GPL(do_splice_to); - - /** - * do_splice_direct - splices data directly between two files -diff --git a/fs/sync.c b/fs/sync.c -index 1373a610dc78..fa5c7fba7f1b 100644 ---- a/fs/sync.c -+++ b/fs/sync.c -@@ -28,7 +28,7 @@ - * wait == 1 case since in that case write_inode() functions do - * sync_dirty_buffer() and thus effectively write one block at a time. - */ --static int __sync_filesystem(struct super_block *sb, int wait) -+int __sync_filesystem(struct super_block *sb, int wait) - { - if (wait) - sync_inodes_sb(sb); -@@ -39,6 +39,7 @@ static int __sync_filesystem(struct super_block *sb, int wait) - sb->s_op->sync_fs(sb, wait); - return __sync_blockdev(sb->s_bdev, wait); - } -+EXPORT_SYMBOL_GPL(__sync_filesystem); - - /* - * Write out and wait upon all dirty data associated with this -diff --git a/fs/xattr.c b/fs/xattr.c -index 95f38f57347f..f01b5bd9c102 100644 ---- a/fs/xattr.c -+++ b/fs/xattr.c -@@ -333,6 +333,7 @@ vfs_getxattr_alloc(struct dentry *dentry, const char *name, char **xattr_value, - *xattr_value = value; - return error; - } -+EXPORT_SYMBOL_GPL(vfs_getxattr_alloc); - - ssize_t - __vfs_getxattr(struct dentry *dentry, struct inode *inode, const char *name, -diff --git a/include/linux/fs.h b/include/linux/fs.h -index f5abba86107d..0b008da5678d 100644 ---- a/include/linux/fs.h -+++ b/include/linux/fs.h -@@ -1360,6 +1360,7 @@ extern void fasync_free(struct fasync_struct *); - /* can be called from interrupts */ - extern void kill_fasync(struct fasync_struct **, int, int); - -+extern int setfl(int fd, struct file *filp, unsigned long arg); - extern void __f_setown(struct file *filp, struct pid *, enum pid_type, int force); - extern int f_setown(struct file *filp, unsigned long arg, int force); - extern void f_delown(struct file *filp); -@@ -1848,6 +1849,7 @@ struct file_operations { - ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int); - unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); - int (*check_flags)(int); -+ int (*setfl)(struct file *, unsigned long); - int (*flock) (struct file *, int, struct file_lock *); - ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int); - ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int); -@@ -1918,6 +1920,12 @@ ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector, - struct iovec *fast_pointer, - struct iovec **ret_pointer); - -+typedef ssize_t (*vfs_readf_t)(struct file *, char __user *, size_t, loff_t *); -+typedef ssize_t (*vfs_writef_t)(struct file *, const char __user *, size_t, -+ loff_t *); -+vfs_readf_t vfs_readf(struct file *file); -+vfs_writef_t vfs_writef(struct file *file); -+ - extern ssize_t vfs_read(struct file *, char __user *, size_t, loff_t *); - extern ssize_t vfs_write(struct file *, const char __user *, size_t, loff_t *); - extern ssize_t vfs_readv(struct file *, const struct iovec __user *, -@@ -2352,6 +2360,7 @@ extern int current_umask(void); - extern void ihold(struct inode * inode); - extern void iput(struct inode *); - extern int generic_update_time(struct inode *, struct timespec64 *, int); -+extern int update_time(struct inode *, struct timespec64 *, int); - - /* /sys/fs */ - extern struct kobject *fs_kobj; -@@ -2633,6 +2642,7 @@ static inline bool sb_is_blkdev_sb(struct super_block *sb) - } - - void emergency_thaw_all(void); -+extern int __sync_filesystem(struct super_block *, int); - extern int sync_filesystem(struct super_block *); - extern const struct file_operations def_blk_fops; - extern const struct file_operations def_chr_fops; -diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h -index 8fce5c98a4b0..c1a3f172e97a 100644 ---- a/include/linux/lockdep.h -+++ b/include/linux/lockdep.h -@@ -395,6 +395,8 @@ static inline int lockdep_match_key(struct lockdep_map *lock, - return lock->key == key; - } - -+struct lock_class *lockdep_hlock_class(struct held_lock *hlock); -+ - /* - * Acquire a lock. - * -@@ -540,6 +542,7 @@ struct lockdep_map { }; - - #define lockdep_depth(tsk) (0) - -+#define lockdep_is_held(lock) (1) - #define lockdep_is_held_type(l, r) (1) - - #define lockdep_assert_held(l) do { (void)(l); } while (0) -diff --git a/include/linux/mm.h b/include/linux/mm.h -index dc7b87310c10..40e450bbf00f 100644 ---- a/include/linux/mm.h -+++ b/include/linux/mm.h -@@ -1684,6 +1684,28 @@ static inline void unmap_shared_mapping_range(struct address_space *mapping, - unmap_mapping_range(mapping, holebegin, holelen, 0); - } - -+extern void vma_do_file_update_time(struct vm_area_struct *, const char[], int); -+extern struct file *vma_do_pr_or_file(struct vm_area_struct *, const char[], -+ int); -+extern void vma_do_get_file(struct vm_area_struct *, const char[], int); -+extern void vma_do_fput(struct vm_area_struct *, const char[], int); -+ -+#define vma_file_update_time(vma) vma_do_file_update_time(vma, __func__, \ -+ __LINE__) -+#define vma_pr_or_file(vma) vma_do_pr_or_file(vma, __func__, \ -+ __LINE__) -+#define vma_get_file(vma) vma_do_get_file(vma, __func__, __LINE__) -+#define vma_fput(vma) vma_do_fput(vma, __func__, __LINE__) -+ -+#ifndef CONFIG_MMU -+extern struct file *vmr_do_pr_or_file(struct vm_region *, const char[], int); -+extern void vmr_do_fput(struct vm_region *, const char[], int); -+ -+#define vmr_pr_or_file(region) vmr_do_pr_or_file(region, __func__, \ -+ __LINE__) -+#define vmr_fput(region) vmr_do_fput(region, __func__, __LINE__) -+#endif /* !CONFIG_MMU */ -+ - extern int access_process_vm(struct task_struct *tsk, unsigned long addr, - void *buf, int len, unsigned int gup_flags); - extern int access_remote_vm(struct mm_struct *mm, unsigned long addr, -diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h -index 64ede5f150dc..1c899fd6bda4 100644 ---- a/include/linux/mm_types.h -+++ b/include/linux/mm_types.h -@@ -276,6 +276,7 @@ struct vm_region { - unsigned long vm_top; /* region allocated to here */ - unsigned long vm_pgoff; /* the offset in vm_file corresponding to vm_start */ - struct file *vm_file; /* the backing file or NULL */ -+ struct file *vm_prfile; /* the virtual backing file or NULL */ - - int vm_usage; /* region usage count (access under nommu_region_sem) */ - bool vm_icache_flushed : 1; /* true if the icache has been flushed for -@@ -355,6 +356,7 @@ struct vm_area_struct { - unsigned long vm_pgoff; /* Offset (within vm_file) in PAGE_SIZE - units */ - struct file * vm_file; /* File we map to (can be NULL). */ -+ struct file *vm_prfile; /* shadow of vm_file */ - void * vm_private_data; /* was vm_pte (shared mem) */ - - #ifdef CONFIG_SWAP -diff --git a/include/linux/mnt_namespace.h b/include/linux/mnt_namespace.h -index 8f882f5881e8..6b9808f09843 100644 ---- a/include/linux/mnt_namespace.h -+++ b/include/linux/mnt_namespace.h -@@ -7,12 +7,15 @@ struct mnt_namespace; - struct fs_struct; - struct user_namespace; - struct ns_common; -+struct vfsmount; - - extern struct mnt_namespace *copy_mnt_ns(unsigned long, struct mnt_namespace *, - struct user_namespace *, struct fs_struct *); - extern void put_mnt_ns(struct mnt_namespace *ns); - extern struct ns_common *from_mnt_ns(struct mnt_namespace *); - -+extern int is_current_mnt_ns(struct vfsmount *mnt); -+ - extern const struct file_operations proc_mounts_operations; - extern const struct file_operations proc_mountinfo_operations; - extern const struct file_operations proc_mountstats_operations; -diff --git a/include/linux/splice.h b/include/linux/splice.h -index 5c47013f708e..fef6c59ed92a 100644 ---- a/include/linux/splice.h -+++ b/include/linux/splice.h -@@ -93,4 +93,10 @@ extern void splice_shrink_spd(struct splice_pipe_desc *); - - extern const struct pipe_buf_operations page_cache_pipe_buf_ops; - extern const struct pipe_buf_operations default_pipe_buf_ops; -+ -+extern long do_splice_from(struct pipe_inode_info *pipe, struct file *out, -+ loff_t *ppos, size_t len, unsigned int flags); -+extern long do_splice_to(struct file *in, loff_t *ppos, -+ struct pipe_inode_info *pipe, size_t len, -+ unsigned int flags); - #endif -diff --git a/include/uapi/linux/aufs_type.h b/include/uapi/linux/aufs_type.h -new file mode 100644 -index 000000000000..71501ea96e0b ---- /dev/null -+++ b/include/uapi/linux/aufs_type.h -@@ -0,0 +1,439 @@ -+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+#ifndef __AUFS_TYPE_H__ -+#define __AUFS_TYPE_H__ -+ -+#define AUFS_NAME "aufs" -+ -+#ifdef __KERNEL__ -+/* -+ * define it before including all other headers. -+ * sched.h may use pr_* macros before defining "current", so define the -+ * no-current version first, and re-define later. -+ */ -+#define pr_fmt(fmt) AUFS_NAME " %s:%d: " fmt, __func__, __LINE__ -+#include -+#undef pr_fmt -+#define pr_fmt(fmt) \ -+ AUFS_NAME " %s:%d:%.*s[%d]: " fmt, __func__, __LINE__, \ -+ (int)sizeof(current->comm), current->comm, current->pid -+#include -+#else -+#include -+#include -+#include -+#endif /* __KERNEL__ */ -+ -+#define AUFS_VERSION "5.7" -+ -+/* todo? move this to linux-2.6.19/include/magic.h */ -+#define AUFS_SUPER_MAGIC ('a' << 24 | 'u' << 16 | 'f' << 8 | 's') -+ -+/* ---------------------------------------------------------------------- */ -+ -+#ifdef __KERNEL__ -+#ifdef CONFIG_AUFS_BRANCH_MAX_127 -+typedef int8_t aufs_bindex_t; -+#define AUFS_BRANCH_MAX 127 -+#else -+typedef int16_t aufs_bindex_t; -+#ifdef CONFIG_AUFS_BRANCH_MAX_511 -+#define AUFS_BRANCH_MAX 511 -+#elif defined(CONFIG_AUFS_BRANCH_MAX_1023) -+#define AUFS_BRANCH_MAX 1023 -+#elif defined(CONFIG_AUFS_BRANCH_MAX_32767) -+#define AUFS_BRANCH_MAX 32767 -+#endif -+#endif -+ -+#ifndef AUFS_BRANCH_MAX -+#error unknown CONFIG_AUFS_BRANCH_MAX value -+#endif -+#endif /* __KERNEL__ */ -+ -+/* ---------------------------------------------------------------------- */ -+ -+#define AUFS_FSTYPE AUFS_NAME -+ -+#define AUFS_ROOT_INO 2 -+#define AUFS_FIRST_INO 11 -+ -+#define AUFS_WH_PFX ".wh." -+#define AUFS_WH_PFX_LEN ((int)sizeof(AUFS_WH_PFX) - 1) -+#define AUFS_WH_TMP_LEN 4 -+/* a limit for rmdir/rename a dir and copyup */ -+#define AUFS_MAX_NAMELEN (NAME_MAX \ -+ - AUFS_WH_PFX_LEN * 2 /* doubly whiteouted */\ -+ - 1 /* dot */\ -+ - AUFS_WH_TMP_LEN) /* hex */ -+#define AUFS_XINO_FNAME "." AUFS_NAME ".xino" -+#define AUFS_XINO_DEFPATH "/tmp/" AUFS_XINO_FNAME -+#define AUFS_XINO_DEF_SEC 30 /* seconds */ -+#define AUFS_XINO_DEF_TRUNC 45 /* percentage */ -+#define AUFS_DIRWH_DEF 3 -+#define AUFS_RDCACHE_DEF 10 /* seconds */ -+#define AUFS_RDCACHE_MAX 3600 /* seconds */ -+#define AUFS_RDBLK_DEF 512 /* bytes */ -+#define AUFS_RDHASH_DEF 32 -+#define AUFS_WKQ_NAME AUFS_NAME "d" -+#define AUFS_MFS_DEF_SEC 30 /* seconds */ -+#define AUFS_MFS_MAX_SEC 3600 /* seconds */ -+#define AUFS_FHSM_CACHE_DEF_SEC 30 /* seconds */ -+#define AUFS_PLINK_WARN 50 /* number of plinks in a single bucket */ -+ -+/* pseudo-link maintenace under /proc */ -+#define AUFS_PLINK_MAINT_NAME "plink_maint" -+#define AUFS_PLINK_MAINT_DIR "fs/" AUFS_NAME -+#define AUFS_PLINK_MAINT_PATH AUFS_PLINK_MAINT_DIR "/" AUFS_PLINK_MAINT_NAME -+ -+/* dirren, renamed dir */ -+#define AUFS_DR_INFO_PFX AUFS_WH_PFX ".dr." -+#define AUFS_DR_BRHINO_NAME AUFS_WH_PFX "hino" -+/* whiteouted doubly */ -+#define AUFS_WH_DR_INFO_PFX AUFS_WH_PFX AUFS_DR_INFO_PFX -+#define AUFS_WH_DR_BRHINO AUFS_WH_PFX AUFS_DR_BRHINO_NAME -+ -+#define AUFS_DIROPQ_NAME AUFS_WH_PFX ".opq" /* whiteouted doubly */ -+#define AUFS_WH_DIROPQ AUFS_WH_PFX AUFS_DIROPQ_NAME -+ -+#define AUFS_BASE_NAME AUFS_WH_PFX AUFS_NAME -+#define AUFS_PLINKDIR_NAME AUFS_WH_PFX "plnk" -+#define AUFS_ORPHDIR_NAME AUFS_WH_PFX "orph" -+ -+/* doubly whiteouted */ -+#define AUFS_WH_BASE AUFS_WH_PFX AUFS_BASE_NAME -+#define AUFS_WH_PLINKDIR AUFS_WH_PFX AUFS_PLINKDIR_NAME -+#define AUFS_WH_ORPHDIR AUFS_WH_PFX AUFS_ORPHDIR_NAME -+ -+/* branch permissions and attributes */ -+#define AUFS_BRPERM_RW "rw" -+#define AUFS_BRPERM_RO "ro" -+#define AUFS_BRPERM_RR "rr" -+#define AUFS_BRATTR_COO_REG "coo_reg" -+#define AUFS_BRATTR_COO_ALL "coo_all" -+#define AUFS_BRATTR_FHSM "fhsm" -+#define AUFS_BRATTR_UNPIN "unpin" -+#define AUFS_BRATTR_ICEX "icex" -+#define AUFS_BRATTR_ICEX_SEC "icexsec" -+#define AUFS_BRATTR_ICEX_SYS "icexsys" -+#define AUFS_BRATTR_ICEX_TR "icextr" -+#define AUFS_BRATTR_ICEX_USR "icexusr" -+#define AUFS_BRATTR_ICEX_OTH "icexoth" -+#define AUFS_BRRATTR_WH "wh" -+#define AUFS_BRWATTR_NLWH "nolwh" -+#define AUFS_BRWATTR_MOO "moo" -+ -+#define AuBrPerm_RW 1 /* writable, hardlinkable wh */ -+#define AuBrPerm_RO (1 << 1) /* readonly */ -+#define AuBrPerm_RR (1 << 2) /* natively readonly */ -+#define AuBrPerm_Mask (AuBrPerm_RW | AuBrPerm_RO | AuBrPerm_RR) -+ -+#define AuBrAttr_COO_REG (1 << 3) /* copy-up on open */ -+#define AuBrAttr_COO_ALL (1 << 4) -+#define AuBrAttr_COO_Mask (AuBrAttr_COO_REG | AuBrAttr_COO_ALL) -+ -+#define AuBrAttr_FHSM (1 << 5) /* file-based hsm */ -+#define AuBrAttr_UNPIN (1 << 6) /* rename-able top dir of -+ branch. meaningless since -+ linux-3.18-rc1 */ -+ -+/* ignore error in copying XATTR */ -+#define AuBrAttr_ICEX_SEC (1 << 7) -+#define AuBrAttr_ICEX_SYS (1 << 8) -+#define AuBrAttr_ICEX_TR (1 << 9) -+#define AuBrAttr_ICEX_USR (1 << 10) -+#define AuBrAttr_ICEX_OTH (1 << 11) -+#define AuBrAttr_ICEX (AuBrAttr_ICEX_SEC \ -+ | AuBrAttr_ICEX_SYS \ -+ | AuBrAttr_ICEX_TR \ -+ | AuBrAttr_ICEX_USR \ -+ | AuBrAttr_ICEX_OTH) -+ -+#define AuBrRAttr_WH (1 << 12) /* whiteout-able */ -+#define AuBrRAttr_Mask AuBrRAttr_WH -+ -+#define AuBrWAttr_NoLinkWH (1 << 13) /* un-hardlinkable whiteouts */ -+#define AuBrWAttr_MOO (1 << 14) /* move-up on open */ -+#define AuBrWAttr_Mask (AuBrWAttr_NoLinkWH | AuBrWAttr_MOO) -+ -+#define AuBrAttr_CMOO_Mask (AuBrAttr_COO_Mask | AuBrWAttr_MOO) -+ -+/* #warning test userspace */ -+#ifdef __KERNEL__ -+#ifndef CONFIG_AUFS_FHSM -+#undef AuBrAttr_FHSM -+#define AuBrAttr_FHSM 0 -+#endif -+#ifndef CONFIG_AUFS_XATTR -+#undef AuBrAttr_ICEX -+#define AuBrAttr_ICEX 0 -+#undef AuBrAttr_ICEX_SEC -+#define AuBrAttr_ICEX_SEC 0 -+#undef AuBrAttr_ICEX_SYS -+#define AuBrAttr_ICEX_SYS 0 -+#undef AuBrAttr_ICEX_TR -+#define AuBrAttr_ICEX_TR 0 -+#undef AuBrAttr_ICEX_USR -+#define AuBrAttr_ICEX_USR 0 -+#undef AuBrAttr_ICEX_OTH -+#define AuBrAttr_ICEX_OTH 0 -+#endif -+#endif -+ -+/* the longest combination */ -+/* AUFS_BRATTR_ICEX and AUFS_BRATTR_ICEX_TR don't affect here */ -+#define AuBrPermStrSz sizeof(AUFS_BRPERM_RW \ -+ "+" AUFS_BRATTR_COO_REG \ -+ "+" AUFS_BRATTR_FHSM \ -+ "+" AUFS_BRATTR_UNPIN \ -+ "+" AUFS_BRATTR_ICEX_SEC \ -+ "+" AUFS_BRATTR_ICEX_SYS \ -+ "+" AUFS_BRATTR_ICEX_USR \ -+ "+" AUFS_BRATTR_ICEX_OTH \ -+ "+" AUFS_BRWATTR_NLWH) -+ -+typedef struct { -+ char a[AuBrPermStrSz]; -+} au_br_perm_str_t; -+ -+static inline int au_br_writable(int brperm) -+{ -+ return brperm & AuBrPerm_RW; -+} -+ -+static inline int au_br_whable(int brperm) -+{ -+ return brperm & (AuBrPerm_RW | AuBrRAttr_WH); -+} -+ -+static inline int au_br_wh_linkable(int brperm) -+{ -+ return !(brperm & AuBrWAttr_NoLinkWH); -+} -+ -+static inline int au_br_cmoo(int brperm) -+{ -+ return brperm & AuBrAttr_CMOO_Mask; -+} -+ -+static inline int au_br_fhsm(int brperm) -+{ -+ return brperm & AuBrAttr_FHSM; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* ioctl */ -+enum { -+ /* readdir in userspace */ -+ AuCtl_RDU, -+ AuCtl_RDU_INO, -+ -+ AuCtl_WBR_FD, /* pathconf wrapper */ -+ AuCtl_IBUSY, /* busy inode */ -+ AuCtl_MVDOWN, /* move-down */ -+ AuCtl_BR, /* info about branches */ -+ AuCtl_FHSM_FD /* connection for fhsm */ -+}; -+ -+/* borrowed from linux/include/linux/kernel.h */ -+#ifndef ALIGN -+#ifdef _GNU_SOURCE -+#define ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a)-1) -+#else -+#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) -+#endif -+#define __ALIGN_MASK(x, mask) (((x)+(mask))&~(mask)) -+#endif -+ -+/* borrowed from linux/include/linux/compiler-gcc3.h */ -+#ifndef __aligned -+#define __aligned(x) __attribute__((aligned(x))) -+#endif -+ -+#ifdef __KERNEL__ -+#ifndef __packed -+#define __packed __attribute__((packed)) -+#endif -+#endif -+ -+struct au_rdu_cookie { -+ uint64_t h_pos; -+ int16_t bindex; -+ uint8_t flags; -+ uint8_t pad; -+ uint32_t generation; -+} __aligned(8); -+ -+struct au_rdu_ent { -+ uint64_t ino; -+ int16_t bindex; -+ uint8_t type; -+ uint8_t nlen; -+ uint8_t wh; -+ char name[]; -+} __aligned(8); -+ -+static inline int au_rdu_len(int nlen) -+{ -+ /* include the terminating NULL */ -+ return ALIGN(sizeof(struct au_rdu_ent) + nlen + 1, -+ sizeof(uint64_t)); -+} -+ -+union au_rdu_ent_ul { -+ struct au_rdu_ent __user *e; -+ uint64_t ul; -+}; -+ -+enum { -+ AufsCtlRduV_SZ, -+ AufsCtlRduV_End -+}; -+ -+struct aufs_rdu { -+ /* input */ -+ union { -+ uint64_t sz; /* AuCtl_RDU */ -+ uint64_t nent; /* AuCtl_RDU_INO */ -+ }; -+ union au_rdu_ent_ul ent; -+ uint16_t verify[AufsCtlRduV_End]; -+ -+ /* input/output */ -+ uint32_t blk; -+ -+ /* output */ -+ union au_rdu_ent_ul tail; -+ /* number of entries which were added in a single call */ -+ uint64_t rent; -+ uint8_t full; -+ uint8_t shwh; -+ -+ struct au_rdu_cookie cookie; -+} __aligned(8); -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* dirren. the branch is identified by the filename who contains this */ -+struct au_drinfo { -+ uint64_t ino; -+ union { -+ uint8_t oldnamelen; -+ uint64_t _padding; -+ }; -+ uint8_t oldname[]; -+} __aligned(8); -+ -+struct au_drinfo_fdata { -+ uint32_t magic; -+ struct au_drinfo drinfo; -+} __aligned(8); -+ -+#define AUFS_DRINFO_MAGIC_V1 ('a' << 24 | 'd' << 16 | 'r' << 8 | 0x01) -+/* future */ -+#define AUFS_DRINFO_MAGIC_V2 ('a' << 24 | 'd' << 16 | 'r' << 8 | 0x02) -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct aufs_wbr_fd { -+ uint32_t oflags; -+ int16_t brid; -+} __aligned(8); -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct aufs_ibusy { -+ uint64_t ino, h_ino; -+ int16_t bindex; -+} __aligned(8); -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* error code for move-down */ -+/* the actual message strings are implemented in aufs-util.git */ -+enum { -+ EAU_MVDOWN_OPAQUE = 1, -+ EAU_MVDOWN_WHITEOUT, -+ EAU_MVDOWN_UPPER, -+ EAU_MVDOWN_BOTTOM, -+ EAU_MVDOWN_NOUPPER, -+ EAU_MVDOWN_NOLOWERBR, -+ EAU_Last -+}; -+ -+/* flags for move-down */ -+#define AUFS_MVDOWN_DMSG 1 -+#define AUFS_MVDOWN_OWLOWER (1 << 1) /* overwrite lower */ -+#define AUFS_MVDOWN_KUPPER (1 << 2) /* keep upper */ -+#define AUFS_MVDOWN_ROLOWER (1 << 3) /* do even if lower is RO */ -+#define AUFS_MVDOWN_ROLOWER_R (1 << 4) /* did on lower RO */ -+#define AUFS_MVDOWN_ROUPPER (1 << 5) /* do even if upper is RO */ -+#define AUFS_MVDOWN_ROUPPER_R (1 << 6) /* did on upper RO */ -+#define AUFS_MVDOWN_BRID_UPPER (1 << 7) /* upper brid */ -+#define AUFS_MVDOWN_BRID_LOWER (1 << 8) /* lower brid */ -+#define AUFS_MVDOWN_FHSM_LOWER (1 << 9) /* find fhsm attr for lower */ -+#define AUFS_MVDOWN_STFS (1 << 10) /* req. stfs */ -+#define AUFS_MVDOWN_STFS_FAILED (1 << 11) /* output: stfs is unusable */ -+#define AUFS_MVDOWN_BOTTOM (1 << 12) /* output: no more lowers */ -+ -+/* index for move-down */ -+enum { -+ AUFS_MVDOWN_UPPER, -+ AUFS_MVDOWN_LOWER, -+ AUFS_MVDOWN_NARRAY -+}; -+ -+/* -+ * additional info of move-down -+ * number of free blocks and inodes. -+ * subset of struct kstatfs, but smaller and always 64bit. -+ */ -+struct aufs_stfs { -+ uint64_t f_blocks; -+ uint64_t f_bavail; -+ uint64_t f_files; -+ uint64_t f_ffree; -+}; -+ -+struct aufs_stbr { -+ int16_t brid; /* optional input */ -+ int16_t bindex; /* output */ -+ struct aufs_stfs stfs; /* output when AUFS_MVDOWN_STFS set */ -+} __aligned(8); -+ -+struct aufs_mvdown { -+ uint32_t flags; /* input/output */ -+ struct aufs_stbr stbr[AUFS_MVDOWN_NARRAY]; /* input/output */ -+ int8_t au_errno; /* output */ -+} __aligned(8); -+ -+/* ---------------------------------------------------------------------- */ -+ -+union aufs_brinfo { -+ /* PATH_MAX may differ between kernel-space and user-space */ -+ char _spacer[4096]; -+ struct { -+ int16_t id; -+ int perm; -+ char path[]; -+ }; -+} __aligned(8); -+ -+/* ---------------------------------------------------------------------- */ -+ -+#define AuCtlType 'A' -+#define AUFS_CTL_RDU _IOWR(AuCtlType, AuCtl_RDU, struct aufs_rdu) -+#define AUFS_CTL_RDU_INO _IOWR(AuCtlType, AuCtl_RDU_INO, struct aufs_rdu) -+#define AUFS_CTL_WBR_FD _IOW(AuCtlType, AuCtl_WBR_FD, \ -+ struct aufs_wbr_fd) -+#define AUFS_CTL_IBUSY _IOWR(AuCtlType, AuCtl_IBUSY, struct aufs_ibusy) -+#define AUFS_CTL_MVDOWN _IOWR(AuCtlType, AuCtl_MVDOWN, \ -+ struct aufs_mvdown) -+#define AUFS_CTL_BRINFO _IOW(AuCtlType, AuCtl_BR, union aufs_brinfo) -+#define AUFS_CTL_FHSM_FD _IOW(AuCtlType, AuCtl_FHSM_FD, int) -+ -+#endif /* __AUFS_TYPE_H__ */ -diff --git a/kernel/fork.c b/kernel/fork.c -index efc5493203ae..ba1174fb5d91 100644 ---- a/kernel/fork.c -+++ b/kernel/fork.c -@@ -570,7 +570,7 @@ static __latent_entropy int dup_mmap(struct mm_struct *mm, - struct inode *inode = file_inode(file); - struct address_space *mapping = file->f_mapping; - -- get_file(file); -+ vma_get_file(tmp); - if (tmp->vm_flags & VM_DENYWRITE) - atomic_dec(&inode->i_writecount); - i_mmap_lock_write(mapping); -diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c -index 29a8de4c50b9..1d54603f1f56 100644 ---- a/kernel/locking/lockdep.c -+++ b/kernel/locking/lockdep.c -@@ -169,7 +169,7 @@ static - struct lock_class lock_classes[MAX_LOCKDEP_KEYS]; - static DECLARE_BITMAP(lock_classes_in_use, MAX_LOCKDEP_KEYS); - --static inline struct lock_class *hlock_class(struct held_lock *hlock) -+inline struct lock_class *lockdep_hlock_class(struct held_lock *hlock) - { - unsigned int class_idx = hlock->class_idx; - -@@ -190,6 +190,8 @@ static inline struct lock_class *hlock_class(struct held_lock *hlock) - */ - return lock_classes + class_idx; - } -+EXPORT_SYMBOL_GPL(lockdep_hlock_class); -+#define hlock_class(hlock) lockdep_hlock_class(hlock) - - #ifdef CONFIG_LOCK_STAT - static DEFINE_PER_CPU(struct lock_class_stats[MAX_LOCKDEP_KEYS], cpu_lock_stats); -diff --git a/kernel/task_work.c b/kernel/task_work.c -index 5c0848ca1287..87f09e627840 100644 ---- a/kernel/task_work.c -+++ b/kernel/task_work.c -@@ -138,3 +138,4 @@ void task_work_run(void) - } while (work); - } - } -+EXPORT_SYMBOL_GPL(task_work_run); -diff --git a/mm/Makefile b/mm/Makefile -index 6e9d46b2efc9..a432b5664d83 100644 ---- a/mm/Makefile -+++ b/mm/Makefile -@@ -52,7 +52,7 @@ obj-y := filemap.o mempool.o oom_kill.o fadvise.o \ - mm_init.o percpu.o slab_common.o \ - compaction.o vmacache.o \ - interval_tree.o list_lru.o workingset.o \ -- debug.o gup.o $(mmu-y) -+ prfile.o debug.o gup.o $(mmu-y) - - # Give 'page_alloc' its own module-parameter namespace - page-alloc-y := page_alloc.o -diff --git a/mm/filemap.c b/mm/filemap.c -index 385759c4ce4b..570f4e1bc4d3 100644 ---- a/mm/filemap.c -+++ b/mm/filemap.c -@@ -2676,7 +2676,7 @@ vm_fault_t filemap_page_mkwrite(struct vm_fault *vmf) - vm_fault_t ret = VM_FAULT_LOCKED; - - sb_start_pagefault(inode->i_sb); -- file_update_time(vmf->vma->vm_file); -+ vma_file_update_time(vmf->vma); - lock_page(page); - if (page->mapping != inode->i_mapping) { - unlock_page(page); -diff --git a/mm/mmap.c b/mm/mmap.c -index 8c7ca737a19b..c4e2b1383925 100644 ---- a/mm/mmap.c -+++ b/mm/mmap.c -@@ -179,7 +179,7 @@ static struct vm_area_struct *remove_vma(struct vm_area_struct *vma) - if (vma->vm_ops && vma->vm_ops->close) - vma->vm_ops->close(vma); - if (vma->vm_file) -- fput(vma->vm_file); -+ vma_fput(vma); - mpol_put(vma_policy(vma)); - vm_area_free(vma); - return next; -@@ -910,7 +910,7 @@ int __vma_adjust(struct vm_area_struct *vma, unsigned long start, - if (remove_next) { - if (file) { - uprobe_munmap(next, next->vm_start, next->vm_end); -- fput(file); -+ vma_fput(vma); - } - if (next->anon_vma) - anon_vma_merge(vma, next); -@@ -1831,8 +1831,8 @@ unsigned long mmap_region(struct file *file, unsigned long addr, - return addr; - - unmap_and_free_vma: -+ vma_fput(vma); - vma->vm_file = NULL; -- fput(file); - - /* Undo any partial mapping done by a device driver. */ - unmap_region(mm, vma, prev, vma->vm_start, vma->vm_end); -@@ -2694,7 +2694,7 @@ int __split_vma(struct mm_struct *mm, struct vm_area_struct *vma, - goto out_free_mpol; - - if (new->vm_file) -- get_file(new->vm_file); -+ vma_get_file(new); - - if (new->vm_ops && new->vm_ops->open) - new->vm_ops->open(new); -@@ -2713,7 +2713,7 @@ int __split_vma(struct mm_struct *mm, struct vm_area_struct *vma, - if (new->vm_ops && new->vm_ops->close) - new->vm_ops->close(new); - if (new->vm_file) -- fput(new->vm_file); -+ vma_fput(new); - unlink_anon_vmas(new); - out_free_mpol: - mpol_put(vma_policy(new)); -@@ -2906,7 +2906,7 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size, - struct vm_area_struct *vma; - unsigned long populate = 0; - unsigned long ret = -EINVAL; -- struct file *file; -+ struct file *file, *prfile; - - pr_warn_once("%s (%d) uses deprecated remap_file_pages() syscall. See Documentation/vm/remap_file_pages.rst.\n", - current->comm, current->pid); -@@ -2981,10 +2981,27 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size, - } - } - -- file = get_file(vma->vm_file); -+ vma_get_file(vma); -+ file = vma->vm_file; -+ prfile = vma->vm_prfile; - ret = do_mmap(vma->vm_file, start, size, - prot, flags, pgoff, &populate, NULL); -+ if (!IS_ERR_VALUE(ret) && file && prfile) { -+ struct vm_area_struct *new_vma; -+ -+ new_vma = find_vma(mm, ret); -+ if (!new_vma->vm_prfile) -+ new_vma->vm_prfile = prfile; -+ if (new_vma != vma) -+ get_file(prfile); -+ } -+ /* -+ * two fput()s instead of vma_fput(vma), -+ * coz vma may not be available anymore. -+ */ - fput(file); -+ if (prfile) -+ fput(prfile); - out: - mmap_write_unlock(mm); - if (populate) -@@ -3275,7 +3292,7 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap, - if (anon_vma_clone(new_vma, vma)) - goto out_free_mempol; - if (new_vma->vm_file) -- get_file(new_vma->vm_file); -+ vma_get_file(new_vma); - if (new_vma->vm_ops && new_vma->vm_ops->open) - new_vma->vm_ops->open(new_vma); - vma_link(mm, new_vma, prev, rb_link, rb_parent); -diff --git a/mm/nommu.c b/mm/nommu.c -index f32a69095d50..26cd21666185 100644 ---- a/mm/nommu.c -+++ b/mm/nommu.c -@@ -540,7 +540,7 @@ static void __put_nommu_region(struct vm_region *region) - up_write(&nommu_region_sem); - - if (region->vm_file) -- fput(region->vm_file); -+ vmr_fput(region); - - /* IO memory and memory shared directly out of the pagecache - * from ramfs/tmpfs mustn't be released here */ -@@ -672,7 +672,7 @@ static void delete_vma(struct mm_struct *mm, struct vm_area_struct *vma) - if (vma->vm_ops && vma->vm_ops->close) - vma->vm_ops->close(vma); - if (vma->vm_file) -- fput(vma->vm_file); -+ vma_fput(vma); - put_nommu_region(vma->vm_region); - vm_area_free(vma); - } -@@ -1195,7 +1195,7 @@ unsigned long do_mmap(struct file *file, - goto error_just_free; - } - } -- fput(region->vm_file); -+ vmr_fput(region); - kmem_cache_free(vm_region_jar, region); - region = pregion; - result = start; -@@ -1272,10 +1272,10 @@ unsigned long do_mmap(struct file *file, - up_write(&nommu_region_sem); - error: - if (region->vm_file) -- fput(region->vm_file); -+ vmr_fput(region); - kmem_cache_free(vm_region_jar, region); - if (vma->vm_file) -- fput(vma->vm_file); -+ vma_fput(vma); - vm_area_free(vma); - return ret; - -diff --git a/mm/prfile.c b/mm/prfile.c -new file mode 100644 -index 000000000000..00d51187c325 ---- /dev/null -+++ b/mm/prfile.c -@@ -0,0 +1,86 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Mainly for aufs which mmap(2) different file and wants to print different -+ * path in /proc/PID/maps. -+ * Call these functions via macros defined in linux/mm.h. -+ * -+ * See Documentation/filesystems/aufs/design/06mmap.txt -+ * -+ * Copyright (c) 2014-2020 Junjro R. Okajima -+ * Copyright (c) 2014 Ian Campbell -+ */ -+ -+#include -+#include -+#include -+ -+/* #define PRFILE_TRACE */ -+static inline void prfile_trace(struct file *f, struct file *pr, -+ const char func[], int line, const char func2[]) -+{ -+#ifdef PRFILE_TRACE -+ if (pr) -+ pr_info("%s:%d: %s, %pD2\n", func, line, func2, f); -+#endif -+} -+ -+void vma_do_file_update_time(struct vm_area_struct *vma, const char func[], -+ int line) -+{ -+ struct file *f = vma->vm_file, *pr = vma->vm_prfile; -+ -+ prfile_trace(f, pr, func, line, __func__); -+ file_update_time(f); -+ if (f && pr) -+ file_update_time(pr); -+} -+ -+struct file *vma_do_pr_or_file(struct vm_area_struct *vma, const char func[], -+ int line) -+{ -+ struct file *f = vma->vm_file, *pr = vma->vm_prfile; -+ -+ prfile_trace(f, pr, func, line, __func__); -+ return (f && pr) ? pr : f; -+} -+ -+void vma_do_get_file(struct vm_area_struct *vma, const char func[], int line) -+{ -+ struct file *f = vma->vm_file, *pr = vma->vm_prfile; -+ -+ prfile_trace(f, pr, func, line, __func__); -+ get_file(f); -+ if (f && pr) -+ get_file(pr); -+} -+ -+void vma_do_fput(struct vm_area_struct *vma, const char func[], int line) -+{ -+ struct file *f = vma->vm_file, *pr = vma->vm_prfile; -+ -+ prfile_trace(f, pr, func, line, __func__); -+ fput(f); -+ if (f && pr) -+ fput(pr); -+} -+ -+#ifndef CONFIG_MMU -+struct file *vmr_do_pr_or_file(struct vm_region *region, const char func[], -+ int line) -+{ -+ struct file *f = region->vm_file, *pr = region->vm_prfile; -+ -+ prfile_trace(f, pr, func, line, __func__); -+ return (f && pr) ? pr : f; -+} -+ -+void vmr_do_fput(struct vm_region *region, const char func[], int line) -+{ -+ struct file *f = region->vm_file, *pr = region->vm_prfile; -+ -+ prfile_trace(f, pr, func, line, __func__); -+ fput(f); -+ if (f && pr) -+ fput(pr); -+} -+#endif /* !CONFIG_MMU */ -diff --git a/security/security.c b/security/security.c -index 70a7ad357bc6..d55b72977544 100644 ---- a/security/security.c -+++ b/security/security.c -@@ -1092,6 +1092,7 @@ int security_path_rmdir(const struct path *dir, struct dentry *dentry) - return 0; - return call_int_hook(path_rmdir, 0, dir, dentry); - } -+EXPORT_SYMBOL_GPL(security_path_rmdir); - - int security_path_unlink(const struct path *dir, struct dentry *dentry) - { -@@ -1108,6 +1109,7 @@ int security_path_symlink(const struct path *dir, struct dentry *dentry, - return 0; - return call_int_hook(path_symlink, 0, dir, dentry, old_name); - } -+EXPORT_SYMBOL_GPL(security_path_symlink); - - int security_path_link(struct dentry *old_dentry, const struct path *new_dir, - struct dentry *new_dentry) -@@ -1116,6 +1118,7 @@ int security_path_link(struct dentry *old_dentry, const struct path *new_dir, - return 0; - return call_int_hook(path_link, 0, old_dentry, new_dir, new_dentry); - } -+EXPORT_SYMBOL_GPL(security_path_link); - - int security_path_rename(const struct path *old_dir, struct dentry *old_dentry, - const struct path *new_dir, struct dentry *new_dentry, -@@ -1143,6 +1146,7 @@ int security_path_truncate(const struct path *path) - return 0; - return call_int_hook(path_truncate, 0, path); - } -+EXPORT_SYMBOL_GPL(security_path_truncate); - - int security_path_chmod(const struct path *path, umode_t mode) - { -@@ -1150,6 +1154,7 @@ int security_path_chmod(const struct path *path, umode_t mode) - return 0; - return call_int_hook(path_chmod, 0, path, mode); - } -+EXPORT_SYMBOL_GPL(security_path_chmod); - - int security_path_chown(const struct path *path, kuid_t uid, kgid_t gid) - { -@@ -1157,6 +1162,7 @@ int security_path_chown(const struct path *path, kuid_t uid, kgid_t gid) - return 0; - return call_int_hook(path_chown, 0, path, uid, gid); - } -+EXPORT_SYMBOL_GPL(security_path_chown); - - int security_path_chroot(const struct path *path) - { -@@ -1257,6 +1263,7 @@ int security_inode_permission(struct inode *inode, int mask) - return 0; - return call_int_hook(inode_permission, 0, inode, mask); - } -+EXPORT_SYMBOL_GPL(security_inode_permission); - - int security_inode_setattr(struct dentry *dentry, struct iattr *attr) - { -@@ -1449,6 +1456,7 @@ int security_file_permission(struct file *file, int mask) - - return fsnotify_perm(file, mask); - } -+EXPORT_SYMBOL_GPL(security_file_permission); - - int security_file_alloc(struct file *file) - { diff --git a/kernel/kernel/files/patches/mageia/fs-aufs-5.6-fix.patch b/kernel/kernel/files/patches/mageia/fs-aufs-5.6-fix.patch deleted file mode 100644 index 9fe6102a..00000000 --- a/kernel/kernel/files/patches/mageia/fs-aufs-5.6-fix.patch +++ /dev/null @@ -1,39 +0,0 @@ -diff -Nurp linux-5.6.3-aufs/fs/aufs/procfs.c linux-5.6.3-aufs-fix/fs/aufs/procfs.c ---- linux-5.6.3-aufs/fs/aufs/procfs.c 2020-04-10 12:40:52.192049502 +0300 -+++ linux-5.6.3-aufs-fix/fs/aufs/procfs.c 2020-04-10 17:46:50.019444421 +0300 -@@ -116,10 +116,9 @@ out: - return err; - } - --static const struct file_operations au_procfs_plm_fop = { -- .write = au_procfs_plm_write, -- .release = au_procfs_plm_release, -- .owner = THIS_MODULE -+static const struct proc_ops au_procfs_plm_op = { -+ .proc_write = au_procfs_plm_write, -+ .proc_release = au_procfs_plm_release - }; - - /* ---------------------------------------------------------------------- */ -@@ -143,7 +142,7 @@ int __init au_procfs_init(void) - goto out; - - entry = proc_create(AUFS_PLINK_MAINT_NAME, S_IFREG | 0200, -- au_procfs_dir, &au_procfs_plm_fop); -+ au_procfs_dir, &au_procfs_plm_op); - if (unlikely(!entry)) - goto out_dir; - -diff -Nurp linux-5.6.3-aufs/fs/aufs/xino.c linux-5.6.3-aufs-fix/fs/aufs/xino.c ---- linux-5.6.3-aufs/fs/aufs/xino.c 2020-04-10 12:40:52.193049549 +0300 -+++ linux-5.6.3-aufs-fix/fs/aufs/xino.c 2020-04-10 17:46:25.165284147 +0300 -@@ -1344,7 +1344,8 @@ static void au_xino_release(struct kref - hlist_bl_lock(hbl); - hlist_bl_for_each_entry_safe(p, pos, n, hbl, node) { - hlist_bl_del(&p->node); -- au_kfree_rcu(p); -+ /* kmemleak reported au_kfree_rcu() doesn't free it */ -+ kfree(p); - } - hlist_bl_unlock(hbl); - } diff --git a/kernel/kernel/files/patches/mageia/fs-aufs-5.6-modular.patch b/kernel/kernel/files/patches/mageia/fs-aufs-5.6-modular.patch deleted file mode 100644 index ad296b9a..00000000 --- a/kernel/kernel/files/patches/mageia/fs-aufs-5.6-modular.patch +++ /dev/null @@ -1,312 +0,0 @@ - - fs/aufs/Kconfig | 2 +- - fs/dcache.c | 2 ++ - fs/exec.c | 1 + - fs/fcntl.c | 1 + - fs/file_table.c | 2 ++ - fs/inode.c | 1 + - fs/namespace.c | 3 +++ - fs/notify/group.c | 1 + - fs/open.c | 1 + - fs/read_write.c | 4 ++++ - fs/splice.c | 2 ++ - fs/sync.c | 1 + - fs/xattr.c | 1 + - kernel/locking/lockdep.c | 1 + - kernel/task_work.c | 1 + - security/security.c | 8 ++++++++ - 16 files changed, 31 insertions(+), 1 deletion(-) - -diff -Nurp linux-5.6.3-aufs/fs/aufs/Kconfig linux-5.6.3-aufs-mod/fs/aufs/Kconfig ---- linux-5.6.3-aufs/fs/aufs/Kconfig 2020-04-10 12:40:52.187049268 +0300 -+++ linux-5.6.3-aufs-mod/fs/aufs/Kconfig 2020-04-10 13:15:44.979742386 +0300 -@@ -1,6 +1,6 @@ - # SPDX-License-Identifier: GPL-2.0 - config AUFS_FS -- bool "Aufs (Advanced multi layered unification filesystem) support" -+ tristate "Aufs (Advanced multi layered unification filesystem) support" - help - Aufs is a stackable unification filesystem such as Unionfs, - which unifies several directories and provides a merged single -diff -Nurp linux-5.6.3-aufs/fs/dcache.c linux-5.6.3-aufs-mod/fs/dcache.c ---- linux-5.6.3-aufs/fs/dcache.c 2020-04-10 12:40:52.194049596 +0300 -+++ linux-5.6.3-aufs-mod/fs/dcache.c 2020-04-10 13:15:44.979742386 +0300 -@@ -1371,6 +1371,7 @@ rename_retry: - seq = 1; - goto again; - } -+EXPORT_SYMBOL_GPL(d_walk); - - struct check_mount { - struct vfsmount *mnt; -@@ -2916,6 +2917,7 @@ void d_exchange(struct dentry *dentry1, - - write_sequnlock(&rename_lock); - } -+EXPORT_SYMBOL_GPL(d_exchange); - - /** - * d_ancestor - search for an ancestor -diff -Nurp linux-5.6.3-aufs/fs/exec.c linux-5.6.3-aufs-mod/fs/exec.c ---- linux-5.6.3-aufs/fs/exec.c 2020-03-30 01:25:41.000000000 +0300 -+++ linux-5.6.3-aufs-mod/fs/exec.c 2020-04-10 13:15:44.979742386 +0300 -@@ -109,6 +109,7 @@ bool path_noexec(const struct path *path - return (path->mnt->mnt_flags & MNT_NOEXEC) || - (path->mnt->mnt_sb->s_iflags & SB_I_NOEXEC); - } -+EXPORT_SYMBOL_GPL(path_noexec); - - #ifdef CONFIG_USELIB - /* -diff -Nurp linux-5.6.3-aufs/fs/fcntl.c linux-5.6.3-aufs-mod/fs/fcntl.c ---- linux-5.6.3-aufs/fs/fcntl.c 2020-04-10 12:40:52.194049596 +0300 -+++ linux-5.6.3-aufs-mod/fs/fcntl.c 2020-04-10 13:15:44.979742386 +0300 -@@ -85,6 +85,7 @@ int setfl(int fd, struct file *filp, uns - out: - return error; - } -+EXPORT_SYMBOL_GPL(setfl); - - static void f_modown(struct file *filp, struct pid *pid, enum pid_type type, - int force) -diff -Nurp linux-5.6.3-aufs/fs/file_table.c linux-5.6.3-aufs-mod/fs/file_table.c ---- linux-5.6.3-aufs/fs/file_table.c 2020-03-30 01:25:41.000000000 +0300 -+++ linux-5.6.3-aufs-mod/fs/file_table.c 2020-04-10 13:15:44.979742386 +0300 -@@ -162,6 +162,7 @@ over: - } - return ERR_PTR(-ENFILE); - } -+EXPORT_SYMBOL_GPL(alloc_empty_file); - - /* - * Variant of alloc_empty_file() that doesn't check and modify nr_files. -@@ -375,6 +376,7 @@ void __fput_sync(struct file *file) - } - - EXPORT_SYMBOL(fput); -+EXPORT_SYMBOL_GPL(__fput_sync); - - void __init files_init(void) - { -diff -Nurp linux-5.6.3-aufs/fs/inode.c linux-5.6.3-aufs-mod/fs/inode.c ---- linux-5.6.3-aufs/fs/inode.c 2020-04-10 12:40:52.194049596 +0300 -+++ linux-5.6.3-aufs-mod/fs/inode.c 2020-04-10 13:15:44.980742432 +0300 -@@ -1694,6 +1694,7 @@ int update_time(struct inode *inode, str - return inode->i_op->update_time(inode, time, flags); - return generic_update_time(inode, time, flags); - } -+EXPORT_SYMBOL_GPL(update_time); - - /** - * touch_atime - update the access time -diff -Nurp linux-5.6.3-aufs/fs/namespace.c linux-5.6.3-aufs-mod/fs/namespace.c ---- linux-5.6.3-aufs/fs/namespace.c 2020-04-10 12:40:52.194049596 +0300 -+++ linux-5.6.3-aufs-mod/fs/namespace.c 2020-04-10 13:15:44.980742432 +0300 -@@ -431,6 +431,7 @@ void __mnt_drop_write(struct vfsmount *m - mnt_dec_writers(real_mount(mnt)); - preempt_enable(); - } -+EXPORT_SYMBOL_GPL(__mnt_drop_write); - - /** - * mnt_drop_write - give up write access to a mount -@@ -781,6 +782,7 @@ int is_current_mnt_ns(struct vfsmount *m - { - return check_mnt(real_mount(mnt)); - } -+EXPORT_SYMBOL_GPL(is_current_mnt_ns); - - /* - * vfsmount lock must be held for write -@@ -1903,6 +1905,7 @@ int iterate_mounts(int (*f)(struct vfsmo - } - return 0; - } -+EXPORT_SYMBOL_GPL(iterate_mounts); - - static void lock_mnt_tree(struct mount *mnt) - { -diff -Nurp linux-5.6.3-aufs/fs/notify/group.c linux-5.6.3-aufs-mod/fs/notify/group.c ---- linux-5.6.3-aufs/fs/notify/group.c 2020-03-30 01:25:41.000000000 +0300 -+++ linux-5.6.3-aufs-mod/fs/notify/group.c 2020-04-10 13:15:44.980742432 +0300 -@@ -99,6 +99,7 @@ void fsnotify_get_group(struct fsnotify_ - { - refcount_inc(&group->refcnt); - } -+EXPORT_SYMBOL_GPL(fsnotify_get_group); - - /* - * Drop a reference to a group. Free it if it's through. -diff -Nurp linux-5.6.3-aufs/fs/open.c linux-5.6.3-aufs-mod/fs/open.c ---- linux-5.6.3-aufs/fs/open.c 2020-03-30 01:25:41.000000000 +0300 -+++ linux-5.6.3-aufs-mod/fs/open.c 2020-04-10 13:15:44.980742432 +0300 -@@ -65,6 +65,7 @@ int do_truncate(struct dentry *dentry, l - inode_unlock(dentry->d_inode); - return ret; - } -+EXPORT_SYMBOL_GPL(do_truncate); - - long vfs_truncate(const struct path *path, loff_t length) - { -diff -Nurp linux-5.6.3-aufs/fs/read_write.c linux-5.6.3-aufs-mod/fs/read_write.c ---- linux-5.6.3-aufs/fs/read_write.c 2020-04-10 12:40:52.194049596 +0300 -+++ linux-5.6.3-aufs-mod/fs/read_write.c 2020-04-10 13:15:44.981742479 +0300 -@@ -468,6 +468,7 @@ ssize_t vfs_read(struct file *file, char - - return ret; - } -+EXPORT_SYMBOL_GPL(vfs_read); - - static ssize_t new_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos) - { -@@ -508,6 +509,7 @@ vfs_readf_t vfs_readf(struct file *file) - return new_sync_read; - return ERR_PTR(-ENOSYS); /* doesn't have ->read(|_iter)() op */ - } -+EXPORT_SYMBOL_GPL(vfs_readf); - - vfs_writef_t vfs_writef(struct file *file) - { -@@ -519,6 +521,7 @@ vfs_writef_t vfs_writef(struct file *fil - return new_sync_write; - return ERR_PTR(-ENOSYS); /* doesn't have ->write(|_iter)() op */ - } -+EXPORT_SYMBOL_GPL(vfs_writef); - - ssize_t __kernel_write(struct file *file, const void *buf, size_t count, loff_t *pos) - { -@@ -588,6 +591,7 @@ ssize_t vfs_write(struct file *file, con - - return ret; - } -+EXPORT_SYMBOL_GPL(vfs_write); - - /* file_ppos returns &file->f_pos or NULL if file is stream */ - static inline loff_t *file_ppos(struct file *file) -diff -Nurp linux-5.6.3-aufs/fs/splice.c linux-5.6.3-aufs-mod/fs/splice.c ---- linux-5.6.3-aufs/fs/splice.c 2020-04-10 12:40:52.194049596 +0300 -+++ linux-5.6.3-aufs-mod/fs/splice.c 2020-04-10 13:15:44.981742479 +0300 -@@ -862,6 +862,7 @@ long do_splice_from(struct pipe_inode_in - - return splice_write(pipe, out, ppos, len, flags); - } -+EXPORT_SYMBOL_GPL(do_splice_from); - - /* - * Attempt to initiate a splice from a file to a pipe. -@@ -891,6 +892,7 @@ long do_splice_to(struct file *in, loff_ - - return splice_read(in, ppos, pipe, len, flags); - } -+EXPORT_SYMBOL_GPL(do_splice_to); - - /** - * splice_direct_to_actor - splices data directly between two non-pipes -diff -Nurp linux-5.6.3-aufs/fs/sync.c linux-5.6.3-aufs-mod/fs/sync.c ---- linux-5.6.3-aufs/fs/sync.c 2020-04-10 12:40:52.194049596 +0300 -+++ linux-5.6.3-aufs-mod/fs/sync.c 2020-04-10 13:15:44.981742479 +0300 -@@ -39,6 +39,7 @@ int __sync_filesystem(struct super_block - sb->s_op->sync_fs(sb, wait); - return __sync_blockdev(sb->s_bdev, wait); - } -+EXPORT_SYMBOL_GPL(__sync_filesystem); - - /* - * Write out and wait upon all dirty data associated with this -diff -Nurp linux-5.6.3-aufs/fs/xattr.c linux-5.6.3-aufs-mod/fs/xattr.c ---- linux-5.6.3-aufs/fs/xattr.c 2020-03-30 01:25:41.000000000 +0300 -+++ linux-5.6.3-aufs-mod/fs/xattr.c 2020-04-10 13:15:44.981742479 +0300 -@@ -296,6 +296,7 @@ vfs_getxattr_alloc(struct dentry *dentry - *xattr_value = value; - return error; - } -+EXPORT_SYMBOL_GPL(vfs_getxattr_alloc); - - ssize_t - __vfs_getxattr(struct dentry *dentry, struct inode *inode, const char *name, -diff -Nurp linux-5.6.3-aufs/kernel/locking/lockdep.c linux-5.6.3-aufs-mod/kernel/locking/lockdep.c ---- linux-5.6.3-aufs/kernel/locking/lockdep.c 2020-04-10 12:40:52.195049643 +0300 -+++ linux-5.6.3-aufs-mod/kernel/locking/lockdep.c 2020-04-10 13:15:44.982742525 +0300 -@@ -174,6 +174,7 @@ inline struct lock_class *lockdep_hlock_ - */ - return lock_classes + class_idx; - } -+EXPORT_SYMBOL_GPL(lockdep_hlock_class); - #define hlock_class(hlock) lockdep_hlock_class(hlock) - - #ifdef CONFIG_LOCK_STAT -diff -Nurp linux-5.6.3-aufs/kernel/task_work.c linux-5.6.3-aufs-mod/kernel/task_work.c ---- linux-5.6.3-aufs/kernel/task_work.c 2020-03-30 01:25:41.000000000 +0300 -+++ linux-5.6.3-aufs-mod/kernel/task_work.c 2020-04-10 13:15:44.982742525 +0300 -@@ -116,3 +116,4 @@ void task_work_run(void) - } while (work); - } - } -+EXPORT_SYMBOL_GPL(task_work_run); -diff -Nurp linux-5.6.3-aufs/security/security.c linux-5.6.3-aufs-mod/security/security.c ---- linux-5.6.3-aufs/security/security.c 2020-03-30 01:25:41.000000000 +0300 -+++ linux-5.6.3-aufs-mod/security/security.c 2020-04-10 13:15:44.982742525 +0300 -@@ -1068,6 +1068,7 @@ int security_path_rmdir(const struct pat - return 0; - return call_int_hook(path_rmdir, 0, dir, dentry); - } -+EXPORT_SYMBOL_GPL(security_path_rmdir); - - int security_path_unlink(const struct path *dir, struct dentry *dentry) - { -@@ -1084,6 +1085,7 @@ int security_path_symlink(const struct p - return 0; - return call_int_hook(path_symlink, 0, dir, dentry, old_name); - } -+EXPORT_SYMBOL_GPL(security_path_symlink); - - int security_path_link(struct dentry *old_dentry, const struct path *new_dir, - struct dentry *new_dentry) -@@ -1092,6 +1094,7 @@ int security_path_link(struct dentry *ol - return 0; - return call_int_hook(path_link, 0, old_dentry, new_dir, new_dentry); - } -+EXPORT_SYMBOL_GPL(security_path_link); - - int security_path_rename(const struct path *old_dir, struct dentry *old_dentry, - const struct path *new_dir, struct dentry *new_dentry, -@@ -1119,6 +1122,7 @@ int security_path_truncate(const struct - return 0; - return call_int_hook(path_truncate, 0, path); - } -+EXPORT_SYMBOL_GPL(security_path_truncate); - - int security_path_chmod(const struct path *path, umode_t mode) - { -@@ -1126,6 +1130,7 @@ int security_path_chmod(const struct pat - return 0; - return call_int_hook(path_chmod, 0, path, mode); - } -+EXPORT_SYMBOL_GPL(security_path_chmod); - - int security_path_chown(const struct path *path, kuid_t uid, kgid_t gid) - { -@@ -1133,6 +1138,7 @@ int security_path_chown(const struct pat - return 0; - return call_int_hook(path_chown, 0, path, uid, gid); - } -+EXPORT_SYMBOL_GPL(security_path_chown); - - int security_path_chroot(const struct path *path) - { -@@ -1233,6 +1239,7 @@ int security_inode_permission(struct ino - return 0; - return call_int_hook(inode_permission, 0, inode, mask); - } -+EXPORT_SYMBOL_GPL(security_inode_permission); - - int security_inode_setattr(struct dentry *dentry, struct iattr *attr) - { -@@ -1410,6 +1417,7 @@ int security_file_permission(struct file - - return fsnotify_perm(file, mask); - } -+EXPORT_SYMBOL_GPL(security_file_permission); - - int security_file_alloc(struct file *file) - { diff --git a/kernel/kernel/files/patches/mageia/fs-aufs-5.6.patch b/kernel/kernel/files/patches/mageia/fs-aufs-5.6.patch deleted file mode 100644 index 52c8cfbb..00000000 --- a/kernel/kernel/files/patches/mageia/fs-aufs-5.6.patch +++ /dev/null @@ -1,37834 +0,0 @@ - - Documentation/ABI/testing/debugfs-aufs | 55 - Documentation/ABI/testing/sysfs-aufs | 31 - Documentation/filesystems/aufs/README | 401 +++ - Documentation/filesystems/aufs/design/01intro.txt | 158 + - Documentation/filesystems/aufs/design/02struct.txt | 245 ++ - Documentation/filesystems/aufs/design/03atomic_open.txt | 72 - Documentation/filesystems/aufs/design/03lookup.txt | 100 - Documentation/filesystems/aufs/design/04branch.txt | 61 - Documentation/filesystems/aufs/design/05wbr_policy.txt | 51 - Documentation/filesystems/aufs/design/06dirren.dot | 31 - Documentation/filesystems/aufs/design/06dirren.txt | 89 - Documentation/filesystems/aufs/design/06fhsm.txt | 105 - Documentation/filesystems/aufs/design/06mmap.txt | 59 - Documentation/filesystems/aufs/design/06xattr.txt | 81 - Documentation/filesystems/aufs/design/07export.txt | 45 - Documentation/filesystems/aufs/design/08shwh.txt | 39 - Documentation/filesystems/aufs/design/10dynop.txt | 34 - MAINTAINERS | 13 - drivers/block/loop.c | 18 - fs/Kconfig | 1 - fs/Makefile | 1 - fs/aufs/Kconfig | 199 + - fs/aufs/Makefile | 39 - fs/aufs/aufs.h | 49 - fs/aufs/branch.c | 1415 +++++++++++ - fs/aufs/branch.h | 353 ++ - fs/aufs/cpup.c | 1445 +++++++++++ - fs/aufs/cpup.h | 87 - fs/aufs/dbgaufs.c | 513 ++++ - fs/aufs/dbgaufs.h | 40 - fs/aufs/dcsub.c | 212 + - fs/aufs/dcsub.h | 124 + - fs/aufs/debug.c | 428 +++ - fs/aufs/debug.h | 213 + - fs/aufs/dentry.c | 1141 +++++++++ - fs/aufs/dentry.h | 255 ++ - fs/aufs/dinfo.c | 541 ++++ - fs/aufs/dir.c | 750 ++++++ - fs/aufs/dir.h | 121 - fs/aufs/dirren.c | 1303 ++++++++++ - fs/aufs/dirren.h | 127 + - fs/aufs/dynop.c | 354 ++ - fs/aufs/dynop.h | 64 - fs/aufs/export.c | 825 ++++++ - fs/aufs/f_op.c | 806 ++++++ - fs/aufs/fhsm.c | 413 +++ - fs/aufs/file.c | 850 ++++++ - fs/aufs/file.h | 329 ++ - fs/aufs/finfo.c | 136 + - fs/aufs/fstype.h | 388 +++ - fs/aufs/hbl.h | 52 - fs/aufs/hfsnotify.c | 275 ++ - fs/aufs/hfsplus.c | 47 - fs/aufs/hnotify.c | 702 +++++ - fs/aufs/i_op.c | 1485 ++++++++++++ - fs/aufs/i_op_add.c | 923 +++++++ - fs/aufs/i_op_del.c | 500 ++++ - fs/aufs/i_op_ren.c | 1237 ++++++++++ - fs/aufs/iinfo.c | 273 ++ - fs/aufs/inode.c | 516 ++++ - fs/aufs/inode.h | 685 +++++ - fs/aufs/ioctl.c | 207 + - fs/aufs/lcnt.h | 173 + - fs/aufs/loop.c | 135 + - fs/aufs/loop.h | 42 - fs/aufs/magic.mk | 31 - fs/aufs/module.c | 259 ++ - fs/aufs/module.h | 153 + - fs/aufs/mvdown.c | 693 +++++ - fs/aufs/opts.c | 1867 +++++++++++++++ - fs/aufs/opts.h | 212 + - fs/aufs/plink.c | 503 ++++ - fs/aufs/poll.c | 38 - fs/aufs/posix_acl.c | 92 - fs/aufs/procfs.c | 158 + - fs/aufs/rdu.c | 371 +++ - fs/aufs/rwsem.h | 60 - fs/aufs/sbinfo.c | 301 ++ - fs/aufs/super.c | 1034 ++++++++ - fs/aufs/super.h | 576 ++++ - fs/aufs/sysaufs.c | 80 - fs/aufs/sysaufs.h | 89 - fs/aufs/sysfs.c | 338 ++ - fs/aufs/sysrq.c | 136 + - fs/aufs/vdir.c | 883 +++++++ - fs/aufs/vfsub.c | 889 +++++++ - fs/aufs/vfsub.h | 341 ++ - fs/aufs/wbr_policy.c | 817 ++++++ - fs/aufs/whout.c | 1049 ++++++++ - fs/aufs/whout.h | 73 - fs/aufs/wkq.c | 359 ++ - fs/aufs/wkq.h | 76 - fs/aufs/xattr.c | 343 ++ - fs/aufs/xino.c | 1952 ++++++++++++++++ - fs/dcache.c | 2 - fs/fcntl.c | 4 - fs/inode.c | 2 - fs/namespace.c | 6 - fs/proc/base.c | 2 - fs/proc/nommu.c | 5 - fs/proc/task_mmu.c | 7 - fs/proc/task_nommu.c | 5 - fs/read_write.c | 22 - fs/splice.c | 10 - fs/sync.c | 2 - include/linux/fs.h | 10 - include/linux/lockdep.h | 3 - include/linux/mm.h | 22 - include/linux/mm_types.h | 2 - include/linux/mnt_namespace.h | 3 - include/linux/splice.h | 6 - include/uapi/linux/aufs_type.h | 439 +++ - kernel/fork.c | 2 - kernel/locking/lockdep.c | 3 - mm/Makefile | 2 - mm/filemap.c | 2 - mm/mmap.c | 33 - mm/nommu.c | 10 - mm/prfile.c | 86 - 119 files changed, 36894 insertions(+), 31 deletions(-) - -diff -Nurp linux-5.6.3/Documentation/ABI/testing/debugfs-aufs linux-5.6.3-aufs/Documentation/ABI/testing/debugfs-aufs ---- linux-5.6.3/Documentation/ABI/testing/debugfs-aufs 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/Documentation/ABI/testing/debugfs-aufs 2020-04-10 12:40:52.184049128 +0300 -@@ -0,0 +1,55 @@ -+What: /debug/aufs/si_/ -+Date: March 2009 -+Contact: J. R. Okajima -+Description: -+ Under /debug/aufs, a directory named si_ is created -+ per aufs mount, where is a unique id generated -+ internally. -+ -+What: /debug/aufs/si_/plink -+Date: Apr 2013 -+Contact: J. R. Okajima -+Description: -+ It has three lines and shows the information about the -+ pseudo-link. The first line is a single number -+ representing a number of buckets. The second line is a -+ number of pseudo-links per buckets (separated by a -+ blank). The last line is a single number representing a -+ total number of psedo-links. -+ When the aufs mount option 'noplink' is specified, it -+ will show "1\n0\n0\n". -+ -+What: /debug/aufs/si_/xib -+Date: March 2009 -+Contact: J. R. Okajima -+Description: -+ It shows the consumed blocks by xib (External Inode Number -+ Bitmap), its block size and file size. -+ When the aufs mount option 'noxino' is specified, it -+ will be empty. About XINO files, see the aufs manual. -+ -+What: /debug/aufs/si_/xi0, xi1 ... xiN and xiN-N -+Date: March 2009 -+Contact: J. R. Okajima -+Description: -+ It shows the consumed blocks by xino (External Inode Number -+ Translation Table), its link count, block size and file -+ size. -+ Due to the file size limit, there may exist multiple -+ xino files per branch. In this case, "-N" is added to -+ the filename and it corresponds to the index of the -+ internal xino array. "-0" is omitted. -+ When the aufs mount option 'noxino' is specified, Those -+ entries won't exist. About XINO files, see the aufs -+ manual. -+ -+What: /debug/aufs/si_/xigen -+Date: March 2009 -+Contact: J. R. Okajima -+Description: -+ It shows the consumed blocks by xigen (External Inode -+ Generation Table), its block size and file size. -+ If CONFIG_AUFS_EXPORT is disabled, this entry will not -+ be created. -+ When the aufs mount option 'noxino' is specified, it -+ will be empty. About XINO files, see the aufs manual. -diff -Nurp linux-5.6.3/Documentation/ABI/testing/sysfs-aufs linux-5.6.3-aufs/Documentation/ABI/testing/sysfs-aufs ---- linux-5.6.3/Documentation/ABI/testing/sysfs-aufs 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/Documentation/ABI/testing/sysfs-aufs 2020-04-10 12:40:52.184049128 +0300 -@@ -0,0 +1,31 @@ -+What: /sys/fs/aufs/si_/ -+Date: March 2009 -+Contact: J. R. Okajima -+Description: -+ Under /sys/fs/aufs, a directory named si_ is created -+ per aufs mount, where is a unique id generated -+ internally. -+ -+What: /sys/fs/aufs/si_/br0, br1 ... brN -+Date: March 2009 -+Contact: J. R. Okajima -+Description: -+ It shows the abolute path of a member directory (which -+ is called branch) in aufs, and its permission. -+ -+What: /sys/fs/aufs/si_/brid0, brid1 ... bridN -+Date: July 2013 -+Contact: J. R. Okajima -+Description: -+ It shows the id of a member directory (which is called -+ branch) in aufs. -+ -+What: /sys/fs/aufs/si_/xi_path -+Date: March 2009 -+Contact: J. R. Okajima -+Description: -+ It shows the abolute path of XINO (External Inode Number -+ Bitmap, Translation Table and Generation Table) file -+ even if it is the default path. -+ When the aufs mount option 'noxino' is specified, it -+ will be empty. About XINO files, see the aufs manual. -diff -Nurp linux-5.6.3/Documentation/filesystems/aufs/design/01intro.txt linux-5.6.3-aufs/Documentation/filesystems/aufs/design/01intro.txt ---- linux-5.6.3/Documentation/filesystems/aufs/design/01intro.txt 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/Documentation/filesystems/aufs/design/01intro.txt 2020-04-10 12:40:52.184049128 +0300 -@@ -0,0 +1,158 @@ -+ -+# Copyright (C) 2005-2020 Junjiro R. Okajima -+ -+Introduction -+---------------------------------------- -+ -+aufs [ei ju: ef es] | /ey-yoo-ef-es/ | [a u f s] -+1. abbrev. for "advanced multi-layered unification filesystem". -+2. abbrev. for "another unionfs". -+3. abbrev. for "auf das" in German which means "on the" in English. -+ Ex. "Butter aufs Brot"(G) means "butter onto bread"(E). -+ But "Filesystem aufs Filesystem" is hard to understand. -+4. abbrev. for "African Urban Fashion Show". -+ -+AUFS is a filesystem with features: -+- multi layered stackable unification filesystem, the member directory -+ is called as a branch. -+- branch permission and attribute, 'readonly', 'real-readonly', -+ 'readwrite', 'whiteout-able', 'link-able whiteout', etc. and their -+ combination. -+- internal "file copy-on-write". -+- logical deletion, whiteout. -+- dynamic branch manipulation, adding, deleting and changing permission. -+- allow bypassing aufs, user's direct branch access. -+- external inode number translation table and bitmap which maintains the -+ persistent aufs inode number. -+- seekable directory, including NFS readdir. -+- file mapping, mmap and sharing pages. -+- pseudo-link, hardlink over branches. -+- loopback mounted filesystem as a branch. -+- several policies to select one among multiple writable branches. -+- revert a single systemcall when an error occurs in aufs. -+- and more... -+ -+ -+Multi Layered Stackable Unification Filesystem -+---------------------------------------------------------------------- -+Most people already knows what it is. -+It is a filesystem which unifies several directories and provides a -+merged single directory. When users access a file, the access will be -+passed/re-directed/converted (sorry, I am not sure which English word is -+correct) to the real file on the member filesystem. The member -+filesystem is called 'lower filesystem' or 'branch' and has a mode -+'readonly' and 'readwrite.' And the deletion for a file on the lower -+readonly branch is handled by creating 'whiteout' on the upper writable -+branch. -+ -+On LKML, there have been discussions about UnionMount (Jan Blunck, -+Bharata B Rao and Valerie Aurora) and Unionfs (Erez Zadok). They took -+different approaches to implement the merged-view. -+The former tries putting it into VFS, and the latter implements as a -+separate filesystem. -+(If I misunderstand about these implementations, please let me know and -+I shall correct it. Because it is a long time ago when I read their -+source files last time). -+ -+UnionMount's approach will be able to small, but may be hard to share -+branches between several UnionMount since the whiteout in it is -+implemented in the inode on branch filesystem and always -+shared. According to Bharata's post, readdir does not seems to be -+finished yet. -+There are several missing features known in this implementations such as -+- for users, the inode number may change silently. eg. copy-up. -+- link(2) may break by copy-up. -+- read(2) may get an obsoleted filedata (fstat(2) too). -+- fcntl(F_SETLK) may be broken by copy-up. -+- unnecessary copy-up may happen, for example mmap(MAP_PRIVATE) after -+ open(O_RDWR). -+ -+In linux-3.18, "overlay" filesystem (formerly known as "overlayfs") was -+merged into mainline. This is another implementation of UnionMount as a -+separated filesystem. All the limitations and known problems which -+UnionMount are equally inherited to "overlay" filesystem. -+ -+Unionfs has a longer history. When I started implementing a stackable -+filesystem (Aug 2005), it already existed. It has virtual super_block, -+inode, dentry and file objects and they have an array pointing lower -+same kind objects. After contributing many patches for Unionfs, I -+re-started my project AUFS (Jun 2006). -+ -+In AUFS, the structure of filesystem resembles to Unionfs, but I -+implemented my own ideas, approaches and enhancements and it became -+totally different one. -+ -+Comparing DM snapshot and fs based implementation -+- the number of bytes to be copied between devices is much smaller. -+- the type of filesystem must be one and only. -+- the fs must be writable, no readonly fs, even for the lower original -+ device. so the compression fs will not be usable. but if we use -+ loopback mount, we may address this issue. -+ for instance, -+ mount /cdrom/squashfs.img /sq -+ losetup /sq/ext2.img -+ losetup /somewhere/cow -+ dmsetup "snapshot /dev/loop0 /dev/loop1 ..." -+- it will be difficult (or needs more operations) to extract the -+ difference between the original device and COW. -+- DM snapshot-merge may help a lot when users try merging. in the -+ fs-layer union, users will use rsync(1). -+ -+You may want to read my old paper "Filesystems in LiveCD" -+(http://aufs.sourceforge.net/aufs2/report/sq/sq.pdf). -+ -+ -+Several characters/aspects/persona of aufs -+---------------------------------------------------------------------- -+ -+Aufs has several characters, aspects or persona. -+1. a filesystem, callee of VFS helper -+2. sub-VFS, caller of VFS helper for branches -+3. a virtual filesystem which maintains persistent inode number -+4. reader/writer of files on branches such like an application -+ -+1. Callee of VFS Helper -+As an ordinary linux filesystem, aufs is a callee of VFS. For instance, -+unlink(2) from an application reaches sys_unlink() kernel function and -+then vfs_unlink() is called. vfs_unlink() is one of VFS helper and it -+calls filesystem specific unlink operation. Actually aufs implements the -+unlink operation but it behaves like a redirector. -+ -+2. Caller of VFS Helper for Branches -+aufs_unlink() passes the unlink request to the branch filesystem as if -+it were called from VFS. So the called unlink operation of the branch -+filesystem acts as usual. As a caller of VFS helper, aufs should handle -+every necessary pre/post operation for the branch filesystem. -+- acquire the lock for the parent dir on a branch -+- lookup in a branch -+- revalidate dentry on a branch -+- mnt_want_write() for a branch -+- vfs_unlink() for a branch -+- mnt_drop_write() for a branch -+- release the lock on a branch -+ -+3. Persistent Inode Number -+One of the most important issue for a filesystem is to maintain inode -+numbers. This is particularly important to support exporting a -+filesystem via NFS. Aufs is a virtual filesystem which doesn't have a -+backend block device for its own. But some storage is necessary to -+keep and maintain the inode numbers. It may be a large space and may not -+suit to keep in memory. Aufs rents some space from its first writable -+branch filesystem (by default) and creates file(s) on it. These files -+are created by aufs internally and removed soon (currently) keeping -+opened. -+Note: Because these files are removed, they are totally gone after -+ unmounting aufs. It means the inode numbers are not persistent -+ across unmount or reboot. I have a plan to make them really -+ persistent which will be important for aufs on NFS server. -+ -+4. Read/Write Files Internally (copy-on-write) -+Because a branch can be readonly, when you write a file on it, aufs will -+"copy-up" it to the upper writable branch internally. And then write the -+originally requested thing to the file. Generally kernel doesn't -+open/read/write file actively. In aufs, even a single write may cause a -+internal "file copy". This behaviour is very similar to cp(1) command. -+ -+Some people may think it is better to pass such work to user space -+helper, instead of doing in kernel space. Actually I am still thinking -+about it. But currently I have implemented it in kernel space. -diff -Nurp linux-5.6.3/Documentation/filesystems/aufs/design/02struct.txt linux-5.6.3-aufs/Documentation/filesystems/aufs/design/02struct.txt ---- linux-5.6.3/Documentation/filesystems/aufs/design/02struct.txt 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/Documentation/filesystems/aufs/design/02struct.txt 2020-04-10 12:40:52.184049128 +0300 -@@ -0,0 +1,245 @@ -+ -+# Copyright (C) 2005-2020 Junjiro R. Okajima -+ -+Basic Aufs Internal Structure -+ -+Superblock/Inode/Dentry/File Objects -+---------------------------------------------------------------------- -+As like an ordinary filesystem, aufs has its own -+superblock/inode/dentry/file objects. All these objects have a -+dynamically allocated array and store the same kind of pointers to the -+lower filesystem, branch. -+For example, when you build a union with one readwrite branch and one -+readonly, mounted /au, /rw and /ro respectively. -+- /au = /rw + /ro -+- /ro/fileA exists but /rw/fileA -+ -+Aufs lookup operation finds /ro/fileA and gets dentry for that. These -+pointers are stored in a aufs dentry. The array in aufs dentry will be, -+- [0] = NULL (because /rw/fileA doesn't exist) -+- [1] = /ro/fileA -+ -+This style of an array is essentially same to the aufs -+superblock/inode/dentry/file objects. -+ -+Because aufs supports manipulating branches, ie. add/delete/change -+branches dynamically, these objects has its own generation. When -+branches are changed, the generation in aufs superblock is -+incremented. And a generation in other object are compared when it is -+accessed. When a generation in other objects are obsoleted, aufs -+refreshes the internal array. -+ -+ -+Superblock -+---------------------------------------------------------------------- -+Additionally aufs superblock has some data for policies to select one -+among multiple writable branches, XIB files, pseudo-links and kobject. -+See below in detail. -+About the policies which supports copy-down a directory, see -+wbr_policy.txt too. -+ -+ -+Branch and XINO(External Inode Number Translation Table) -+---------------------------------------------------------------------- -+Every branch has its own xino (external inode number translation table) -+file. The xino file is created and unlinked by aufs internally. When two -+members of a union exist on the same filesystem, they share the single -+xino file. -+The struct of a xino file is simple, just a sequence of aufs inode -+numbers which is indexed by the lower inode number. -+In the above sample, assume the inode number of /ro/fileA is i111 and -+aufs assigns the inode number i999 for fileA. Then aufs writes 999 as -+4(8) bytes at 111 * 4(8) bytes offset in the xino file. -+ -+When the inode numbers are not contiguous, the xino file will be sparse -+which has a hole in it and doesn't consume as much disk space as it -+might appear. If your branch filesystem consumes disk space for such -+holes, then you should specify 'xino=' option at mounting aufs. -+ -+Aufs has a mount option to free the disk blocks for such holes in XINO -+files on tmpfs or ramdisk. But it is not so effective actually. If you -+meet a problem of disk shortage due to XINO files, then you should try -+"tmpfs-ino.patch" (and "vfs-ino.patch" too) in aufs4-standalone.git. -+The patch localizes the assignment inumbers per tmpfs-mount and avoid -+the holes in XINO files. -+ -+Also a writable branch has three kinds of "whiteout bases". All these -+are existed when the branch is joined to aufs, and their names are -+whiteout-ed doubly, so that users will never see their names in aufs -+hierarchy. -+1. a regular file which will be hardlinked to all whiteouts. -+2. a directory to store a pseudo-link. -+3. a directory to store an "orphan"-ed file temporary. -+ -+1. Whiteout Base -+ When you remove a file on a readonly branch, aufs handles it as a -+ logical deletion and creates a whiteout on the upper writable branch -+ as a hardlink of this file in order not to consume inode on the -+ writable branch. -+2. Pseudo-link Dir -+ See below, Pseudo-link. -+3. Step-Parent Dir -+ When "fileC" exists on the lower readonly branch only and it is -+ opened and removed with its parent dir, and then user writes -+ something into it, then aufs copies-up fileC to this -+ directory. Because there is no other dir to store fileC. After -+ creating a file under this dir, the file is unlinked. -+ -+Because aufs supports manipulating branches, ie. add/delete/change -+dynamically, a branch has its own id. When the branch order changes, -+aufs finds the new index by searching the branch id. -+ -+ -+Pseudo-link -+---------------------------------------------------------------------- -+Assume "fileA" exists on the lower readonly branch only and it is -+hardlinked to "fileB" on the branch. When you write something to fileA, -+aufs copies-up it to the upper writable branch. Additionally aufs -+creates a hardlink under the Pseudo-link Directory of the writable -+branch. The inode of a pseudo-link is kept in aufs super_block as a -+simple list. If fileB is read after unlinking fileA, aufs returns -+filedata from the pseudo-link instead of the lower readonly -+branch. Because the pseudo-link is based upon the inode, to keep the -+inode number by xino (see above) is essentially necessary. -+ -+All the hardlinks under the Pseudo-link Directory of the writable branch -+should be restored in a proper location later. Aufs provides a utility -+to do this. The userspace helpers executed at remounting and unmounting -+aufs by default. -+During this utility is running, it puts aufs into the pseudo-link -+maintenance mode. In this mode, only the process which began the -+maintenance mode (and its child processes) is allowed to operate in -+aufs. Some other processes which are not related to the pseudo-link will -+be allowed to run too, but the rest have to return an error or wait -+until the maintenance mode ends. If a process already acquires an inode -+mutex (in VFS), it has to return an error. -+ -+ -+XIB(external inode number bitmap) -+---------------------------------------------------------------------- -+Addition to the xino file per a branch, aufs has an external inode number -+bitmap in a superblock object. It is also an internal file such like a -+xino file. -+It is a simple bitmap to mark whether the aufs inode number is in-use or -+not. -+To reduce the file I/O, aufs prepares a single memory page to cache xib. -+ -+As well as XINO files, aufs has a feature to truncate/refresh XIB to -+reduce the number of consumed disk blocks for these files. -+ -+ -+Virtual or Vertical Dir, and Readdir in Userspace -+---------------------------------------------------------------------- -+In order to support multiple layers (branches), aufs readdir operation -+constructs a virtual dir block on memory. For readdir, aufs calls -+vfs_readdir() internally for each dir on branches, merges their entries -+with eliminating the whiteout-ed ones, and sets it to file (dir) -+object. So the file object has its entry list until it is closed. The -+entry list will be updated when the file position is zero and becomes -+obsoleted. This decision is made in aufs automatically. -+ -+The dynamically allocated memory block for the name of entries has a -+unit of 512 bytes (by default) and stores the names contiguously (no -+padding). Another block for each entry is handled by kmem_cache too. -+During building dir blocks, aufs creates hash list and judging whether -+the entry is whiteouted by its upper branch or already listed. -+The merged result is cached in the corresponding inode object and -+maintained by a customizable life-time option. -+ -+Some people may call it can be a security hole or invite DoS attack -+since the opened and once readdir-ed dir (file object) holds its entry -+list and becomes a pressure for system memory. But I'd say it is similar -+to files under /proc or /sys. The virtual files in them also holds a -+memory page (generally) while they are opened. When an idea to reduce -+memory for them is introduced, it will be applied to aufs too. -+For those who really hate this situation, I've developed readdir(3) -+library which operates this merging in userspace. You just need to set -+LD_PRELOAD environment variable, and aufs will not consume no memory in -+kernel space for readdir(3). -+ -+ -+Workqueue -+---------------------------------------------------------------------- -+Aufs sometimes requires privilege access to a branch. For instance, -+in copy-up/down operation. When a user process is going to make changes -+to a file which exists in the lower readonly branch only, and the mode -+of one of ancestor directories may not be writable by a user -+process. Here aufs copy-up the file with its ancestors and they may -+require privilege to set its owner/group/mode/etc. -+This is a typical case of a application character of aufs (see -+Introduction). -+ -+Aufs uses workqueue synchronously for this case. It creates its own -+workqueue. The workqueue is a kernel thread and has privilege. Aufs -+passes the request to call mkdir or write (for example), and wait for -+its completion. This approach solves a problem of a signal handler -+simply. -+If aufs didn't adopt the workqueue and changed the privilege of the -+process, then the process may receive the unexpected SIGXFSZ or other -+signals. -+ -+Also aufs uses the system global workqueue ("events" kernel thread) too -+for asynchronous tasks, such like handling inotify/fsnotify, re-creating a -+whiteout base and etc. This is unrelated to a privilege. -+Most of aufs operation tries acquiring a rw_semaphore for aufs -+superblock at the beginning, at the same time waits for the completion -+of all queued asynchronous tasks. -+ -+ -+Whiteout -+---------------------------------------------------------------------- -+The whiteout in aufs is very similar to Unionfs's. That is represented -+by its filename. UnionMount takes an approach of a file mode, but I am -+afraid several utilities (find(1) or something) will have to support it. -+ -+Basically the whiteout represents "logical deletion" which stops aufs to -+lookup further, but also it represents "dir is opaque" which also stop -+further lookup. -+ -+In aufs, rmdir(2) and rename(2) for dir uses whiteout alternatively. -+In order to make several functions in a single systemcall to be -+revertible, aufs adopts an approach to rename a directory to a temporary -+unique whiteouted name. -+For example, in rename(2) dir where the target dir already existed, aufs -+renames the target dir to a temporary unique whiteouted name before the -+actual rename on a branch, and then handles other actions (make it opaque, -+update the attributes, etc). If an error happens in these actions, aufs -+simply renames the whiteouted name back and returns an error. If all are -+succeeded, aufs registers a function to remove the whiteouted unique -+temporary name completely and asynchronously to the system global -+workqueue. -+ -+ -+Copy-up -+---------------------------------------------------------------------- -+It is a well-known feature or concept. -+When user modifies a file on a readonly branch, aufs operate "copy-up" -+internally and makes change to the new file on the upper writable branch. -+When the trigger systemcall does not update the timestamps of the parent -+dir, aufs reverts it after copy-up. -+ -+ -+Move-down (aufs3.9 and later) -+---------------------------------------------------------------------- -+"Copy-up" is one of the essential feature in aufs. It copies a file from -+the lower readonly branch to the upper writable branch when a user -+changes something about the file. -+"Move-down" is an opposite action of copy-up. Basically this action is -+ran manually instead of automatically and internally. -+For desgin and implementation, aufs has to consider these issues. -+- whiteout for the file may exist on the lower branch. -+- ancestor directories may not exist on the lower branch. -+- diropq for the ancestor directories may exist on the upper branch. -+- free space on the lower branch will reduce. -+- another access to the file may happen during moving-down, including -+ UDBA (see "Revalidate Dentry and UDBA"). -+- the file should not be hard-linked nor pseudo-linked. they should be -+ handled by auplink utility later. -+ -+Sometimes users want to move-down a file from the upper writable branch -+to the lower readonly or writable branch. For instance, -+- the free space of the upper writable branch is going to run out. -+- create a new intermediate branch between the upper and lower branch. -+- etc. -+ -+For this purpose, use "aumvdown" command in aufs-util.git. -diff -Nurp linux-5.6.3/Documentation/filesystems/aufs/design/03atomic_open.txt linux-5.6.3-aufs/Documentation/filesystems/aufs/design/03atomic_open.txt ---- linux-5.6.3/Documentation/filesystems/aufs/design/03atomic_open.txt 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/Documentation/filesystems/aufs/design/03atomic_open.txt 2020-04-10 12:40:52.184049128 +0300 -@@ -0,0 +1,72 @@ -+ -+# Copyright (C) 2015-2020 Junjiro R. Okajima -+ -+Support for a branch who has its ->atomic_open() -+---------------------------------------------------------------------- -+The filesystems who implement its ->atomic_open() are not majority. For -+example NFSv4 does, and aufs should call NFSv4 ->atomic_open, -+particularly for open(O_CREAT|O_EXCL, 0400) case. Other than -+->atomic_open(), NFSv4 returns an error for this open(2). While I am not -+sure whether all filesystems who have ->atomic_open() behave like this, -+but NFSv4 surely returns the error. -+ -+In order to support ->atomic_open() for aufs, there are a few -+approaches. -+ -+A. Introduce aufs_atomic_open() -+ - calls one of VFS:do_last(), lookup_open() or atomic_open() for -+ branch fs. -+B. Introduce aufs_atomic_open() calling create, open and chmod. this is -+ an aufs user Pip Cet's approach -+ - calls aufs_create(), VFS finish_open() and notify_change(). -+ - pass fake-mode to finish_open(), and then correct the mode by -+ notify_change(). -+C. Extend aufs_open() to call branch fs's ->atomic_open() -+ - no aufs_atomic_open(). -+ - aufs_lookup() registers the TID to an aufs internal object. -+ - aufs_create() does nothing when the matching TID is registered, but -+ registers the mode. -+ - aufs_open() calls branch fs's ->atomic_open() when the matching -+ TID is registered. -+D. Extend aufs_open() to re-try branch fs's ->open() with superuser's -+ credential -+ - no aufs_atomic_open(). -+ - aufs_create() registers the TID to an internal object. this info -+ represents "this process created this file just now." -+ - when aufs gets EACCES from branch fs's ->open(), then confirm the -+ registered TID and re-try open() with superuser's credential. -+ -+Pros and cons for each approach. -+ -+A. -+ - straightforward but highly depends upon VFS internal. -+ - the atomic behavaiour is kept. -+ - some of parameters such as nameidata are hard to reproduce for -+ branch fs. -+ - large overhead. -+B. -+ - easy to implement. -+ - the atomic behavaiour is lost. -+C. -+ - the atomic behavaiour is kept. -+ - dirty and tricky. -+ - VFS checks whether the file is created correctly after calling -+ ->create(), which means this approach doesn't work. -+D. -+ - easy to implement. -+ - the atomic behavaiour is lost. -+ - to open a file with superuser's credential and give it to a user -+ process is a bad idea, since the file object keeps the credential -+ in it. It may affect LSM or something. This approach doesn't work -+ either. -+ -+The approach A is ideal, but it hard to implement. So here is a -+variation of A, which is to be implemented. -+ -+A-1. Introduce aufs_atomic_open() -+ - calls branch fs ->atomic_open() if exists. otherwise calls -+ vfs_create() and finish_open(). -+ - the demerit is that the several checks after branch fs -+ ->atomic_open() are lost. in the ordinary case, the checks are -+ done by VFS:do_last(), lookup_open() and atomic_open(). some can -+ be implemented in aufs, but not all I am afraid. -diff -Nurp linux-5.6.3/Documentation/filesystems/aufs/design/03lookup.txt linux-5.6.3-aufs/Documentation/filesystems/aufs/design/03lookup.txt ---- linux-5.6.3/Documentation/filesystems/aufs/design/03lookup.txt 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/Documentation/filesystems/aufs/design/03lookup.txt 2020-04-10 12:40:52.185049175 +0300 -@@ -0,0 +1,100 @@ -+ -+# Copyright (C) 2005-2020 Junjiro R. Okajima -+ -+Lookup in a Branch -+---------------------------------------------------------------------- -+Since aufs has a character of sub-VFS (see Introduction), it operates -+lookup for branches as VFS does. It may be a heavy work. But almost all -+lookup operation in aufs is the simplest case, ie. lookup only an entry -+directly connected to its parent. Digging down the directory hierarchy -+is unnecessary. VFS has a function lookup_one_len() for that use, and -+aufs calls it. -+ -+When a branch is a remote filesystem, aufs basically relies upon its -+->d_revalidate(), also aufs forces the hardest revalidate tests for -+them. -+For d_revalidate, aufs implements three levels of revalidate tests. See -+"Revalidate Dentry and UDBA" in detail. -+ -+ -+Test Only the Highest One for the Directory Permission (dirperm1 option) -+---------------------------------------------------------------------- -+Let's try case study. -+- aufs has two branches, upper readwrite and lower readonly. -+ /au = /rw + /ro -+- "dirA" exists under /ro, but /rw. and its mode is 0700. -+- user invoked "chmod a+rx /au/dirA" -+- the internal copy-up is activated and "/rw/dirA" is created and its -+ permission bits are set to world readable. -+- then "/au/dirA" becomes world readable? -+ -+In this case, /ro/dirA is still 0700 since it exists in readonly branch, -+or it may be a natively readonly filesystem. If aufs respects the lower -+branch, it should not respond readdir request from other users. But user -+allowed it by chmod. Should really aufs rejects showing the entries -+under /ro/dirA? -+ -+To be honest, I don't have a good solution for this case. So aufs -+implements 'dirperm1' and 'nodirperm1' mount options, and leave it to -+users. -+When dirperm1 is specified, aufs checks only the highest one for the -+directory permission, and shows the entries. Otherwise, as usual, checks -+every dir existing on all branches and rejects the request. -+ -+As a side effect, dirperm1 option improves the performance of aufs -+because the number of permission check is reduced when the number of -+branch is many. -+ -+ -+Revalidate Dentry and UDBA (User's Direct Branch Access) -+---------------------------------------------------------------------- -+Generally VFS helpers re-validate a dentry as a part of lookup. -+0. digging down the directory hierarchy. -+1. lock the parent dir by its i_mutex. -+2. lookup the final (child) entry. -+3. revalidate it. -+4. call the actual operation (create, unlink, etc.) -+5. unlock the parent dir -+ -+If the filesystem implements its ->d_revalidate() (step 3), then it is -+called. Actually aufs implements it and checks the dentry on a branch is -+still valid. -+But it is not enough. Because aufs has to release the lock for the -+parent dir on a branch at the end of ->lookup() (step 2) and -+->d_revalidate() (step 3) while the i_mutex of the aufs dir is still -+held by VFS. -+If the file on a branch is changed directly, eg. bypassing aufs, after -+aufs released the lock, then the subsequent operation may cause -+something unpleasant result. -+ -+This situation is a result of VFS architecture, ->lookup() and -+->d_revalidate() is separated. But I never say it is wrong. It is a good -+design from VFS's point of view. It is just not suitable for sub-VFS -+character in aufs. -+ -+Aufs supports such case by three level of revalidation which is -+selectable by user. -+1. Simple Revalidate -+ Addition to the native flow in VFS's, confirm the child-parent -+ relationship on the branch just after locking the parent dir on the -+ branch in the "actual operation" (step 4). When this validation -+ fails, aufs returns EBUSY. ->d_revalidate() (step 3) in aufs still -+ checks the validation of the dentry on branches. -+2. Monitor Changes Internally by Inotify/Fsnotify -+ Addition to above, in the "actual operation" (step 4) aufs re-lookup -+ the dentry on the branch, and returns EBUSY if it finds different -+ dentry. -+ Additionally, aufs sets the inotify/fsnotify watch for every dir on branches -+ during it is in cache. When the event is notified, aufs registers a -+ function to kernel 'events' thread by schedule_work(). And the -+ function sets some special status to the cached aufs dentry and inode -+ private data. If they are not cached, then aufs has nothing to -+ do. When the same file is accessed through aufs (step 0-3) later, -+ aufs will detect the status and refresh all necessary data. -+ In this mode, aufs has to ignore the event which is fired by aufs -+ itself. -+3. No Extra Validation -+ This is the simplest test and doesn't add any additional revalidation -+ test, and skip the revalidation in step 4. It is useful and improves -+ aufs performance when system surely hide the aufs branches from user, -+ by over-mounting something (or another method). -diff -Nurp linux-5.6.3/Documentation/filesystems/aufs/design/04branch.txt linux-5.6.3-aufs/Documentation/filesystems/aufs/design/04branch.txt ---- linux-5.6.3/Documentation/filesystems/aufs/design/04branch.txt 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/Documentation/filesystems/aufs/design/04branch.txt 2020-04-10 12:40:52.185049175 +0300 -@@ -0,0 +1,61 @@ -+ -+# Copyright (C) 2005-2020 Junjiro R. Okajima -+ -+Branch Manipulation -+ -+Since aufs supports dynamic branch manipulation, ie. add/remove a branch -+and changing its permission/attribute, there are a lot of works to do. -+ -+ -+Add a Branch -+---------------------------------------------------------------------- -+o Confirm the adding dir exists outside of aufs, including loopback -+ mount, and its various attributes. -+o Initialize the xino file and whiteout bases if necessary. -+ See struct.txt. -+ -+o Check the owner/group/mode of the directory -+ When the owner/group/mode of the adding directory differs from the -+ existing branch, aufs issues a warning because it may impose a -+ security risk. -+ For example, when a upper writable branch has a world writable empty -+ top directory, a malicious user can create any files on the writable -+ branch directly, like copy-up and modify manually. If something like -+ /etc/{passwd,shadow} exists on the lower readonly branch but the upper -+ writable branch, and the writable branch is world-writable, then a -+ malicious guy may create /etc/passwd on the writable branch directly -+ and the infected file will be valid in aufs. -+ I am afraid it can be a security issue, but aufs can do nothing except -+ producing a warning. -+ -+ -+Delete a Branch -+---------------------------------------------------------------------- -+o Confirm the deleting branch is not busy -+ To be general, there is one merit to adopt "remount" interface to -+ manipulate branches. It is to discard caches. At deleting a branch, -+ aufs checks the still cached (and connected) dentries and inodes. If -+ there are any, then they are all in-use. An inode without its -+ corresponding dentry can be alive alone (for example, inotify/fsnotify case). -+ -+ For the cached one, aufs checks whether the same named entry exists on -+ other branches. -+ If the cached one is a directory, because aufs provides a merged view -+ to users, as long as one dir is left on any branch aufs can show the -+ dir to users. In this case, the branch can be removed from aufs. -+ Otherwise aufs rejects deleting the branch. -+ -+ If any file on the deleting branch is opened by aufs, then aufs -+ rejects deleting. -+ -+ -+Modify the Permission of a Branch -+---------------------------------------------------------------------- -+o Re-initialize or remove the xino file and whiteout bases if necessary. -+ See struct.txt. -+ -+o rw --> ro: Confirm the modifying branch is not busy -+ Aufs rejects the request if any of these conditions are true. -+ - a file on the branch is mmap-ed. -+ - a regular file on the branch is opened for write and there is no -+ same named entry on the upper branch. -diff -Nurp linux-5.6.3/Documentation/filesystems/aufs/design/05wbr_policy.txt linux-5.6.3-aufs/Documentation/filesystems/aufs/design/05wbr_policy.txt ---- linux-5.6.3/Documentation/filesystems/aufs/design/05wbr_policy.txt 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/Documentation/filesystems/aufs/design/05wbr_policy.txt 2020-04-10 12:40:52.185049175 +0300 -@@ -0,0 +1,51 @@ -+ -+# Copyright (C) 2005-2020 Junjiro R. Okajima -+ -+Policies to Select One among Multiple Writable Branches -+---------------------------------------------------------------------- -+When the number of writable branch is more than one, aufs has to decide -+the target branch for file creation or copy-up. By default, the highest -+writable branch which has the parent (or ancestor) dir of the target -+file is chosen (top-down-parent policy). -+By user's request, aufs implements some other policies to select the -+writable branch, for file creation several policies, round-robin, -+most-free-space, and other policies. For copy-up, top-down-parent, -+bottom-up-parent, bottom-up and others. -+ -+As expected, the round-robin policy selects the branch in circular. When -+you have two writable branches and creates 10 new files, 5 files will be -+created for each branch. mkdir(2) systemcall is an exception. When you -+create 10 new directories, all will be created on the same branch. -+And the most-free-space policy selects the one which has most free -+space among the writable branches. The amount of free space will be -+checked by aufs internally, and users can specify its time interval. -+ -+The policies for copy-up is more simple, -+top-down-parent is equivalent to the same named on in create policy, -+bottom-up-parent selects the writable branch where the parent dir -+exists and the nearest upper one from the copyup-source, -+bottom-up selects the nearest upper writable branch from the -+copyup-source, regardless the existence of the parent dir. -+ -+There are some rules or exceptions to apply these policies. -+- If there is a readonly branch above the policy-selected branch and -+ the parent dir is marked as opaque (a variation of whiteout), or the -+ target (creating) file is whiteout-ed on the upper readonly branch, -+ then the result of the policy is ignored and the target file will be -+ created on the nearest upper writable branch than the readonly branch. -+- If there is a writable branch above the policy-selected branch and -+ the parent dir is marked as opaque or the target file is whiteouted -+ on the branch, then the result of the policy is ignored and the target -+ file will be created on the highest one among the upper writable -+ branches who has diropq or whiteout. In case of whiteout, aufs removes -+ it as usual. -+- link(2) and rename(2) systemcalls are exceptions in every policy. -+ They try selecting the branch where the source exists as possible -+ since copyup a large file will take long time. If it can't be, -+ ie. the branch where the source exists is readonly, then they will -+ follow the copyup policy. -+- There is an exception for rename(2) when the target exists. -+ If the rename target exists, aufs compares the index of the branches -+ where the source and the target exists and selects the higher -+ one. If the selected branch is readonly, then aufs follows the -+ copyup policy. -diff -Nurp linux-5.6.3/Documentation/filesystems/aufs/design/06dirren.dot linux-5.6.3-aufs/Documentation/filesystems/aufs/design/06dirren.dot ---- linux-5.6.3/Documentation/filesystems/aufs/design/06dirren.dot 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/Documentation/filesystems/aufs/design/06dirren.dot 2020-04-10 12:40:52.185049175 +0300 -@@ -0,0 +1,31 @@ -+ -+// to view this graph, run dot(1) command in GRAPHVIZ. -+ -+digraph G { -+node [shape=box]; -+whinfo [label="detailed info file\n(lower_brid_root-hinum, h_inum, namelen, old name)"]; -+ -+node [shape=oval]; -+ -+aufs_rename -> whinfo [label="store/remove"]; -+ -+node [shape=oval]; -+inode_list [label="h_inum list in branch\ncache"]; -+ -+node [shape=box]; -+whinode [label="h_inum list file"]; -+ -+node [shape=oval]; -+brmgmt [label="br_add/del/mod/umount"]; -+ -+brmgmt -> inode_list [label="create/remove"]; -+brmgmt -> whinode [label="load/store"]; -+ -+inode_list -> whinode [style=dashed,dir=both]; -+ -+aufs_rename -> inode_list [label="add/del"]; -+ -+aufs_lookup -> inode_list [label="search"]; -+ -+aufs_lookup -> whinfo [label="load/remove"]; -+} -diff -Nurp linux-5.6.3/Documentation/filesystems/aufs/design/06dirren.txt linux-5.6.3-aufs/Documentation/filesystems/aufs/design/06dirren.txt ---- linux-5.6.3/Documentation/filesystems/aufs/design/06dirren.txt 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/Documentation/filesystems/aufs/design/06dirren.txt 2020-04-10 12:40:52.185049175 +0300 -@@ -0,0 +1,89 @@ -+ -+# Copyright (C) 2017-2020 Junjiro R. Okajima -+ -+Special handling for renaming a directory (DIRREN) -+---------------------------------------------------------------------- -+First, let's assume we have a simple usecase. -+ -+- /u = /rw + /ro -+- /rw/dirA exists -+- /ro/dirA and /ro/dirA/file exist too -+- there is no dirB on both branches -+- a user issues rename("dirA", "dirB") -+ -+Now, what should aufs behave against this rename(2)? -+There are a few possible cases. -+ -+A. returns EROFS. -+ since dirA exists on a readonly branch which cannot be renamed. -+B. returns EXDEV. -+ it is possible to copy-up dirA (only the dir itself), but the child -+ entries ("file" in this case) should not be. it must be a bad -+ approach to copy-up recursively. -+C. returns a success. -+ even the branch /ro is readonly, aufs tries renaming it. Obviously it -+ is a violation of aufs' policy. -+D. construct an extra information which indicates that /ro/dirA should -+ be handled as the name of dirB. -+ overlayfs has a similar feature called REDIRECT. -+ -+Until now, aufs implements the case B only which returns EXDEV, and -+expects the userspace application behaves like mv(1) which tries -+issueing rename(2) recursively. -+ -+A new aufs feature called DIRREN is introduced which implements the case -+D. There are several "extra information" added. -+ -+1. detailed info per renamed directory -+ path: /rw/dirB/$AUFS_WH_DR_INFO_PFX. -+2. the inode-number list of directories on a branch -+ path: /rw/dirB/$AUFS_WH_DR_BRHINO -+ -+The filename of "detailed info per directory" represents the lower -+branch, and its format is -+- a type of the branch id -+ one of these. -+ + uuid (not implemented yet) -+ + fsid -+ + dev -+- the inode-number of the branch root dir -+ -+And it contains these info in a single regular file. -+- magic number -+- branch's inode-number of the logically renamed dir -+- the name of the before-renamed dir -+ -+The "detailed info per directory" file is created in aufs rename(2), and -+loaded in any lookup. -+The info is considered in lookup for the matching case only. Here -+"matching" means that the root of branch (in the info filename) is same -+to the current looking-up branch. After looking-up the before-renamed -+name, the inode-number is compared. And the matched dentry is used. -+ -+The "inode-number list of directories" is a regular file which contains -+simply the inode-numbers on the branch. The file is created or updated -+in removing the branch, and loaded in adding the branch. Its lifetime is -+equal to the branch. -+The list is refered in lookup, and when the current target inode is -+found in the list, the aufs tries loading the "detailed info per -+directory" and get the changed and valid name of the dir. -+ -+Theoretically these "extra informaiton" may be able to be put into XATTR -+in the dir inode. But aufs doesn't choose this way because -+1. XATTR may not be supported by the branch (or its configuration) -+2. XATTR may have its size limit. -+3. XATTR may be less easy to convert than a regular file, when the -+ format of the info is changed in the future. -+At the same time, I agree that the regular file approach is much slower -+than XATTR approach. So, in the future, aufs may take the XATTR or other -+better approach. -+ -+This DIRREN feature is enabled by aufs configuration, and is activated -+by a new mount option. -+ -+For the more complicated case, there is a work with UDBA option, which -+is to dected the direct access to the branches (by-passing aufs) and to -+maintain the cashes in aufs. Since a single cached aufs dentry may -+contains two names, before- and after-rename, the name comparision in -+UDBA handler may not work correctly. In this case, the behaviour will be -+equivalen to udba=reval case. -diff -Nurp linux-5.6.3/Documentation/filesystems/aufs/design/06fhsm.txt linux-5.6.3-aufs/Documentation/filesystems/aufs/design/06fhsm.txt ---- linux-5.6.3/Documentation/filesystems/aufs/design/06fhsm.txt 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/Documentation/filesystems/aufs/design/06fhsm.txt 2020-04-10 12:40:52.185049175 +0300 -@@ -0,0 +1,105 @@ -+ -+# Copyright (C) 2011-2020 Junjiro R. Okajima -+ -+File-based Hierarchical Storage Management (FHSM) -+---------------------------------------------------------------------- -+Hierarchical Storage Management (or HSM) is a well-known feature in the -+storage world. Aufs provides this feature as file-based with multiple -+writable branches, based upon the principle of "Colder, the Lower". -+Here the word "colder" means that the less used files, and "lower" means -+that the position in the order of the stacked branches vertically. -+These multiple writable branches are prioritized, ie. the topmost one -+should be the fastest drive and be used heavily. -+ -+o Characters in aufs FHSM story -+- aufs itself and a new branch attribute. -+- a new ioctl interface to move-down and to establish a connection with -+ the daemon ("move-down" is a converse of "copy-up"). -+- userspace tool and daemon. -+ -+The userspace daemon establishes a connection with aufs and waits for -+the notification. The notified information is very similar to struct -+statfs containing the number of consumed blocks and inodes. -+When the consumed blocks/inodes of a branch exceeds the user-specified -+upper watermark, the daemon activates its move-down process until the -+consumed blocks/inodes reaches the user-specified lower watermark. -+ -+The actual move-down is done by aufs based upon the request from -+user-space since we need to maintain the inode number and the internal -+pointer arrays in aufs. -+ -+Currently aufs FHSM handles the regular files only. Additionally they -+must not be hard-linked nor pseudo-linked. -+ -+ -+o Cowork of aufs and the user-space daemon -+ During the userspace daemon established the connection, aufs sends a -+ small notification to it whenever aufs writes something into the -+ writable branch. But it may cost high since aufs issues statfs(2) -+ internally. So user can specify a new option to cache the -+ info. Actually the notification is controlled by these factors. -+ + the specified cache time. -+ + classified as "force" by aufs internally. -+ Until the specified time expires, aufs doesn't send the info -+ except the forced cases. When aufs decide forcing, the info is always -+ notified to userspace. -+ For example, the number of free inodes is generally large enough and -+ the shortage of it happens rarely. So aufs doesn't force the -+ notification when creating a new file, directory and others. This is -+ the typical case which aufs doesn't force. -+ When aufs writes the actual filedata and the files consumes any of new -+ blocks, the aufs forces notifying. -+ -+ -+o Interfaces in aufs -+- New branch attribute. -+ + fhsm -+ Specifies that the branch is managed by FHSM feature. In other word, -+ participant in the FHSM. -+ When nofhsm is set to the branch, it will not be the source/target -+ branch of the move-down operation. This attribute is set -+ independently from coo and moo attributes, and if you want full -+ FHSM, you should specify them as well. -+- New mount option. -+ + fhsm_sec -+ Specifies a second to suppress many less important info to be -+ notified. -+- New ioctl. -+ + AUFS_CTL_FHSM_FD -+ create a new file descriptor which userspace can read the notification -+ (a subset of struct statfs) from aufs. -+- Module parameter 'brs' -+ It has to be set to 1. Otherwise the new mount option 'fhsm' will not -+ be set. -+- mount helpers /sbin/mount.aufs and /sbin/umount.aufs -+ When there are two or more branches with fhsm attributes, -+ /sbin/mount.aufs invokes the user-space daemon and /sbin/umount.aufs -+ terminates it. As a result of remounting and branch-manipulation, the -+ number of branches with fhsm attribute can be one. In this case, -+ /sbin/mount.aufs will terminate the user-space daemon. -+ -+ -+Finally the operation is done as these steps in kernel-space. -+- make sure that, -+ + no one else is using the file. -+ + the file is not hard-linked. -+ + the file is not pseudo-linked. -+ + the file is a regular file. -+ + the parent dir is not opaqued. -+- find the target writable branch. -+- make sure the file is not whiteout-ed by the upper (than the target) -+ branch. -+- make the parent dir on the target branch. -+- mutex lock the inode on the branch. -+- unlink the whiteout on the target branch (if exists). -+- lookup and create the whiteout-ed temporary name on the target branch. -+- copy the file as the whiteout-ed temporary name on the target branch. -+- rename the whiteout-ed temporary name to the original name. -+- unlink the file on the source branch. -+- maintain the internal pointer array and the external inode number -+ table (XINO). -+- maintain the timestamps and other attributes of the parent dir and the -+ file. -+ -+And of course, in every step, an error may happen. So the operation -+should restore the original file state after an error happens. -diff -Nurp linux-5.6.3/Documentation/filesystems/aufs/design/06mmap.txt linux-5.6.3-aufs/Documentation/filesystems/aufs/design/06mmap.txt ---- linux-5.6.3/Documentation/filesystems/aufs/design/06mmap.txt 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/Documentation/filesystems/aufs/design/06mmap.txt 2020-04-10 12:40:52.185049175 +0300 -@@ -0,0 +1,59 @@ -+ -+# Copyright (C) 2005-2020 Junjiro R. Okajima -+ -+mmap(2) -- File Memory Mapping -+---------------------------------------------------------------------- -+In aufs, the file-mapped pages are handled by a branch fs directly, no -+interaction with aufs. It means aufs_mmap() calls the branch fs's -+->mmap(). -+This approach is simple and good, but there is one problem. -+Under /proc, several entries show the mmapped files by its path (with -+device and inode number), and the printed path will be the path on the -+branch fs's instead of virtual aufs's. -+This is not a problem in most cases, but some utilities lsof(1) (and its -+user) may expect the path on aufs. -+ -+To address this issue, aufs adds a new member called vm_prfile in struct -+vm_area_struct (and struct vm_region). The original vm_file points to -+the file on the branch fs in order to handle everything correctly as -+usual. The new vm_prfile points to a virtual file in aufs, and the -+show-functions in procfs refers to vm_prfile if it is set. -+Also we need to maintain several other places where touching vm_file -+such like -+- fork()/clone() copies vma and the reference count of vm_file is -+ incremented. -+- merging vma maintains the ref count too. -+ -+This is not a good approach. It just fakes the printed path. But it -+leaves all behaviour around f_mapping unchanged. This is surely an -+advantage. -+Actually aufs had adopted another complicated approach which calls -+generic_file_mmap() and handles struct vm_operations_struct. In this -+approach, aufs met a hard problem and I could not solve it without -+switching the approach. -+ -+There may be one more another approach which is -+- bind-mount the branch-root onto the aufs-root internally -+- grab the new vfsmount (ie. struct mount) -+- lazy-umount the branch-root internally -+- in open(2) the aufs-file, open the branch-file with the hidden -+ vfsmount (instead of the original branch's vfsmount) -+- ideally this "bind-mount and lazy-umount" should be done atomically, -+ but it may be possible from userspace by the mount helper. -+ -+Adding the internal hidden vfsmount and using it in opening a file, the -+file path under /proc will be printed correctly. This approach looks -+smarter, but is not possible I am afraid. -+- aufs-root may be bind-mount later. when it happens, another hidden -+ vfsmount will be required. -+- it is hard to get the chance to bind-mount and lazy-umount -+ + in kernel-space, FS can have vfsmount in open(2) via -+ file->f_path, and aufs can know its vfsmount. But several locks are -+ already acquired, and if aufs tries to bind-mount and lazy-umount -+ here, then it may cause a deadlock. -+ + in user-space, bind-mount doesn't invoke the mount helper. -+- since /proc shows dev and ino, aufs has to give vma these info. it -+ means a new member vm_prinode will be necessary. this is essentially -+ equivalent to vm_prfile described above. -+ -+I have to give up this "looks-smater" approach. -diff -Nurp linux-5.6.3/Documentation/filesystems/aufs/design/06xattr.txt linux-5.6.3-aufs/Documentation/filesystems/aufs/design/06xattr.txt ---- linux-5.6.3/Documentation/filesystems/aufs/design/06xattr.txt 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/Documentation/filesystems/aufs/design/06xattr.txt 2020-04-10 12:40:52.185049175 +0300 -@@ -0,0 +1,81 @@ -+ -+# Copyright (C) 2014-2020 Junjiro R. Okajima -+ -+Listing XATTR/EA and getting the value -+---------------------------------------------------------------------- -+For the inode standard attributes (owner, group, timestamps, etc.), aufs -+shows the values from the topmost existing file. This behaviour is good -+for the non-dir entries since the bahaviour exactly matches the shown -+information. But for the directories, aufs considers all the same named -+entries on the lower branches. Which means, if one of the lower entry -+rejects readdir call, then aufs returns an error even if the topmost -+entry allows it. This behaviour is necessary to respect the branch fs's -+security, but can make users confused since the user-visible standard -+attributes don't match the behaviour. -+To address this issue, aufs has a mount option called dirperm1 which -+checks the permission for the topmost entry only, and ignores the lower -+entry's permission. -+ -+A similar issue can happen around XATTR. -+getxattr(2) and listxattr(2) families behave as if dirperm1 option is -+always set. Otherwise these very unpleasant situation would happen. -+- listxattr(2) may return the duplicated entries. -+- users may not be able to remove or reset the XATTR forever, -+ -+ -+XATTR/EA support in the internal (copy,move)-(up,down) -+---------------------------------------------------------------------- -+Generally the extended attributes of inode are categorized as these. -+- "security" for LSM and capability. -+- "system" for posix ACL, 'acl' mount option is required for the branch -+ fs generally. -+- "trusted" for userspace, CAP_SYS_ADMIN is required. -+- "user" for userspace, 'user_xattr' mount option is required for the -+ branch fs generally. -+ -+Moreover there are some other categories. Aufs handles these rather -+unpopular categories as the ordinary ones, ie. there is no special -+condition nor exception. -+ -+In copy-up, the support for XATTR on the dst branch may differ from the -+src branch. In this case, the copy-up operation will get an error and -+the original user operation which triggered the copy-up will fail. It -+can happen that even all copy-up will fail. -+When both of src and dst branches support XATTR and if an error occurs -+during copying XATTR, then the copy-up should fail obviously. That is a -+good reason and aufs should return an error to userspace. But when only -+the src branch support that XATTR, aufs should not return an error. -+For example, the src branch supports ACL but the dst branch doesn't -+because the dst branch may natively un-support it or temporary -+un-support it due to "noacl" mount option. Of course, the dst branch fs -+may NOT return an error even if the XATTR is not supported. It is -+totally up to the branch fs. -+ -+Anyway when the aufs internal copy-up gets an error from the dst branch -+fs, then aufs tries removing the just copied entry and returns the error -+to the userspace. The worst case of this situation will be all copy-up -+will fail. -+ -+For the copy-up operation, there two basic approaches. -+- copy the specified XATTR only (by category above), and return the -+ error unconditionally if it happens. -+- copy all XATTR, and ignore the error on the specified category only. -+ -+In order to support XATTR and to implement the correct behaviour, aufs -+chooses the latter approach and introduces some new branch attributes, -+"icexsec", "icexsys", "icextr", "icexusr", and "icexoth". -+They correspond to the XATTR namespaces (see above). Additionally, to be -+convenient, "icex" is also provided which means all "icex*" attributes -+are set (here the word "icex" stands for "ignore copy-error on XATTR"). -+ -+The meaning of these attributes is to ignore the error from setting -+XATTR on that branch. -+Note that aufs tries copying all XATTR unconditionally, and ignores the -+error from the dst branch according to the specified attributes. -+ -+Some XATTR may have its default value. The default value may come from -+the parent dir or the environment. If the default value is set at the -+file creating-time, it will be overwritten by copy-up. -+Some contradiction may happen I am afraid. -+Do we need another attribute to stop copying XATTR? I am unsure. For -+now, aufs implements the branch attributes to ignore the error. -diff -Nurp linux-5.6.3/Documentation/filesystems/aufs/design/07export.txt linux-5.6.3-aufs/Documentation/filesystems/aufs/design/07export.txt ---- linux-5.6.3/Documentation/filesystems/aufs/design/07export.txt 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/Documentation/filesystems/aufs/design/07export.txt 2020-04-10 12:40:52.185049175 +0300 -@@ -0,0 +1,45 @@ -+ -+# Copyright (C) 2005-2020 Junjiro R. Okajima -+ -+Export Aufs via NFS -+---------------------------------------------------------------------- -+Here is an approach. -+- like xino/xib, add a new file 'xigen' which stores aufs inode -+ generation. -+- iget_locked(): initialize aufs inode generation for a new inode, and -+ store it in xigen file. -+- destroy_inode(): increment aufs inode generation and store it in xigen -+ file. it is necessary even if it is not unlinked, because any data of -+ inode may be changed by UDBA. -+- encode_fh(): for a root dir, simply return FILEID_ROOT. otherwise -+ build file handle by -+ + branch id (4 bytes) -+ + superblock generation (4 bytes) -+ + inode number (4 or 8 bytes) -+ + parent dir inode number (4 or 8 bytes) -+ + inode generation (4 bytes)) -+ + return value of exportfs_encode_fh() for the parent on a branch (4 -+ bytes) -+ + file handle for a branch (by exportfs_encode_fh()) -+- fh_to_dentry(): -+ + find the index of a branch from its id in handle, and check it is -+ still exist in aufs. -+ + 1st level: get the inode number from handle and search it in cache. -+ + 2nd level: if not found in cache, get the parent inode number from -+ the handle and search it in cache. and then open the found parent -+ dir, find the matching inode number by vfs_readdir() and get its -+ name, and call lookup_one_len() for the target dentry. -+ + 3rd level: if the parent dir is not cached, call -+ exportfs_decode_fh() for a branch and get the parent on a branch, -+ build a pathname of it, convert it a pathname in aufs, call -+ path_lookup(). now aufs gets a parent dir dentry, then handle it as -+ the 2nd level. -+ + to open the dir, aufs needs struct vfsmount. aufs keeps vfsmount -+ for every branch, but not itself. to get this, (currently) aufs -+ searches in current->nsproxy->mnt_ns list. it may not be a good -+ idea, but I didn't get other approach. -+ + test the generation of the gotten inode. -+- every inode operation: they may get EBUSY due to UDBA. in this case, -+ convert it into ESTALE for NFSD. -+- readdir(): call lockdep_on/off() because filldir in NFSD calls -+ lookup_one_len(), vfs_getattr(), encode_fh() and others. -diff -Nurp linux-5.6.3/Documentation/filesystems/aufs/design/08shwh.txt linux-5.6.3-aufs/Documentation/filesystems/aufs/design/08shwh.txt ---- linux-5.6.3/Documentation/filesystems/aufs/design/08shwh.txt 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/Documentation/filesystems/aufs/design/08shwh.txt 2020-04-10 12:40:52.185049175 +0300 -@@ -0,0 +1,39 @@ -+ -+# Copyright (C) 2005-2020 Junjiro R. Okajima -+ -+Show Whiteout Mode (shwh) -+---------------------------------------------------------------------- -+Generally aufs hides the name of whiteouts. But in some cases, to show -+them is very useful for users. For instance, creating a new middle layer -+(branch) by merging existing layers. -+ -+(borrowing aufs1 HOW-TO from a user, Michael Towers) -+When you have three branches, -+- Bottom: 'system', squashfs (underlying base system), read-only -+- Middle: 'mods', squashfs, read-only -+- Top: 'overlay', ram (tmpfs), read-write -+ -+The top layer is loaded at boot time and saved at shutdown, to preserve -+the changes made to the system during the session. -+When larger changes have been made, or smaller changes have accumulated, -+the size of the saved top layer data grows. At this point, it would be -+nice to be able to merge the two overlay branches ('mods' and 'overlay') -+and rewrite the 'mods' squashfs, clearing the top layer and thus -+restoring save and load speed. -+ -+This merging is simplified by the use of another aufs mount, of just the -+two overlay branches using the 'shwh' option. -+# mount -t aufs -o ro,shwh,br:/livesys/overlay=ro+wh:/livesys/mods=rr+wh \ -+ aufs /livesys/merge_union -+ -+A merged view of these two branches is then available at -+/livesys/merge_union, and the new feature is that the whiteouts are -+visible! -+Note that in 'shwh' mode the aufs mount must be 'ro', which will disable -+writing to all branches. Also the default mode for all branches is 'ro'. -+It is now possible to save the combined contents of the two overlay -+branches to a new squashfs, e.g.: -+# mksquashfs /livesys/merge_union /path/to/newmods.squash -+ -+This new squashfs archive can be stored on the boot device and the -+initramfs will use it to replace the old one at the next boot. -diff -Nurp linux-5.6.3/Documentation/filesystems/aufs/design/10dynop.txt linux-5.6.3-aufs/Documentation/filesystems/aufs/design/10dynop.txt ---- linux-5.6.3/Documentation/filesystems/aufs/design/10dynop.txt 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/Documentation/filesystems/aufs/design/10dynop.txt 2020-04-10 12:40:52.185049175 +0300 -@@ -0,0 +1,34 @@ -+ -+# Copyright (C) 2010-2020 Junjiro R. Okajima -+ -+Dynamically customizable FS operations -+---------------------------------------------------------------------- -+Generally FS operations (struct inode_operations, struct -+address_space_operations, struct file_operations, etc.) are defined as -+"static const", but it never means that FS have only one set of -+operation. Some FS have multiple sets of them. For instance, ext2 has -+three sets, one for XIP, for NOBH, and for normal. -+Since aufs overrides and redirects these operations, sometimes aufs has -+to change its behaviour according to the branch FS type. More importantly -+VFS acts differently if a function (member in the struct) is set or -+not. It means aufs should have several sets of operations and select one -+among them according to the branch FS definition. -+ -+In order to solve this problem and not to affect the behaviour of VFS, -+aufs defines these operations dynamically. For instance, aufs defines -+dummy direct_IO function for struct address_space_operations, but it may -+not be set to the address_space_operations actually. When the branch FS -+doesn't have it, aufs doesn't set it to its address_space_operations -+while the function definition itself is still alive. So the behaviour -+itself will not change, and it will return an error when direct_IO is -+not set. -+ -+The lifetime of these dynamically generated operation object is -+maintained by aufs branch object. When the branch is removed from aufs, -+the reference counter of the object is decremented. When it reaches -+zero, the dynamically generated operation object will be freed. -+ -+This approach is designed to support AIO (io_submit), Direct I/O and -+XIP (DAX) mainly. -+Currently this approach is applied to address_space_operations for -+regular files only. -diff -Nurp linux-5.6.3/Documentation/filesystems/aufs/README linux-5.6.3-aufs/Documentation/filesystems/aufs/README ---- linux-5.6.3/Documentation/filesystems/aufs/README 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/Documentation/filesystems/aufs/README 2020-04-10 12:40:52.184049128 +0300 -@@ -0,0 +1,401 @@ -+ -+Aufs5 -- advanced multi layered unification filesystem version 5.x -+http://aufs.sf.net -+Junjiro R. Okajima -+ -+ -+0. Introduction -+---------------------------------------- -+In the early days, aufs was entirely re-designed and re-implemented -+Unionfs Version 1.x series. Adding many original ideas, approaches, -+improvements and implementations, it became totally different from -+Unionfs while keeping the basic features. -+Later, Unionfs Version 2.x series began taking some of the same -+approaches to aufs1's. -+Unionfs was being developed by Professor Erez Zadok at Stony Brook -+University and his team. -+ -+Aufs5 supports linux-v5.0 and later, If you want older kernel version -+support, -+- for linux-v4.x series, try aufs4-linux.git or aufs4-standalone.git -+- for linux-v3.x series, try aufs3-linux.git or aufs3-standalone.git -+- for linux-v2.6.16 and later, try aufs2-2.6.git, aufs2-standalone.git -+ or aufs1 from CVS on SourceForge. -+ -+Note: it becomes clear that "Aufs was rejected. Let's give it up." -+ According to Christoph Hellwig, linux rejects all union-type -+ filesystems but UnionMount. -+ -+ -+PS. Al Viro seems have a plan to merge aufs as well as overlayfs and -+ UnionMount, and he pointed out an issue around a directory mutex -+ lock and aufs addressed it. But it is still unsure whether aufs will -+ be merged (or any other union solution). -+ -+ -+ -+1. Features -+---------------------------------------- -+- unite several directories into a single virtual filesystem. The member -+ directory is called as a branch. -+- you can specify the permission flags to the branch, which are 'readonly', -+ 'readwrite' and 'whiteout-able.' -+- by upper writable branch, internal copyup and whiteout, files/dirs on -+ readonly branch are modifiable logically. -+- dynamic branch manipulation, add, del. -+- etc... -+ -+Also there are many enhancements in aufs, such as: -+- test only the highest one for the directory permission (dirperm1) -+- copyup on open (coo=) -+- 'move' policy for copy-up between two writable branches, after -+ checking free space. -+- xattr, acl -+- readdir(3) in userspace. -+- keep inode number by external inode number table -+- keep the timestamps of file/dir in internal copyup operation -+- seekable directory, supporting NFS readdir. -+- whiteout is hardlinked in order to reduce the consumption of inodes -+ on branch -+- do not copyup, nor create a whiteout when it is unnecessary -+- revert a single systemcall when an error occurs in aufs -+- remount interface instead of ioctl -+- maintain /etc/mtab by an external command, /sbin/mount.aufs. -+- loopback mounted filesystem as a branch -+- kernel thread for removing the dir who has a plenty of whiteouts -+- support copyup sparse file (a file which has a 'hole' in it) -+- default permission flags for branches -+- selectable permission flags for ro branch, whether whiteout can -+ exist or not -+- export via NFS. -+- support /fs/aufs and /aufs. -+- support multiple writable branches, some policies to select one -+ among multiple writable branches. -+- a new semantics for link(2) and rename(2) to support multiple -+ writable branches. -+- no glibc changes are required. -+- pseudo hardlink (hardlink over branches) -+- allow a direct access manually to a file on branch, e.g. bypassing aufs. -+ including NFS or remote filesystem branch. -+- userspace wrapper for pathconf(3)/fpathconf(3) with _PC_LINK_MAX. -+- and more... -+ -+Currently these features are dropped temporary from aufs5. -+See design/08plan.txt in detail. -+- nested mount, i.e. aufs as readonly no-whiteout branch of another aufs -+ (robr) -+- statistics of aufs thread (/sys/fs/aufs/stat) -+ -+Features or just an idea in the future (see also design/*.txt), -+- reorder the branch index without del/re-add. -+- permanent xino files for NFSD -+- an option for refreshing the opened files after add/del branches -+- light version, without branch manipulation. (unnecessary?) -+- copyup in userspace -+- inotify in userspace -+- readv/writev -+ -+ -+2. Download -+---------------------------------------- -+There are three GIT trees for aufs5, aufs5-linux.git, -+aufs5-standalone.git, and aufs-util.git. Note that there is no "5" in -+"aufs-util.git." -+While the aufs-util is always necessary, you need either of aufs5-linux -+or aufs5-standalone. -+ -+The aufs5-linux tree includes the whole linux mainline GIT tree, -+git://git.kernel.org/.../torvalds/linux.git. -+And you cannot select CONFIG_AUFS_FS=m for this version, eg. you cannot -+build aufs5 as an external kernel module. -+Several extra patches are not included in this tree. Only -+aufs5-standalone tree contains them. They are described in the later -+section "Configuration and Compilation." -+ -+On the other hand, the aufs5-standalone tree has only aufs source files -+and necessary patches, and you can select CONFIG_AUFS_FS=m. -+But you need to apply all aufs patches manually. -+ -+You will find GIT branches whose name is in form of "aufs5.x" where "x" -+represents the linux kernel version, "linux-5.x". For instance, -+"aufs5.0" is for linux-5.0. For latest "linux-5.x-rcN", use -+"aufs5.x-rcN" branch. -+ -+o aufs5-linux tree -+$ git clone --reference /your/linux/git/tree \ -+ git://github.com/sfjro/aufs5-linux.git aufs5-linux.git -+- if you don't have linux GIT tree, then remove "--reference ..." -+$ cd aufs5-linux.git -+$ git checkout origin/aufs5.0 -+ -+Or You may want to directly git-pull aufs into your linux GIT tree, and -+leave the patch-work to GIT. -+$ cd /your/linux/git/tree -+$ git remote add aufs5 git://github.com/sfjro/aufs5-linux.git -+$ git fetch aufs5 -+$ git checkout -b my5.0 v5.0 -+$ (add your local change...) -+$ git pull aufs5 aufs5.0 -+- now you have v5.0 + your_changes + aufs5.0 in you my5.0 branch. -+- you may need to solve some conflicts between your_changes and -+ aufs5.0. in this case, git-rerere is recommended so that you can -+ solve the similar conflicts automatically when you upgrade to 5.1 or -+ later in the future. -+ -+o aufs5-standalone tree -+$ git clone git://github.com/sfjro/aufs5-standalone.git aufs5-standalone.git -+$ cd aufs5-standalone.git -+$ git checkout origin/aufs5.0 -+ -+o aufs-util tree -+$ git clone git://git.code.sf.net/p/aufs/aufs-util aufs-util.git -+- note that the public aufs-util.git is on SourceForge instead of -+ GitHUB. -+$ cd aufs-util.git -+$ git checkout origin/aufs5.0 -+ -+Note: The 5.x-rcN branch is to be used with `rc' kernel versions ONLY. -+The minor version number, 'x' in '5.x', of aufs may not always -+follow the minor version number of the kernel. -+Because changes in the kernel that cause the use of a new -+minor version number do not always require changes to aufs-util. -+ -+Since aufs-util has its own minor version number, you may not be -+able to find a GIT branch in aufs-util for your kernel's -+exact minor version number. -+In this case, you should git-checkout the branch for the -+nearest lower number. -+ -+For (an unreleased) example: -+If you are using "linux-5.10" and the "aufs5.10" branch -+does not exist in aufs-util repository, then "aufs5.9", "aufs5.8" -+or something numerically smaller is the branch for your kernel. -+ -+Also you can view all branches by -+ $ git branch -a -+ -+ -+3. Configuration and Compilation -+---------------------------------------- -+Make sure you have git-checkout'ed the correct branch. -+ -+For aufs5-linux tree, -+- enable CONFIG_AUFS_FS. -+- set other aufs configurations if necessary. -+ -+For aufs5-standalone tree, -+There are several ways to build. -+ -+1. -+- apply ./aufs5-kbuild.patch to your kernel source files. -+- apply ./aufs5-base.patch too. -+- apply ./aufs5-mmap.patch too. -+- apply ./aufs5-standalone.patch too, if you have a plan to set -+ CONFIG_AUFS_FS=m. otherwise you don't need ./aufs5-standalone.patch. -+- copy ./{Documentation,fs,include/uapi/linux/aufs_type.h} files to your -+ kernel source tree. Never copy $PWD/include/uapi/linux/Kbuild. -+- enable CONFIG_AUFS_FS, you can select either -+ =m or =y. -+- and build your kernel as usual. -+- install the built kernel. -+- install the header files too by "make headers_install" to the -+ directory where you specify. By default, it is $PWD/usr. -+ "make help" shows a brief note for headers_install. -+- and reboot your system. -+ -+2. -+- module only (CONFIG_AUFS_FS=m). -+- apply ./aufs5-base.patch to your kernel source files. -+- apply ./aufs5-mmap.patch too. -+- apply ./aufs5-standalone.patch too. -+- build your kernel, don't forget "make headers_install", and reboot. -+- edit ./config.mk and set other aufs configurations if necessary. -+ Note: You should read $PWD/fs/aufs/Kconfig carefully which describes -+ every aufs configurations. -+- build the module by simple "make". -+- you can specify ${KDIR} make variable which points to your kernel -+ source tree. -+- install the files -+ + run "make install" to install the aufs module, or copy the built -+ $PWD/aufs.ko to /lib/modules/... and run depmod -a (or reboot simply). -+ + run "make install_headers" (instead of headers_install) to install -+ the modified aufs header file (you can specify DESTDIR which is -+ available in aufs standalone version's Makefile only), or copy -+ $PWD/usr/include/linux/aufs_type.h to /usr/include/linux or wherever -+ you like manually. By default, the target directory is $PWD/usr. -+- no need to apply aufs5-kbuild.patch, nor copying source files to your -+ kernel source tree. -+ -+Note: The header file aufs_type.h is necessary to build aufs-util -+ as well as "make headers_install" in the kernel source tree. -+ headers_install is subject to be forgotten, but it is essentially -+ necessary, not only for building aufs-util. -+ You may not meet problems without headers_install in some older -+ version though. -+ -+And then, -+- read README in aufs-util, build and install it -+- note that your distribution may contain an obsoleted version of -+ aufs_type.h in /usr/include/linux or something. When you build aufs -+ utilities, make sure that your compiler refers the correct aufs header -+ file which is built by "make headers_install." -+- if you want to use readdir(3) in userspace or pathconf(3) wrapper, -+ then run "make install_ulib" too. And refer to the aufs manual in -+ detail. -+ -+There several other patches in aufs5-standalone.git. They are all -+optional. When you meet some problems, they will help you. -+- aufs5-loopback.patch -+ Supports a nested loopback mount in a branch-fs. This patch is -+ unnecessary until aufs produces a message like "you may want to try -+ another patch for loopback file". -+- proc_mounts.patch -+ When there are many mountpoints and many mount(2)/umount(2) are -+ running, then /proc/mounts may not show the all mountpoints. This -+ patch makes /proc/mounts always show the full mountpoints list. -+ If you don't want to apply this patch and meet such problem, then you -+ need to increase the value of 'ProcMounts_Times' make-variable in -+ aufs-util.git as a second best solution. -+- vfs-ino.patch -+ Modifies a system global kernel internal function get_next_ino() in -+ order to stop assigning 0 for an inode-number. Not directly related to -+ aufs, but recommended generally. -+- tmpfs-idr.patch -+ Keeps the tmpfs inode number as the lowest value. Effective to reduce -+ the size of aufs XINO files for tmpfs branch. Also it prevents the -+ duplication of inode number, which is important for backup tools and -+ other utilities. When you find aufs XINO files for tmpfs branch -+ growing too much, try this patch. -+- lockdep-debug.patch -+ Because aufs is not only an ordinary filesystem (callee of VFS), but -+ also a caller of VFS functions for branch filesystems, subclassing of -+ the internal locks for LOCKDEP is necessary. LOCKDEP is a debugging -+ feature of linux kernel. If you enable CONFIG_LOCKDEP, then you will -+ need to apply this debug patch to expand several constant values. -+ If you don't know what LOCKDEP is, then you don't have apply this -+ patch. -+ -+ -+4. Usage -+---------------------------------------- -+At first, make sure aufs-util are installed, and please read the aufs -+manual, aufs.5 in aufs-util.git tree. -+$ man -l aufs.5 -+ -+And then, -+$ mkdir /tmp/rw /tmp/aufs -+# mount -t aufs -o br=/tmp/rw:${HOME} none /tmp/aufs -+ -+Here is another example. The result is equivalent. -+# mount -t aufs -o br=/tmp/rw=rw:${HOME}=ro none /tmp/aufs -+ Or -+# mount -t aufs -o br:/tmp/rw none /tmp/aufs -+# mount -o remount,append:${HOME} /tmp/aufs -+ -+Then, you can see whole tree of your home dir through /tmp/aufs. If -+you modify a file under /tmp/aufs, the one on your home directory is -+not affected, instead the same named file will be newly created under -+/tmp/rw. And all of your modification to a file will be applied to -+the one under /tmp/rw. This is called the file based Copy on Write -+(COW) method. -+Aufs mount options are described in aufs.5. -+If you run chroot or something and make your aufs as a root directory, -+then you need to customize the shutdown script. See the aufs manual in -+detail. -+ -+Additionally, there are some sample usages of aufs which are a -+diskless system with network booting, and LiveCD over NFS. -+See sample dir in CVS tree on SourceForge. -+ -+ -+5. Contact -+---------------------------------------- -+When you have any problems or strange behaviour in aufs, please let me -+know with: -+- /proc/mounts (instead of the output of mount(8)) -+- /sys/module/aufs/* -+- /sys/fs/aufs/* (if you have them) -+- /debug/aufs/* (if you have them) -+- linux kernel version -+ if your kernel is not plain, for example modified by distributor, -+ the url where i can download its source is necessary too. -+- aufs version which was printed at loading the module or booting the -+ system, instead of the date you downloaded. -+- configuration (define/undefine CONFIG_AUFS_xxx) -+- kernel configuration or /proc/config.gz (if you have it) -+- LSM (linux security module, if you are using) -+- behaviour which you think to be incorrect -+- actual operation, reproducible one is better -+- mailto: aufs-users at lists.sourceforge.net -+ -+Usually, I don't watch the Public Areas(Bugs, Support Requests, Patches, -+and Feature Requests) on SourceForge. Please join and write to -+aufs-users ML. -+ -+ -+6. Acknowledgements -+---------------------------------------- -+Thanks to everyone who have tried and are using aufs, whoever -+have reported a bug or any feedback. -+ -+Especially donators: -+Tomas Matejicek(slax.org) made a donation (much more than once). -+ Since Apr 2010, Tomas M (the author of Slax and Linux Live -+ scripts) is making "doubling" donations. -+ Unfortunately I cannot list all of the donators, but I really -+ appreciate. -+ It ends Aug 2010, but the ordinary donation URL is still available. -+ -+Dai Itasaka made a donation (2007/8). -+Chuck Smith made a donation (2008/4, 10 and 12). -+Henk Schoneveld made a donation (2008/9). -+Chih-Wei Huang, ASUS, CTC donated Eee PC 4G (2008/10). -+Francois Dupoux made a donation (2008/11). -+Bruno Cesar Ribas and Luis Carlos Erpen de Bona, C3SL serves public -+ aufs2 GIT tree (2009/2). -+William Grant made a donation (2009/3). -+Patrick Lane made a donation (2009/4). -+The Mail Archive (mail-archive.com) made donations (2009/5). -+Nippy Networks (Ed Wildgoose) made a donation (2009/7). -+New Dream Network, LLC (www.dreamhost.com) made a donation (2009/11). -+Pavel Pronskiy made a donation (2011/2). -+Iridium and Inmarsat satellite phone retailer (www.mailasail.com), Nippy -+ Networks (Ed Wildgoose) made a donation for hardware (2011/3). -+Max Lekomcev (DOM-TV project) made a donation (2011/7, 12, 2012/3, 6 and -+11). -+Sam Liddicott made a donation (2011/9). -+Era Scarecrow made a donation (2013/4). -+Bor Ratajc made a donation (2013/4). -+Alessandro Gorreta made a donation (2013/4). -+POIRETTE Marc made a donation (2013/4). -+Alessandro Gorreta made a donation (2013/4). -+lauri kasvandik made a donation (2013/5). -+"pemasu from Finland" made a donation (2013/7). -+The Parted Magic Project made a donation (2013/9 and 11). -+Pavel Barta made a donation (2013/10). -+Nikolay Pertsev made a donation (2014/5). -+James B made a donation (2014/7 and 2015/7). -+Stefano Di Biase made a donation (2014/8). -+Daniel Epellei made a donation (2015/1). -+OmegaPhil made a donation (2016/1, 2018/4). -+Tomasz Szewczyk made a donation (2016/4). -+James Burry made a donation (2016/12). -+Carsten Rose made a donation (2018/9). -+Porteus Kiosk made a donation (2018/10). -+ -+Thank you very much. -+Donations are always, including future donations, very important and -+helpful for me to keep on developing aufs. -+ -+ -+7. -+---------------------------------------- -+If you are an experienced user, no explanation is needed. Aufs is -+just a linux filesystem. -+ -+ -+Enjoy! -+ -+# Local variables: ; -+# mode: text; -+# End: ; -diff -Nurp linux-5.6.3/drivers/block/loop.c linux-5.6.3-aufs/drivers/block/loop.c ---- linux-5.6.3/drivers/block/loop.c 2020-03-30 01:25:41.000000000 +0300 -+++ linux-5.6.3-aufs/drivers/block/loop.c 2020-04-10 12:40:52.187049268 +0300 -@@ -750,6 +750,24 @@ out_err: - return error; - } - -+/* -+ * for AUFS -+ * no get/put for file. -+ */ -+struct file *loop_backing_file(struct super_block *sb) -+{ -+ struct file *ret; -+ struct loop_device *l; -+ -+ ret = NULL; -+ if (MAJOR(sb->s_dev) == LOOP_MAJOR) { -+ l = sb->s_bdev->bd_disk->private_data; -+ ret = l->lo_backing_file; -+ } -+ return ret; -+} -+EXPORT_SYMBOL_GPL(loop_backing_file); -+ - /* loop sysfs attributes */ - - static ssize_t loop_attr_show(struct device *dev, char *page, -diff -Nurp linux-5.6.3/fs/aufs/aufs.h linux-5.6.3-aufs/fs/aufs/aufs.h ---- linux-5.6.3/fs/aufs/aufs.h 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/aufs.h 2020-04-10 12:40:52.187049268 +0300 -@@ -0,0 +1,49 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * all header files -+ */ -+ -+#ifndef __AUFS_H__ -+#define __AUFS_H__ -+ -+#ifdef __KERNEL__ -+ -+#define AuStub(type, name, body, ...) \ -+ static inline type name(__VA_ARGS__) { body; } -+ -+#define AuStubVoid(name, ...) \ -+ AuStub(void, name, , __VA_ARGS__) -+#define AuStubInt0(name, ...) \ -+ AuStub(int, name, return 0, __VA_ARGS__) -+ -+#include "debug.h" -+ -+#include "branch.h" -+#include "cpup.h" -+#include "dcsub.h" -+#include "dbgaufs.h" -+#include "dentry.h" -+#include "dir.h" -+#include "dirren.h" -+#include "dynop.h" -+#include "file.h" -+#include "fstype.h" -+#include "hbl.h" -+#include "inode.h" -+#include "lcnt.h" -+#include "loop.h" -+#include "module.h" -+#include "opts.h" -+#include "rwsem.h" -+#include "super.h" -+#include "sysaufs.h" -+#include "vfsub.h" -+#include "whout.h" -+#include "wkq.h" -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_H__ */ -diff -Nurp linux-5.6.3/fs/aufs/branch.c linux-5.6.3-aufs/fs/aufs/branch.c ---- linux-5.6.3/fs/aufs/branch.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/branch.c 2020-04-10 12:40:52.188049315 +0300 -@@ -0,0 +1,1415 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * branch management -+ */ -+ -+#include -+#include -+#include "aufs.h" -+ -+/* -+ * free a single branch -+ */ -+static void au_br_do_free(struct au_branch *br) -+{ -+ int i; -+ struct au_wbr *wbr; -+ struct au_dykey **key; -+ -+ au_hnotify_fin_br(br); -+ /* always, regardless the mount option */ -+ au_dr_hino_free(&br->br_dirren); -+ au_xino_put(br); -+ -+ AuLCntZero(au_lcnt_read(&br->br_nfiles, /*do_rev*/0)); -+ au_lcnt_fin(&br->br_nfiles, /*do_sync*/0); -+ AuLCntZero(au_lcnt_read(&br->br_count, /*do_rev*/0)); -+ au_lcnt_fin(&br->br_count, /*do_sync*/0); -+ -+ wbr = br->br_wbr; -+ if (wbr) { -+ for (i = 0; i < AuBrWh_Last; i++) -+ dput(wbr->wbr_wh[i]); -+ AuDebugOn(atomic_read(&wbr->wbr_wh_running)); -+ AuRwDestroy(&wbr->wbr_wh_rwsem); -+ } -+ -+ if (br->br_fhsm) { -+ au_br_fhsm_fin(br->br_fhsm); -+ au_kfree_try_rcu(br->br_fhsm); -+ } -+ -+ key = br->br_dykey; -+ for (i = 0; i < AuBrDynOp; i++, key++) -+ if (*key) -+ au_dy_put(*key); -+ else -+ break; -+ -+ /* recursive lock, s_umount of branch's */ -+ /* synchronize_rcu(); */ /* why? */ -+ lockdep_off(); -+ path_put(&br->br_path); -+ lockdep_on(); -+ au_kfree_rcu(wbr); -+ au_lcnt_wait_for_fin(&br->br_nfiles); -+ au_lcnt_wait_for_fin(&br->br_count); -+ /* I don't know why, but percpu_refcount requires this */ -+ /* synchronize_rcu(); */ -+ au_kfree_rcu(br); -+} -+ -+/* -+ * frees all branches -+ */ -+void au_br_free(struct au_sbinfo *sbinfo) -+{ -+ aufs_bindex_t bmax; -+ struct au_branch **br; -+ -+ AuRwMustWriteLock(&sbinfo->si_rwsem); -+ -+ bmax = sbinfo->si_bbot + 1; -+ br = sbinfo->si_branch; -+ while (bmax--) -+ au_br_do_free(*br++); -+} -+ -+/* -+ * find the index of a branch which is specified by @br_id. -+ */ -+int au_br_index(struct super_block *sb, aufs_bindex_t br_id) -+{ -+ aufs_bindex_t bindex, bbot; -+ -+ bbot = au_sbbot(sb); -+ for (bindex = 0; bindex <= bbot; bindex++) -+ if (au_sbr_id(sb, bindex) == br_id) -+ return bindex; -+ return -1; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * add a branch -+ */ -+ -+static int test_overlap(struct super_block *sb, struct dentry *h_adding, -+ struct dentry *h_root) -+{ -+ if (unlikely(h_adding == h_root -+ || au_test_loopback_overlap(sb, h_adding))) -+ return 1; -+ if (h_adding->d_sb != h_root->d_sb) -+ return 0; -+ return au_test_subdir(h_adding, h_root) -+ || au_test_subdir(h_root, h_adding); -+} -+ -+/* -+ * returns a newly allocated branch. @new_nbranch is a number of branches -+ * after adding a branch. -+ */ -+static struct au_branch *au_br_alloc(struct super_block *sb, int new_nbranch, -+ int perm) -+{ -+ struct au_branch *add_branch; -+ struct dentry *root; -+ struct inode *inode; -+ int err; -+ -+ err = -ENOMEM; -+ add_branch = kzalloc(sizeof(*add_branch), GFP_NOFS); -+ if (unlikely(!add_branch)) -+ goto out; -+ add_branch->br_xino = au_xino_alloc(/*nfile*/1); -+ if (unlikely(!add_branch->br_xino)) -+ goto out_br; -+ err = au_hnotify_init_br(add_branch, perm); -+ if (unlikely(err)) -+ goto out_xino; -+ -+ if (au_br_writable(perm)) { -+ /* may be freed separately at changing the branch permission */ -+ add_branch->br_wbr = kzalloc(sizeof(*add_branch->br_wbr), -+ GFP_NOFS); -+ if (unlikely(!add_branch->br_wbr)) -+ goto out_hnotify; -+ } -+ -+ if (au_br_fhsm(perm)) { -+ err = au_fhsm_br_alloc(add_branch); -+ if (unlikely(err)) -+ goto out_wbr; -+ } -+ -+ root = sb->s_root; -+ err = au_sbr_realloc(au_sbi(sb), new_nbranch, /*may_shrink*/0); -+ if (!err) -+ err = au_di_realloc(au_di(root), new_nbranch, /*may_shrink*/0); -+ if (!err) { -+ inode = d_inode(root); -+ err = au_hinode_realloc(au_ii(inode), new_nbranch, -+ /*may_shrink*/0); -+ } -+ if (!err) -+ return add_branch; /* success */ -+ -+out_wbr: -+ au_kfree_rcu(add_branch->br_wbr); -+out_hnotify: -+ au_hnotify_fin_br(add_branch); -+out_xino: -+ au_xino_put(add_branch); -+out_br: -+ au_kfree_rcu(add_branch); -+out: -+ return ERR_PTR(err); -+} -+ -+/* -+ * test if the branch permission is legal or not. -+ */ -+static int test_br(struct inode *inode, int brperm, char *path) -+{ -+ int err; -+ -+ err = (au_br_writable(brperm) && IS_RDONLY(inode)); -+ if (!err) -+ goto out; -+ -+ err = -EINVAL; -+ pr_err("write permission for readonly mount or inode, %s\n", path); -+ -+out: -+ return err; -+} -+ -+/* -+ * returns: -+ * 0: success, the caller will add it -+ * plus: success, it is already unified, the caller should ignore it -+ * minus: error -+ */ -+static int test_add(struct super_block *sb, struct au_opt_add *add, int remount) -+{ -+ int err; -+ aufs_bindex_t bbot, bindex; -+ struct dentry *root, *h_dentry; -+ struct inode *inode, *h_inode; -+ -+ root = sb->s_root; -+ bbot = au_sbbot(sb); -+ if (unlikely(bbot >= 0 -+ && au_find_dbindex(root, add->path.dentry) >= 0)) { -+ err = 1; -+ if (!remount) { -+ err = -EINVAL; -+ pr_err("%s duplicated\n", add->pathname); -+ } -+ goto out; -+ } -+ -+ err = -ENOSPC; /* -E2BIG; */ -+ if (unlikely(AUFS_BRANCH_MAX <= add->bindex -+ || AUFS_BRANCH_MAX - 1 <= bbot)) { -+ pr_err("number of branches exceeded %s\n", add->pathname); -+ goto out; -+ } -+ -+ err = -EDOM; -+ if (unlikely(add->bindex < 0 || bbot + 1 < add->bindex)) { -+ pr_err("bad index %d\n", add->bindex); -+ goto out; -+ } -+ -+ inode = d_inode(add->path.dentry); -+ err = -ENOENT; -+ if (unlikely(!inode->i_nlink)) { -+ pr_err("no existence %s\n", add->pathname); -+ goto out; -+ } -+ -+ err = -EINVAL; -+ if (unlikely(inode->i_sb == sb)) { -+ pr_err("%s must be outside\n", add->pathname); -+ goto out; -+ } -+ -+ if (unlikely(au_test_fs_unsuppoted(inode->i_sb))) { -+ pr_err("unsupported filesystem, %s (%s)\n", -+ add->pathname, au_sbtype(inode->i_sb)); -+ goto out; -+ } -+ -+ if (unlikely(inode->i_sb->s_stack_depth)) { -+ pr_err("already stacked, %s (%s)\n", -+ add->pathname, au_sbtype(inode->i_sb)); -+ goto out; -+ } -+ -+ err = test_br(d_inode(add->path.dentry), add->perm, add->pathname); -+ if (unlikely(err)) -+ goto out; -+ -+ if (bbot < 0) -+ return 0; /* success */ -+ -+ err = -EINVAL; -+ for (bindex = 0; bindex <= bbot; bindex++) -+ if (unlikely(test_overlap(sb, add->path.dentry, -+ au_h_dptr(root, bindex)))) { -+ pr_err("%s is overlapped\n", add->pathname); -+ goto out; -+ } -+ -+ err = 0; -+ if (au_opt_test(au_mntflags(sb), WARN_PERM)) { -+ h_dentry = au_h_dptr(root, 0); -+ h_inode = d_inode(h_dentry); -+ if ((h_inode->i_mode & S_IALLUGO) != (inode->i_mode & S_IALLUGO) -+ || !uid_eq(h_inode->i_uid, inode->i_uid) -+ || !gid_eq(h_inode->i_gid, inode->i_gid)) -+ pr_warn("uid/gid/perm %s %u/%u/0%o, %u/%u/0%o\n", -+ add->pathname, -+ i_uid_read(inode), i_gid_read(inode), -+ (inode->i_mode & S_IALLUGO), -+ i_uid_read(h_inode), i_gid_read(h_inode), -+ (h_inode->i_mode & S_IALLUGO)); -+ } -+ -+out: -+ return err; -+} -+ -+/* -+ * initialize or clean the whiteouts for an adding branch -+ */ -+static int au_br_init_wh(struct super_block *sb, struct au_branch *br, -+ int new_perm) -+{ -+ int err, old_perm; -+ aufs_bindex_t bindex; -+ struct inode *h_inode; -+ struct au_wbr *wbr; -+ struct au_hinode *hdir; -+ struct dentry *h_dentry; -+ -+ err = vfsub_mnt_want_write(au_br_mnt(br)); -+ if (unlikely(err)) -+ goto out; -+ -+ wbr = br->br_wbr; -+ old_perm = br->br_perm; -+ br->br_perm = new_perm; -+ hdir = NULL; -+ h_inode = NULL; -+ bindex = au_br_index(sb, br->br_id); -+ if (0 <= bindex) { -+ hdir = au_hi(d_inode(sb->s_root), bindex); -+ au_hn_inode_lock_nested(hdir, AuLsc_I_PARENT); -+ } else { -+ h_dentry = au_br_dentry(br); -+ h_inode = d_inode(h_dentry); -+ inode_lock_nested(h_inode, AuLsc_I_PARENT); -+ } -+ if (!wbr) -+ err = au_wh_init(br, sb); -+ else { -+ wbr_wh_write_lock(wbr); -+ err = au_wh_init(br, sb); -+ wbr_wh_write_unlock(wbr); -+ } -+ if (hdir) -+ au_hn_inode_unlock(hdir); -+ else -+ inode_unlock(h_inode); -+ vfsub_mnt_drop_write(au_br_mnt(br)); -+ br->br_perm = old_perm; -+ -+ if (!err && wbr && !au_br_writable(new_perm)) { -+ au_kfree_rcu(wbr); -+ br->br_wbr = NULL; -+ } -+ -+out: -+ return err; -+} -+ -+static int au_wbr_init(struct au_branch *br, struct super_block *sb, -+ int perm) -+{ -+ int err; -+ struct kstatfs kst; -+ struct au_wbr *wbr; -+ -+ wbr = br->br_wbr; -+ au_rw_init(&wbr->wbr_wh_rwsem); -+ atomic_set(&wbr->wbr_wh_running, 0); -+ -+ /* -+ * a limit for rmdir/rename a dir -+ * cf. AUFS_MAX_NAMELEN in include/uapi/linux/aufs_type.h -+ */ -+ err = vfs_statfs(&br->br_path, &kst); -+ if (unlikely(err)) -+ goto out; -+ err = -EINVAL; -+ if (kst.f_namelen >= NAME_MAX) -+ err = au_br_init_wh(sb, br, perm); -+ else -+ pr_err("%pd(%s), unsupported namelen %ld\n", -+ au_br_dentry(br), -+ au_sbtype(au_br_dentry(br)->d_sb), kst.f_namelen); -+ -+out: -+ return err; -+} -+ -+/* initialize a new branch */ -+static int au_br_init(struct au_branch *br, struct super_block *sb, -+ struct au_opt_add *add) -+{ -+ int err; -+ struct au_branch *brbase; -+ struct file *xf; -+ struct inode *h_inode; -+ -+ err = 0; -+ br->br_perm = add->perm; -+ br->br_path = add->path; /* set first, path_get() later */ -+ spin_lock_init(&br->br_dykey_lock); -+ au_lcnt_init(&br->br_nfiles, /*release*/NULL); -+ au_lcnt_init(&br->br_count, /*release*/NULL); -+ br->br_id = au_new_br_id(sb); -+ AuDebugOn(br->br_id < 0); -+ -+ /* always, regardless the given option */ -+ err = au_dr_br_init(sb, br, &add->path); -+ if (unlikely(err)) -+ goto out_err; -+ -+ if (au_br_writable(add->perm)) { -+ err = au_wbr_init(br, sb, add->perm); -+ if (unlikely(err)) -+ goto out_err; -+ } -+ -+ if (au_opt_test(au_mntflags(sb), XINO)) { -+ brbase = au_sbr(sb, 0); -+ xf = au_xino_file(brbase->br_xino, /*idx*/-1); -+ AuDebugOn(!xf); -+ h_inode = d_inode(add->path.dentry); -+ err = au_xino_init_br(sb, br, h_inode->i_ino, &xf->f_path); -+ if (unlikely(err)) { -+ AuDebugOn(au_xino_file(br->br_xino, /*idx*/-1)); -+ goto out_err; -+ } -+ } -+ -+ sysaufs_br_init(br); -+ path_get(&br->br_path); -+ goto out; /* success */ -+ -+out_err: -+ memset(&br->br_path, 0, sizeof(br->br_path)); -+out: -+ return err; -+} -+ -+static void au_br_do_add_brp(struct au_sbinfo *sbinfo, aufs_bindex_t bindex, -+ struct au_branch *br, aufs_bindex_t bbot, -+ aufs_bindex_t amount) -+{ -+ struct au_branch **brp; -+ -+ AuRwMustWriteLock(&sbinfo->si_rwsem); -+ -+ brp = sbinfo->si_branch + bindex; -+ memmove(brp + 1, brp, sizeof(*brp) * amount); -+ *brp = br; -+ sbinfo->si_bbot++; -+ if (unlikely(bbot < 0)) -+ sbinfo->si_bbot = 0; -+} -+ -+static void au_br_do_add_hdp(struct au_dinfo *dinfo, aufs_bindex_t bindex, -+ aufs_bindex_t bbot, aufs_bindex_t amount) -+{ -+ struct au_hdentry *hdp; -+ -+ AuRwMustWriteLock(&dinfo->di_rwsem); -+ -+ hdp = au_hdentry(dinfo, bindex); -+ memmove(hdp + 1, hdp, sizeof(*hdp) * amount); -+ au_h_dentry_init(hdp); -+ dinfo->di_bbot++; -+ if (unlikely(bbot < 0)) -+ dinfo->di_btop = 0; -+} -+ -+static void au_br_do_add_hip(struct au_iinfo *iinfo, aufs_bindex_t bindex, -+ aufs_bindex_t bbot, aufs_bindex_t amount) -+{ -+ struct au_hinode *hip; -+ -+ AuRwMustWriteLock(&iinfo->ii_rwsem); -+ -+ hip = au_hinode(iinfo, bindex); -+ memmove(hip + 1, hip, sizeof(*hip) * amount); -+ au_hinode_init(hip); -+ iinfo->ii_bbot++; -+ if (unlikely(bbot < 0)) -+ iinfo->ii_btop = 0; -+} -+ -+static void au_br_do_add(struct super_block *sb, struct au_branch *br, -+ aufs_bindex_t bindex) -+{ -+ struct dentry *root, *h_dentry; -+ struct inode *root_inode, *h_inode; -+ aufs_bindex_t bbot, amount; -+ -+ root = sb->s_root; -+ root_inode = d_inode(root); -+ bbot = au_sbbot(sb); -+ amount = bbot + 1 - bindex; -+ h_dentry = au_br_dentry(br); -+ au_sbilist_lock(); -+ au_br_do_add_brp(au_sbi(sb), bindex, br, bbot, amount); -+ au_br_do_add_hdp(au_di(root), bindex, bbot, amount); -+ au_br_do_add_hip(au_ii(root_inode), bindex, bbot, amount); -+ au_set_h_dptr(root, bindex, dget(h_dentry)); -+ h_inode = d_inode(h_dentry); -+ au_set_h_iptr(root_inode, bindex, au_igrab(h_inode), /*flags*/0); -+ au_sbilist_unlock(); -+} -+ -+int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount) -+{ -+ int err; -+ aufs_bindex_t bbot, add_bindex; -+ struct dentry *root, *h_dentry; -+ struct inode *root_inode; -+ struct au_branch *add_branch; -+ -+ root = sb->s_root; -+ root_inode = d_inode(root); -+ IMustLock(root_inode); -+ IiMustWriteLock(root_inode); -+ err = test_add(sb, add, remount); -+ if (unlikely(err < 0)) -+ goto out; -+ if (err) { -+ err = 0; -+ goto out; /* success */ -+ } -+ -+ bbot = au_sbbot(sb); -+ add_branch = au_br_alloc(sb, bbot + 2, add->perm); -+ err = PTR_ERR(add_branch); -+ if (IS_ERR(add_branch)) -+ goto out; -+ -+ err = au_br_init(add_branch, sb, add); -+ if (unlikely(err)) { -+ au_br_do_free(add_branch); -+ goto out; -+ } -+ -+ add_bindex = add->bindex; -+ sysaufs_brs_del(sb, add_bindex); /* remove successors */ -+ au_br_do_add(sb, add_branch, add_bindex); -+ sysaufs_brs_add(sb, add_bindex); /* append successors */ -+ dbgaufs_brs_add(sb, add_bindex, /*topdown*/0); /* rename successors */ -+ -+ h_dentry = add->path.dentry; -+ if (!add_bindex) { -+ au_cpup_attr_all(root_inode, /*force*/1); -+ sb->s_maxbytes = h_dentry->d_sb->s_maxbytes; -+ } else -+ au_add_nlink(root_inode, d_inode(h_dentry)); -+ -+out: -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static unsigned long long au_farray_cb(struct super_block *sb, void *a, -+ unsigned long long max __maybe_unused, -+ void *arg) -+{ -+ unsigned long long n; -+ struct file **p, *f; -+ struct hlist_bl_head *files; -+ struct hlist_bl_node *pos; -+ struct au_finfo *finfo; -+ -+ n = 0; -+ p = a; -+ files = &au_sbi(sb)->si_files; -+ hlist_bl_lock(files); -+ hlist_bl_for_each_entry(finfo, pos, files, fi_hlist) { -+ f = finfo->fi_file; -+ if (file_count(f) -+ && !special_file(file_inode(f)->i_mode)) { -+ get_file(f); -+ *p++ = f; -+ n++; -+ AuDebugOn(n > max); -+ } -+ } -+ hlist_bl_unlock(files); -+ -+ return n; -+} -+ -+static struct file **au_farray_alloc(struct super_block *sb, -+ unsigned long long *max) -+{ -+ struct au_sbinfo *sbi; -+ -+ sbi = au_sbi(sb); -+ *max = au_lcnt_read(&sbi->si_nfiles, /*do_rev*/1); -+ return au_array_alloc(max, au_farray_cb, sb, /*arg*/NULL); -+} -+ -+static void au_farray_free(struct file **a, unsigned long long max) -+{ -+ unsigned long long ull; -+ -+ for (ull = 0; ull < max; ull++) -+ if (a[ull]) -+ fput(a[ull]); -+ kvfree(a); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * delete a branch -+ */ -+ -+/* to show the line number, do not make it inlined function */ -+#define AuVerbose(do_info, fmt, ...) do { \ -+ if (do_info) \ -+ pr_info(fmt, ##__VA_ARGS__); \ -+} while (0) -+ -+static int au_test_ibusy(struct inode *inode, aufs_bindex_t btop, -+ aufs_bindex_t bbot) -+{ -+ return (inode && !S_ISDIR(inode->i_mode)) || btop == bbot; -+} -+ -+static int au_test_dbusy(struct dentry *dentry, aufs_bindex_t btop, -+ aufs_bindex_t bbot) -+{ -+ return au_test_ibusy(d_inode(dentry), btop, bbot); -+} -+ -+/* -+ * test if the branch is deletable or not. -+ */ -+static int test_dentry_busy(struct dentry *root, aufs_bindex_t bindex, -+ unsigned int sigen, const unsigned int verbose) -+{ -+ int err, i, j, ndentry; -+ aufs_bindex_t btop, bbot; -+ struct au_dcsub_pages dpages; -+ struct au_dpage *dpage; -+ struct dentry *d; -+ -+ err = au_dpages_init(&dpages, GFP_NOFS); -+ if (unlikely(err)) -+ goto out; -+ err = au_dcsub_pages(&dpages, root, NULL, NULL); -+ if (unlikely(err)) -+ goto out_dpages; -+ -+ for (i = 0; !err && i < dpages.ndpage; i++) { -+ dpage = dpages.dpages + i; -+ ndentry = dpage->ndentry; -+ for (j = 0; !err && j < ndentry; j++) { -+ d = dpage->dentries[j]; -+ AuDebugOn(au_dcount(d) <= 0); -+ if (!au_digen_test(d, sigen)) { -+ di_read_lock_child(d, AuLock_IR); -+ if (unlikely(au_dbrange_test(d))) { -+ di_read_unlock(d, AuLock_IR); -+ continue; -+ } -+ } else { -+ di_write_lock_child(d); -+ if (unlikely(au_dbrange_test(d))) { -+ di_write_unlock(d); -+ continue; -+ } -+ err = au_reval_dpath(d, sigen); -+ if (!err) -+ di_downgrade_lock(d, AuLock_IR); -+ else { -+ di_write_unlock(d); -+ break; -+ } -+ } -+ -+ /* AuDbgDentry(d); */ -+ btop = au_dbtop(d); -+ bbot = au_dbbot(d); -+ if (btop <= bindex -+ && bindex <= bbot -+ && au_h_dptr(d, bindex) -+ && au_test_dbusy(d, btop, bbot)) { -+ err = -EBUSY; -+ AuVerbose(verbose, "busy %pd\n", d); -+ AuDbgDentry(d); -+ } -+ di_read_unlock(d, AuLock_IR); -+ } -+ } -+ -+out_dpages: -+ au_dpages_free(&dpages); -+out: -+ return err; -+} -+ -+static int test_inode_busy(struct super_block *sb, aufs_bindex_t bindex, -+ unsigned int sigen, const unsigned int verbose) -+{ -+ int err; -+ unsigned long long max, ull; -+ struct inode *i, **array; -+ aufs_bindex_t btop, bbot; -+ -+ array = au_iarray_alloc(sb, &max); -+ err = PTR_ERR(array); -+ if (IS_ERR(array)) -+ goto out; -+ -+ err = 0; -+ AuDbg("b%d\n", bindex); -+ for (ull = 0; !err && ull < max; ull++) { -+ i = array[ull]; -+ if (unlikely(!i)) -+ break; -+ if (i->i_ino == AUFS_ROOT_INO) -+ continue; -+ -+ /* AuDbgInode(i); */ -+ if (au_iigen(i, NULL) == sigen) -+ ii_read_lock_child(i); -+ else { -+ ii_write_lock_child(i); -+ err = au_refresh_hinode_self(i); -+ au_iigen_dec(i); -+ if (!err) -+ ii_downgrade_lock(i); -+ else { -+ ii_write_unlock(i); -+ break; -+ } -+ } -+ -+ btop = au_ibtop(i); -+ bbot = au_ibbot(i); -+ if (btop <= bindex -+ && bindex <= bbot -+ && au_h_iptr(i, bindex) -+ && au_test_ibusy(i, btop, bbot)) { -+ err = -EBUSY; -+ AuVerbose(verbose, "busy i%lu\n", i->i_ino); -+ AuDbgInode(i); -+ } -+ ii_read_unlock(i); -+ } -+ au_iarray_free(array, max); -+ -+out: -+ return err; -+} -+ -+static int test_children_busy(struct dentry *root, aufs_bindex_t bindex, -+ const unsigned int verbose) -+{ -+ int err; -+ unsigned int sigen; -+ -+ sigen = au_sigen(root->d_sb); -+ DiMustNoWaiters(root); -+ IiMustNoWaiters(d_inode(root)); -+ di_write_unlock(root); -+ err = test_dentry_busy(root, bindex, sigen, verbose); -+ if (!err) -+ err = test_inode_busy(root->d_sb, bindex, sigen, verbose); -+ di_write_lock_child(root); /* aufs_write_lock() calls ..._child() */ -+ -+ return err; -+} -+ -+static int test_dir_busy(struct file *file, aufs_bindex_t br_id, -+ struct file **to_free, int *idx) -+{ -+ int err; -+ unsigned char matched, root; -+ aufs_bindex_t bindex, bbot; -+ struct au_fidir *fidir; -+ struct au_hfile *hfile; -+ -+ err = 0; -+ root = IS_ROOT(file->f_path.dentry); -+ if (root) { -+ get_file(file); -+ to_free[*idx] = file; -+ (*idx)++; -+ goto out; -+ } -+ -+ matched = 0; -+ fidir = au_fi(file)->fi_hdir; -+ AuDebugOn(!fidir); -+ bbot = au_fbbot_dir(file); -+ for (bindex = au_fbtop(file); bindex <= bbot; bindex++) { -+ hfile = fidir->fd_hfile + bindex; -+ if (!hfile->hf_file) -+ continue; -+ -+ if (hfile->hf_br->br_id == br_id) { -+ matched = 1; -+ break; -+ } -+ } -+ if (matched) -+ err = -EBUSY; -+ -+out: -+ return err; -+} -+ -+static int test_file_busy(struct super_block *sb, aufs_bindex_t br_id, -+ struct file **to_free, int opened) -+{ -+ int err, idx; -+ unsigned long long ull, max; -+ aufs_bindex_t btop; -+ struct file *file, **array; -+ struct dentry *root; -+ struct au_hfile *hfile; -+ -+ array = au_farray_alloc(sb, &max); -+ err = PTR_ERR(array); -+ if (IS_ERR(array)) -+ goto out; -+ -+ err = 0; -+ idx = 0; -+ root = sb->s_root; -+ di_write_unlock(root); -+ for (ull = 0; ull < max; ull++) { -+ file = array[ull]; -+ if (unlikely(!file)) -+ break; -+ -+ /* AuDbg("%pD\n", file); */ -+ fi_read_lock(file); -+ btop = au_fbtop(file); -+ if (!d_is_dir(file->f_path.dentry)) { -+ hfile = &au_fi(file)->fi_htop; -+ if (hfile->hf_br->br_id == br_id) -+ err = -EBUSY; -+ } else -+ err = test_dir_busy(file, br_id, to_free, &idx); -+ fi_read_unlock(file); -+ if (unlikely(err)) -+ break; -+ } -+ di_write_lock_child(root); -+ au_farray_free(array, max); -+ AuDebugOn(idx > opened); -+ -+out: -+ return err; -+} -+ -+static void br_del_file(struct file **to_free, unsigned long long opened, -+ aufs_bindex_t br_id) -+{ -+ unsigned long long ull; -+ aufs_bindex_t bindex, btop, bbot, bfound; -+ struct file *file; -+ struct au_fidir *fidir; -+ struct au_hfile *hfile; -+ -+ for (ull = 0; ull < opened; ull++) { -+ file = to_free[ull]; -+ if (unlikely(!file)) -+ break; -+ -+ /* AuDbg("%pD\n", file); */ -+ AuDebugOn(!d_is_dir(file->f_path.dentry)); -+ bfound = -1; -+ fidir = au_fi(file)->fi_hdir; -+ AuDebugOn(!fidir); -+ fi_write_lock(file); -+ btop = au_fbtop(file); -+ bbot = au_fbbot_dir(file); -+ for (bindex = btop; bindex <= bbot; bindex++) { -+ hfile = fidir->fd_hfile + bindex; -+ if (!hfile->hf_file) -+ continue; -+ -+ if (hfile->hf_br->br_id == br_id) { -+ bfound = bindex; -+ break; -+ } -+ } -+ AuDebugOn(bfound < 0); -+ au_set_h_fptr(file, bfound, NULL); -+ if (bfound == btop) { -+ for (btop++; btop <= bbot; btop++) -+ if (au_hf_dir(file, btop)) { -+ au_set_fbtop(file, btop); -+ break; -+ } -+ } -+ fi_write_unlock(file); -+ } -+} -+ -+static void au_br_do_del_brp(struct au_sbinfo *sbinfo, -+ const aufs_bindex_t bindex, -+ const aufs_bindex_t bbot) -+{ -+ struct au_branch **brp, **p; -+ -+ AuRwMustWriteLock(&sbinfo->si_rwsem); -+ -+ brp = sbinfo->si_branch + bindex; -+ if (bindex < bbot) -+ memmove(brp, brp + 1, sizeof(*brp) * (bbot - bindex)); -+ sbinfo->si_branch[0 + bbot] = NULL; -+ sbinfo->si_bbot--; -+ -+ p = au_krealloc(sbinfo->si_branch, sizeof(*p) * bbot, AuGFP_SBILIST, -+ /*may_shrink*/1); -+ if (p) -+ sbinfo->si_branch = p; -+ /* harmless error */ -+} -+ -+static void au_br_do_del_hdp(struct au_dinfo *dinfo, const aufs_bindex_t bindex, -+ const aufs_bindex_t bbot) -+{ -+ struct au_hdentry *hdp, *p; -+ -+ AuRwMustWriteLock(&dinfo->di_rwsem); -+ -+ hdp = au_hdentry(dinfo, bindex); -+ if (bindex < bbot) -+ memmove(hdp, hdp + 1, sizeof(*hdp) * (bbot - bindex)); -+ /* au_h_dentry_init(au_hdentry(dinfo, bbot); */ -+ dinfo->di_bbot--; -+ -+ p = au_krealloc(dinfo->di_hdentry, sizeof(*p) * bbot, AuGFP_SBILIST, -+ /*may_shrink*/1); -+ if (p) -+ dinfo->di_hdentry = p; -+ /* harmless error */ -+} -+ -+static void au_br_do_del_hip(struct au_iinfo *iinfo, const aufs_bindex_t bindex, -+ const aufs_bindex_t bbot) -+{ -+ struct au_hinode *hip, *p; -+ -+ AuRwMustWriteLock(&iinfo->ii_rwsem); -+ -+ hip = au_hinode(iinfo, bindex); -+ if (bindex < bbot) -+ memmove(hip, hip + 1, sizeof(*hip) * (bbot - bindex)); -+ /* au_hinode_init(au_hinode(iinfo, bbot)); */ -+ iinfo->ii_bbot--; -+ -+ p = au_krealloc(iinfo->ii_hinode, sizeof(*p) * bbot, AuGFP_SBILIST, -+ /*may_shrink*/1); -+ if (p) -+ iinfo->ii_hinode = p; -+ /* harmless error */ -+} -+ -+static void au_br_do_del(struct super_block *sb, aufs_bindex_t bindex, -+ struct au_branch *br) -+{ -+ aufs_bindex_t bbot; -+ struct au_sbinfo *sbinfo; -+ struct dentry *root, *h_root; -+ struct inode *inode, *h_inode; -+ struct au_hinode *hinode; -+ -+ SiMustWriteLock(sb); -+ -+ root = sb->s_root; -+ inode = d_inode(root); -+ sbinfo = au_sbi(sb); -+ bbot = sbinfo->si_bbot; -+ -+ h_root = au_h_dptr(root, bindex); -+ hinode = au_hi(inode, bindex); -+ h_inode = au_igrab(hinode->hi_inode); -+ au_hiput(hinode); -+ -+ au_sbilist_lock(); -+ au_br_do_del_brp(sbinfo, bindex, bbot); -+ au_br_do_del_hdp(au_di(root), bindex, bbot); -+ au_br_do_del_hip(au_ii(inode), bindex, bbot); -+ au_sbilist_unlock(); -+ -+ /* ignore an error */ -+ au_dr_br_fin(sb, br); /* always, regardless the mount option */ -+ -+ dput(h_root); -+ iput(h_inode); -+ au_br_do_free(br); -+} -+ -+static unsigned long long empty_cb(struct super_block *sb, void *array, -+ unsigned long long max, void *arg) -+{ -+ return max; -+} -+ -+int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount) -+{ -+ int err, rerr, i; -+ unsigned long long opened; -+ unsigned int mnt_flags; -+ aufs_bindex_t bindex, bbot, br_id; -+ unsigned char do_wh, verbose; -+ struct au_branch *br; -+ struct au_wbr *wbr; -+ struct dentry *root; -+ struct file **to_free; -+ -+ err = 0; -+ opened = 0; -+ to_free = NULL; -+ root = sb->s_root; -+ bindex = au_find_dbindex(root, del->h_path.dentry); -+ if (bindex < 0) { -+ if (remount) -+ goto out; /* success */ -+ err = -ENOENT; -+ pr_err("%s no such branch\n", del->pathname); -+ goto out; -+ } -+ AuDbg("bindex b%d\n", bindex); -+ -+ err = -EBUSY; -+ mnt_flags = au_mntflags(sb); -+ verbose = !!au_opt_test(mnt_flags, VERBOSE); -+ bbot = au_sbbot(sb); -+ if (unlikely(!bbot)) { -+ AuVerbose(verbose, "no more branches left\n"); -+ goto out; -+ } -+ -+ br = au_sbr(sb, bindex); -+ AuDebugOn(!path_equal(&br->br_path, &del->h_path)); -+ if (unlikely(au_lcnt_read(&br->br_count, /*do_rev*/1))) { -+ AuVerbose(verbose, "br %pd2 is busy now\n", del->h_path.dentry); -+ goto out; -+ } -+ -+ br_id = br->br_id; -+ opened = au_lcnt_read(&br->br_nfiles, /*do_rev*/1); -+ if (unlikely(opened)) { -+ to_free = au_array_alloc(&opened, empty_cb, sb, NULL); -+ err = PTR_ERR(to_free); -+ if (IS_ERR(to_free)) -+ goto out; -+ -+ err = test_file_busy(sb, br_id, to_free, opened); -+ if (unlikely(err)) { -+ AuVerbose(verbose, "%llu file(s) opened\n", opened); -+ goto out; -+ } -+ } -+ -+ wbr = br->br_wbr; -+ do_wh = wbr && (wbr->wbr_whbase || wbr->wbr_plink || wbr->wbr_orph); -+ if (do_wh) { -+ /* instead of WbrWhMustWriteLock(wbr) */ -+ SiMustWriteLock(sb); -+ for (i = 0; i < AuBrWh_Last; i++) { -+ dput(wbr->wbr_wh[i]); -+ wbr->wbr_wh[i] = NULL; -+ } -+ } -+ -+ err = test_children_busy(root, bindex, verbose); -+ if (unlikely(err)) { -+ if (do_wh) -+ goto out_wh; -+ goto out; -+ } -+ -+ err = 0; -+ if (to_free) { -+ /* -+ * now we confirmed the branch is deletable. -+ * let's free the remaining opened dirs on the branch. -+ */ -+ di_write_unlock(root); -+ br_del_file(to_free, opened, br_id); -+ di_write_lock_child(root); -+ } -+ -+ sysaufs_brs_del(sb, bindex); /* remove successors */ -+ dbgaufs_xino_del(br); /* remove one */ -+ au_br_do_del(sb, bindex, br); -+ sysaufs_brs_add(sb, bindex); /* append successors */ -+ dbgaufs_brs_add(sb, bindex, /*topdown*/1); /* rename successors */ -+ -+ if (!bindex) { -+ au_cpup_attr_all(d_inode(root), /*force*/1); -+ sb->s_maxbytes = au_sbr_sb(sb, 0)->s_maxbytes; -+ } else -+ au_sub_nlink(d_inode(root), d_inode(del->h_path.dentry)); -+ if (au_opt_test(mnt_flags, PLINK)) -+ au_plink_half_refresh(sb, br_id); -+ -+ goto out; /* success */ -+ -+out_wh: -+ /* revert */ -+ rerr = au_br_init_wh(sb, br, br->br_perm); -+ if (rerr) -+ pr_warn("failed re-creating base whiteout, %s. (%d)\n", -+ del->pathname, rerr); -+out: -+ if (to_free) -+ au_farray_free(to_free, opened); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int au_ibusy(struct super_block *sb, struct aufs_ibusy __user *arg) -+{ -+ int err; -+ aufs_bindex_t btop, bbot; -+ struct aufs_ibusy ibusy; -+ struct inode *inode, *h_inode; -+ -+ err = -EPERM; -+ if (unlikely(!capable(CAP_SYS_ADMIN))) -+ goto out; -+ -+ err = copy_from_user(&ibusy, arg, sizeof(ibusy)); -+ if (!err) -+ /* VERIFY_WRITE */ -+ err = !access_ok(&arg->h_ino, sizeof(arg->h_ino)); -+ if (unlikely(err)) { -+ err = -EFAULT; -+ AuTraceErr(err); -+ goto out; -+ } -+ -+ err = -EINVAL; -+ si_read_lock(sb, AuLock_FLUSH); -+ if (unlikely(ibusy.bindex < 0 || ibusy.bindex > au_sbbot(sb))) -+ goto out_unlock; -+ -+ err = 0; -+ ibusy.h_ino = 0; /* invalid */ -+ inode = ilookup(sb, ibusy.ino); -+ if (!inode -+ || inode->i_ino == AUFS_ROOT_INO -+ || au_is_bad_inode(inode)) -+ goto out_unlock; -+ -+ ii_read_lock_child(inode); -+ btop = au_ibtop(inode); -+ bbot = au_ibbot(inode); -+ if (btop <= ibusy.bindex && ibusy.bindex <= bbot) { -+ h_inode = au_h_iptr(inode, ibusy.bindex); -+ if (h_inode && au_test_ibusy(inode, btop, bbot)) -+ ibusy.h_ino = h_inode->i_ino; -+ } -+ ii_read_unlock(inode); -+ iput(inode); -+ -+out_unlock: -+ si_read_unlock(sb); -+ if (!err) { -+ err = __put_user(ibusy.h_ino, &arg->h_ino); -+ if (unlikely(err)) { -+ err = -EFAULT; -+ AuTraceErr(err); -+ } -+ } -+out: -+ return err; -+} -+ -+long au_ibusy_ioctl(struct file *file, unsigned long arg) -+{ -+ return au_ibusy(file->f_path.dentry->d_sb, (void __user *)arg); -+} -+ -+#ifdef CONFIG_COMPAT -+long au_ibusy_compat_ioctl(struct file *file, unsigned long arg) -+{ -+ return au_ibusy(file->f_path.dentry->d_sb, compat_ptr(arg)); -+} -+#endif -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * change a branch permission -+ */ -+ -+static void au_warn_ima(void) -+{ -+#ifdef CONFIG_IMA -+ /* since it doesn't support mark_files_ro() */ -+ AuWarn1("RW -> RO makes IMA to produce wrong message\n"); -+#endif -+} -+ -+static int do_need_sigen_inc(int a, int b) -+{ -+ return au_br_whable(a) && !au_br_whable(b); -+} -+ -+static int need_sigen_inc(int old, int new) -+{ -+ return do_need_sigen_inc(old, new) -+ || do_need_sigen_inc(new, old); -+} -+ -+static int au_br_mod_files_ro(struct super_block *sb, aufs_bindex_t bindex) -+{ -+ int err, do_warn; -+ unsigned int mnt_flags; -+ unsigned long long ull, max; -+ aufs_bindex_t br_id; -+ unsigned char verbose, writer; -+ struct file *file, *hf, **array; -+ struct au_hfile *hfile; -+ struct inode *h_inode; -+ -+ mnt_flags = au_mntflags(sb); -+ verbose = !!au_opt_test(mnt_flags, VERBOSE); -+ -+ array = au_farray_alloc(sb, &max); -+ err = PTR_ERR(array); -+ if (IS_ERR(array)) -+ goto out; -+ -+ do_warn = 0; -+ br_id = au_sbr_id(sb, bindex); -+ for (ull = 0; ull < max; ull++) { -+ file = array[ull]; -+ if (unlikely(!file)) -+ break; -+ -+ /* AuDbg("%pD\n", file); */ -+ fi_read_lock(file); -+ if (unlikely(au_test_mmapped(file))) { -+ err = -EBUSY; -+ AuVerbose(verbose, "mmapped %pD\n", file); -+ AuDbgFile(file); -+ FiMustNoWaiters(file); -+ fi_read_unlock(file); -+ goto out_array; -+ } -+ -+ hfile = &au_fi(file)->fi_htop; -+ hf = hfile->hf_file; -+ if (!d_is_reg(file->f_path.dentry) -+ || !(file->f_mode & FMODE_WRITE) -+ || hfile->hf_br->br_id != br_id -+ || !(hf->f_mode & FMODE_WRITE)) -+ array[ull] = NULL; -+ else { -+ do_warn = 1; -+ get_file(file); -+ } -+ -+ FiMustNoWaiters(file); -+ fi_read_unlock(file); -+ fput(file); -+ } -+ -+ err = 0; -+ if (do_warn) -+ au_warn_ima(); -+ -+ for (ull = 0; ull < max; ull++) { -+ file = array[ull]; -+ if (!file) -+ continue; -+ -+ /* todo: already flushed? */ -+ /* -+ * fs/super.c:mark_files_ro() is gone, but aufs keeps its -+ * approach which resets f_mode and calls mnt_drop_write() and -+ * file_release_write() for each file, because the branch -+ * attribute in aufs world is totally different from the native -+ * fs rw/ro mode. -+ */ -+ /* fi_read_lock(file); */ -+ hfile = &au_fi(file)->fi_htop; -+ hf = hfile->hf_file; -+ /* fi_read_unlock(file); */ -+ spin_lock(&hf->f_lock); -+ writer = !!(hf->f_mode & FMODE_WRITER); -+ hf->f_mode &= ~(FMODE_WRITE | FMODE_WRITER); -+ spin_unlock(&hf->f_lock); -+ if (writer) { -+ h_inode = file_inode(hf); -+ put_write_access(h_inode); -+ __mnt_drop_write(hf->f_path.mnt); -+ if ((hf->f_mode & (FMODE_READ | FMODE_WRITE)) -+ == FMODE_READ) -+ i_readcount_inc(h_inode); -+ } -+ } -+ -+out_array: -+ au_farray_free(array, max); -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount, -+ int *do_refresh) -+{ -+ int err, rerr; -+ aufs_bindex_t bindex; -+ struct dentry *root; -+ struct au_branch *br; -+ struct au_br_fhsm *bf; -+ -+ root = sb->s_root; -+ bindex = au_find_dbindex(root, mod->h_root); -+ if (bindex < 0) { -+ if (remount) -+ return 0; /* success */ -+ err = -ENOENT; -+ pr_err("%s no such branch\n", mod->path); -+ goto out; -+ } -+ AuDbg("bindex b%d\n", bindex); -+ -+ err = test_br(d_inode(mod->h_root), mod->perm, mod->path); -+ if (unlikely(err)) -+ goto out; -+ -+ br = au_sbr(sb, bindex); -+ AuDebugOn(mod->h_root != au_br_dentry(br)); -+ if (br->br_perm == mod->perm) -+ return 0; /* success */ -+ -+ /* pre-allocate for non-fhsm --> fhsm */ -+ bf = NULL; -+ if (!au_br_fhsm(br->br_perm) && au_br_fhsm(mod->perm)) { -+ err = au_fhsm_br_alloc(br); -+ if (unlikely(err)) -+ goto out; -+ bf = br->br_fhsm; -+ br->br_fhsm = NULL; -+ } -+ -+ if (au_br_writable(br->br_perm)) { -+ /* remove whiteout base */ -+ err = au_br_init_wh(sb, br, mod->perm); -+ if (unlikely(err)) -+ goto out_bf; -+ -+ if (!au_br_writable(mod->perm)) { -+ /* rw --> ro, file might be mmapped */ -+ DiMustNoWaiters(root); -+ IiMustNoWaiters(d_inode(root)); -+ di_write_unlock(root); -+ err = au_br_mod_files_ro(sb, bindex); -+ /* aufs_write_lock() calls ..._child() */ -+ di_write_lock_child(root); -+ -+ if (unlikely(err)) { -+ rerr = -ENOMEM; -+ br->br_wbr = kzalloc(sizeof(*br->br_wbr), -+ GFP_NOFS); -+ if (br->br_wbr) -+ rerr = au_wbr_init(br, sb, br->br_perm); -+ if (unlikely(rerr)) { -+ AuIOErr("nested error %d (%d)\n", -+ rerr, err); -+ br->br_perm = mod->perm; -+ } -+ } -+ } -+ } else if (au_br_writable(mod->perm)) { -+ /* ro --> rw */ -+ err = -ENOMEM; -+ br->br_wbr = kzalloc(sizeof(*br->br_wbr), GFP_NOFS); -+ if (br->br_wbr) { -+ err = au_wbr_init(br, sb, mod->perm); -+ if (unlikely(err)) { -+ au_kfree_rcu(br->br_wbr); -+ br->br_wbr = NULL; -+ } -+ } -+ } -+ if (unlikely(err)) -+ goto out_bf; -+ -+ if (au_br_fhsm(br->br_perm)) { -+ if (!au_br_fhsm(mod->perm)) { -+ /* fhsm --> non-fhsm */ -+ au_br_fhsm_fin(br->br_fhsm); -+ au_kfree_rcu(br->br_fhsm); -+ br->br_fhsm = NULL; -+ } -+ } else if (au_br_fhsm(mod->perm)) -+ /* non-fhsm --> fhsm */ -+ br->br_fhsm = bf; -+ -+ *do_refresh |= need_sigen_inc(br->br_perm, mod->perm); -+ br->br_perm = mod->perm; -+ goto out; /* success */ -+ -+out_bf: -+ au_kfree_try_rcu(bf); -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+int au_br_stfs(struct au_branch *br, struct aufs_stfs *stfs) -+{ -+ int err; -+ struct kstatfs kstfs; -+ -+ err = vfs_statfs(&br->br_path, &kstfs); -+ if (!err) { -+ stfs->f_blocks = kstfs.f_blocks; -+ stfs->f_bavail = kstfs.f_bavail; -+ stfs->f_files = kstfs.f_files; -+ stfs->f_ffree = kstfs.f_ffree; -+ } -+ -+ return err; -+} -diff -Nurp linux-5.6.3/fs/aufs/branch.h linux-5.6.3-aufs/fs/aufs/branch.h ---- linux-5.6.3/fs/aufs/branch.h 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/branch.h 2020-04-10 12:40:52.188049315 +0300 -@@ -0,0 +1,353 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * branch filesystems and xino for them -+ */ -+ -+#ifndef __AUFS_BRANCH_H__ -+#define __AUFS_BRANCH_H__ -+ -+#ifdef __KERNEL__ -+ -+#include -+#include "dirren.h" -+#include "dynop.h" -+#include "lcnt.h" -+#include "rwsem.h" -+#include "super.h" -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* a xino file */ -+struct au_xino { -+ struct file **xi_file; -+ unsigned int xi_nfile; -+ -+ struct { -+ spinlock_t spin; -+ ino_t *array; -+ int total; -+ /* reserved for future use */ -+ /* unsigned long *bitmap; */ -+ wait_queue_head_t wqh; -+ } xi_nondir; -+ -+ struct mutex xi_mtx; /* protects xi_file array */ -+ struct hlist_bl_head xi_writing; -+ -+ atomic_t xi_truncating; -+ -+ struct kref xi_kref; -+}; -+ -+/* File-based Hierarchical Storage Management */ -+struct au_br_fhsm { -+#ifdef CONFIG_AUFS_FHSM -+ struct mutex bf_lock; -+ unsigned long bf_jiffy; -+ struct aufs_stfs bf_stfs; -+ int bf_readable; -+#endif -+}; -+ -+/* members for writable branch only */ -+enum {AuBrWh_BASE, AuBrWh_PLINK, AuBrWh_ORPH, AuBrWh_Last}; -+struct au_wbr { -+ struct au_rwsem wbr_wh_rwsem; -+ struct dentry *wbr_wh[AuBrWh_Last]; -+ atomic_t wbr_wh_running; -+#define wbr_whbase wbr_wh[AuBrWh_BASE] /* whiteout base */ -+#define wbr_plink wbr_wh[AuBrWh_PLINK] /* pseudo-link dir */ -+#define wbr_orph wbr_wh[AuBrWh_ORPH] /* dir for orphans */ -+ -+ /* mfs mode */ -+ unsigned long long wbr_bytes; -+}; -+ -+/* ext2 has 3 types of operations at least, ext3 has 4 */ -+#define AuBrDynOp (AuDyLast * 4) -+ -+#ifdef CONFIG_AUFS_HFSNOTIFY -+/* support for asynchronous destruction */ -+struct au_br_hfsnotify { -+ struct fsnotify_group *hfsn_group; -+}; -+#endif -+ -+/* sysfs entries */ -+struct au_brsysfs { -+ char name[16]; -+ struct attribute attr; -+}; -+ -+enum { -+ AuBrSysfs_BR, -+ AuBrSysfs_BRID, -+ AuBrSysfs_Last -+}; -+ -+/* protected by superblock rwsem */ -+struct au_branch { -+ struct au_xino *br_xino; -+ -+ aufs_bindex_t br_id; -+ -+ int br_perm; -+ struct path br_path; -+ spinlock_t br_dykey_lock; -+ struct au_dykey *br_dykey[AuBrDynOp]; -+ au_lcnt_t br_nfiles; /* opened files */ -+ au_lcnt_t br_count; /* in-use for other */ -+ -+ struct au_wbr *br_wbr; -+ struct au_br_fhsm *br_fhsm; -+ -+#ifdef CONFIG_AUFS_HFSNOTIFY -+ struct au_br_hfsnotify *br_hfsn; -+#endif -+ -+#ifdef CONFIG_SYSFS -+ /* entries under sysfs per mount-point */ -+ struct au_brsysfs br_sysfs[AuBrSysfs_Last]; -+#endif -+ -+#ifdef CONFIG_DEBUG_FS -+ struct dentry *br_dbgaufs; /* xino */ -+#endif -+ -+ struct au_dr_br br_dirren; -+}; -+ -+/* ---------------------------------------------------------------------- */ -+ -+static inline struct vfsmount *au_br_mnt(struct au_branch *br) -+{ -+ return br->br_path.mnt; -+} -+ -+static inline struct dentry *au_br_dentry(struct au_branch *br) -+{ -+ return br->br_path.dentry; -+} -+ -+static inline struct super_block *au_br_sb(struct au_branch *br) -+{ -+ return au_br_mnt(br)->mnt_sb; -+} -+ -+static inline int au_br_rdonly(struct au_branch *br) -+{ -+ return (sb_rdonly(au_br_sb(br)) -+ || !au_br_writable(br->br_perm)) -+ ? -EROFS : 0; -+} -+ -+static inline int au_br_hnotifyable(int brperm __maybe_unused) -+{ -+#ifdef CONFIG_AUFS_HNOTIFY -+ return !(brperm & AuBrPerm_RR); -+#else -+ return 0; -+#endif -+} -+ -+static inline int au_br_test_oflag(int oflag, struct au_branch *br) -+{ -+ int err, exec_flag; -+ -+ err = 0; -+ exec_flag = oflag & __FMODE_EXEC; -+ if (unlikely(exec_flag && path_noexec(&br->br_path))) -+ err = -EACCES; -+ -+ return err; -+} -+ -+static inline void au_xino_get(struct au_branch *br) -+{ -+ struct au_xino *xi; -+ -+ xi = br->br_xino; -+ if (xi) -+ kref_get(&xi->xi_kref); -+} -+ -+static inline int au_xino_count(struct au_branch *br) -+{ -+ int v; -+ struct au_xino *xi; -+ -+ v = 0; -+ xi = br->br_xino; -+ if (xi) -+ v = kref_read(&xi->xi_kref); -+ -+ return v; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* branch.c */ -+struct au_sbinfo; -+void au_br_free(struct au_sbinfo *sinfo); -+int au_br_index(struct super_block *sb, aufs_bindex_t br_id); -+struct au_opt_add; -+int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount); -+struct au_opt_del; -+int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount); -+long au_ibusy_ioctl(struct file *file, unsigned long arg); -+#ifdef CONFIG_COMPAT -+long au_ibusy_compat_ioctl(struct file *file, unsigned long arg); -+#endif -+struct au_opt_mod; -+int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount, -+ int *do_refresh); -+struct aufs_stfs; -+int au_br_stfs(struct au_branch *br, struct aufs_stfs *stfs); -+ -+/* xino.c */ -+static const loff_t au_loff_max = LLONG_MAX; -+ -+aufs_bindex_t au_xi_root(struct super_block *sb, struct dentry *dentry); -+struct file *au_xino_create(struct super_block *sb, char *fpath, int silent, -+ int wbrtop); -+struct file *au_xino_create2(struct super_block *sb, struct path *base, -+ struct file *copy_src); -+struct au_xi_new { -+ struct au_xino *xi; /* switch between xino and xigen */ -+ int idx; -+ struct path *base; -+ struct file *copy_src; -+}; -+struct file *au_xi_new(struct super_block *sb, struct au_xi_new *xinew); -+ -+int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, -+ ino_t *ino); -+int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, -+ ino_t ino); -+ssize_t xino_fread(vfs_readf_t func, struct file *file, void *buf, size_t size, -+ loff_t *pos); -+ssize_t xino_fwrite(vfs_writef_t func, struct file *file, void *buf, -+ size_t size, loff_t *pos); -+ -+int au_xib_trunc(struct super_block *sb); -+int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex, int idx_begin); -+ -+struct au_xino *au_xino_alloc(unsigned int nfile); -+int au_xino_put(struct au_branch *br); -+struct file *au_xino_file1(struct au_xino *xi); -+ -+struct au_opt_xino; -+void au_xino_clr(struct super_block *sb); -+int au_xino_set(struct super_block *sb, struct au_opt_xino *xiopt, int remount); -+struct file *au_xino_def(struct super_block *sb); -+int au_xino_init_br(struct super_block *sb, struct au_branch *br, ino_t hino, -+ struct path *base); -+ -+ino_t au_xino_new_ino(struct super_block *sb); -+void au_xino_delete_inode(struct inode *inode, const int unlinked); -+ -+void au_xinondir_leave(struct super_block *sb, aufs_bindex_t bindex, -+ ino_t h_ino, int idx); -+int au_xinondir_enter(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, -+ int *idx); -+ -+int au_xino_path(struct seq_file *seq, struct file *file); -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* @idx is signed to accept -1 meaning the first file */ -+static inline struct file *au_xino_file(struct au_xino *xi, int idx) -+{ -+ struct file *file; -+ -+ file = NULL; -+ if (!xi) -+ goto out; -+ -+ if (idx >= 0) { -+ if (idx < xi->xi_nfile) -+ file = xi->xi_file[idx]; -+ } else -+ file = au_xino_file1(xi); -+ -+out: -+ return file; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* Superblock to branch */ -+static inline -+aufs_bindex_t au_sbr_id(struct super_block *sb, aufs_bindex_t bindex) -+{ -+ return au_sbr(sb, bindex)->br_id; -+} -+ -+static inline -+struct vfsmount *au_sbr_mnt(struct super_block *sb, aufs_bindex_t bindex) -+{ -+ return au_br_mnt(au_sbr(sb, bindex)); -+} -+ -+static inline -+struct super_block *au_sbr_sb(struct super_block *sb, aufs_bindex_t bindex) -+{ -+ return au_br_sb(au_sbr(sb, bindex)); -+} -+ -+static inline int au_sbr_perm(struct super_block *sb, aufs_bindex_t bindex) -+{ -+ return au_sbr(sb, bindex)->br_perm; -+} -+ -+static inline int au_sbr_whable(struct super_block *sb, aufs_bindex_t bindex) -+{ -+ return au_br_whable(au_sbr_perm(sb, bindex)); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+#define wbr_wh_read_lock(wbr) au_rw_read_lock(&(wbr)->wbr_wh_rwsem) -+#define wbr_wh_write_lock(wbr) au_rw_write_lock(&(wbr)->wbr_wh_rwsem) -+#define wbr_wh_read_trylock(wbr) au_rw_read_trylock(&(wbr)->wbr_wh_rwsem) -+#define wbr_wh_write_trylock(wbr) au_rw_write_trylock(&(wbr)->wbr_wh_rwsem) -+/* -+#define wbr_wh_read_trylock_nested(wbr) \ -+ au_rw_read_trylock_nested(&(wbr)->wbr_wh_rwsem) -+#define wbr_wh_write_trylock_nested(wbr) \ -+ au_rw_write_trylock_nested(&(wbr)->wbr_wh_rwsem) -+*/ -+ -+#define wbr_wh_read_unlock(wbr) au_rw_read_unlock(&(wbr)->wbr_wh_rwsem) -+#define wbr_wh_write_unlock(wbr) au_rw_write_unlock(&(wbr)->wbr_wh_rwsem) -+#define wbr_wh_downgrade_lock(wbr) au_rw_dgrade_lock(&(wbr)->wbr_wh_rwsem) -+ -+#define WbrWhMustNoWaiters(wbr) AuRwMustNoWaiters(&(wbr)->wbr_wh_rwsem) -+#define WbrWhMustAnyLock(wbr) AuRwMustAnyLock(&(wbr)->wbr_wh_rwsem) -+#define WbrWhMustWriteLock(wbr) AuRwMustWriteLock(&(wbr)->wbr_wh_rwsem) -+ -+/* ---------------------------------------------------------------------- */ -+ -+#ifdef CONFIG_AUFS_FHSM -+static inline void au_br_fhsm_init(struct au_br_fhsm *brfhsm) -+{ -+ mutex_init(&brfhsm->bf_lock); -+ brfhsm->bf_jiffy = 0; -+ brfhsm->bf_readable = 0; -+} -+ -+static inline void au_br_fhsm_fin(struct au_br_fhsm *brfhsm) -+{ -+ mutex_destroy(&brfhsm->bf_lock); -+} -+#else -+AuStubVoid(au_br_fhsm_init, struct au_br_fhsm *brfhsm) -+AuStubVoid(au_br_fhsm_fin, struct au_br_fhsm *brfhsm) -+#endif -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_BRANCH_H__ */ -diff -Nurp linux-5.6.3/fs/aufs/cpup.c linux-5.6.3-aufs/fs/aufs/cpup.c ---- linux-5.6.3/fs/aufs/cpup.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/cpup.c 2020-04-10 12:40:52.188049315 +0300 -@@ -0,0 +1,1445 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * copy-up functions, see wbr_policy.c for copy-down -+ */ -+ -+#include -+#include -+#include -+#include "aufs.h" -+ -+void au_cpup_attr_flags(struct inode *dst, unsigned int iflags) -+{ -+ const unsigned int mask = S_DEAD | S_SWAPFILE | S_PRIVATE -+ | S_NOATIME | S_NOCMTIME | S_AUTOMOUNT; -+ -+ BUILD_BUG_ON(sizeof(iflags) != sizeof(dst->i_flags)); -+ -+ dst->i_flags |= iflags & ~mask; -+ if (au_test_fs_notime(dst->i_sb)) -+ dst->i_flags |= S_NOATIME | S_NOCMTIME; -+} -+ -+void au_cpup_attr_timesizes(struct inode *inode) -+{ -+ struct inode *h_inode; -+ -+ h_inode = au_h_iptr(inode, au_ibtop(inode)); -+ fsstack_copy_attr_times(inode, h_inode); -+ fsstack_copy_inode_size(inode, h_inode); -+} -+ -+void au_cpup_attr_nlink(struct inode *inode, int force) -+{ -+ struct inode *h_inode; -+ struct super_block *sb; -+ aufs_bindex_t bindex, bbot; -+ -+ sb = inode->i_sb; -+ bindex = au_ibtop(inode); -+ h_inode = au_h_iptr(inode, bindex); -+ if (!force -+ && !S_ISDIR(h_inode->i_mode) -+ && au_opt_test(au_mntflags(sb), PLINK) -+ && au_plink_test(inode)) -+ return; -+ -+ /* -+ * 0 can happen in revalidating. -+ * h_inode->i_mutex may not be held here, but it is harmless since once -+ * i_nlink reaches 0, it will never become positive except O_TMPFILE -+ * case. -+ * todo: O_TMPFILE+linkat(AT_SYMLINK_FOLLOW) bypassing aufs may cause -+ * the incorrect link count. -+ */ -+ set_nlink(inode, h_inode->i_nlink); -+ -+ /* -+ * fewer nlink makes find(1) noisy, but larger nlink doesn't. -+ * it may includes whplink directory. -+ */ -+ if (S_ISDIR(h_inode->i_mode)) { -+ bbot = au_ibbot(inode); -+ for (bindex++; bindex <= bbot; bindex++) { -+ h_inode = au_h_iptr(inode, bindex); -+ if (h_inode) -+ au_add_nlink(inode, h_inode); -+ } -+ } -+} -+ -+void au_cpup_attr_changeable(struct inode *inode) -+{ -+ struct inode *h_inode; -+ -+ h_inode = au_h_iptr(inode, au_ibtop(inode)); -+ inode->i_mode = h_inode->i_mode; -+ inode->i_uid = h_inode->i_uid; -+ inode->i_gid = h_inode->i_gid; -+ au_cpup_attr_timesizes(inode); -+ au_cpup_attr_flags(inode, h_inode->i_flags); -+} -+ -+void au_cpup_igen(struct inode *inode, struct inode *h_inode) -+{ -+ struct au_iinfo *iinfo = au_ii(inode); -+ -+ IiMustWriteLock(inode); -+ -+ iinfo->ii_higen = h_inode->i_generation; -+ iinfo->ii_hsb1 = h_inode->i_sb; -+} -+ -+void au_cpup_attr_all(struct inode *inode, int force) -+{ -+ struct inode *h_inode; -+ -+ h_inode = au_h_iptr(inode, au_ibtop(inode)); -+ au_cpup_attr_changeable(inode); -+ if (inode->i_nlink > 0) -+ au_cpup_attr_nlink(inode, force); -+ inode->i_rdev = h_inode->i_rdev; -+ inode->i_blkbits = h_inode->i_blkbits; -+ au_cpup_igen(inode, h_inode); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* Note: dt_dentry and dt_h_dentry are not dget/dput-ed */ -+ -+/* keep the timestamps of the parent dir when cpup */ -+void au_dtime_store(struct au_dtime *dt, struct dentry *dentry, -+ struct path *h_path) -+{ -+ struct inode *h_inode; -+ -+ dt->dt_dentry = dentry; -+ dt->dt_h_path = *h_path; -+ h_inode = d_inode(h_path->dentry); -+ dt->dt_atime = h_inode->i_atime; -+ dt->dt_mtime = h_inode->i_mtime; -+ /* smp_mb(); */ -+} -+ -+void au_dtime_revert(struct au_dtime *dt) -+{ -+ struct iattr attr; -+ int err; -+ -+ attr.ia_atime = dt->dt_atime; -+ attr.ia_mtime = dt->dt_mtime; -+ attr.ia_valid = ATTR_FORCE | ATTR_MTIME | ATTR_MTIME_SET -+ | ATTR_ATIME | ATTR_ATIME_SET; -+ -+ /* no delegation since this is a directory */ -+ err = vfsub_notify_change(&dt->dt_h_path, &attr, /*delegated*/NULL); -+ if (unlikely(err)) -+ pr_warn("restoring timestamps failed(%d). ignored\n", err); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* internal use only */ -+struct au_cpup_reg_attr { -+ int valid; -+ struct kstat st; -+ unsigned int iflags; /* inode->i_flags */ -+}; -+ -+static noinline_for_stack -+int cpup_iattr(struct dentry *dst, aufs_bindex_t bindex, struct dentry *h_src, -+ struct au_cpup_reg_attr *h_src_attr) -+{ -+ int err, sbits, icex; -+ unsigned int mnt_flags; -+ unsigned char verbose; -+ struct iattr ia; -+ struct path h_path; -+ struct inode *h_isrc, *h_idst; -+ struct kstat *h_st; -+ struct au_branch *br; -+ -+ h_path.dentry = au_h_dptr(dst, bindex); -+ h_idst = d_inode(h_path.dentry); -+ br = au_sbr(dst->d_sb, bindex); -+ h_path.mnt = au_br_mnt(br); -+ h_isrc = d_inode(h_src); -+ ia.ia_valid = ATTR_FORCE | ATTR_UID | ATTR_GID -+ | ATTR_ATIME | ATTR_MTIME -+ | ATTR_ATIME_SET | ATTR_MTIME_SET; -+ if (h_src_attr && h_src_attr->valid) { -+ h_st = &h_src_attr->st; -+ ia.ia_uid = h_st->uid; -+ ia.ia_gid = h_st->gid; -+ ia.ia_atime = h_st->atime; -+ ia.ia_mtime = h_st->mtime; -+ if (h_idst->i_mode != h_st->mode -+ && !S_ISLNK(h_idst->i_mode)) { -+ ia.ia_valid |= ATTR_MODE; -+ ia.ia_mode = h_st->mode; -+ } -+ sbits = !!(h_st->mode & (S_ISUID | S_ISGID)); -+ au_cpup_attr_flags(h_idst, h_src_attr->iflags); -+ } else { -+ ia.ia_uid = h_isrc->i_uid; -+ ia.ia_gid = h_isrc->i_gid; -+ ia.ia_atime = h_isrc->i_atime; -+ ia.ia_mtime = h_isrc->i_mtime; -+ if (h_idst->i_mode != h_isrc->i_mode -+ && !S_ISLNK(h_idst->i_mode)) { -+ ia.ia_valid |= ATTR_MODE; -+ ia.ia_mode = h_isrc->i_mode; -+ } -+ sbits = !!(h_isrc->i_mode & (S_ISUID | S_ISGID)); -+ au_cpup_attr_flags(h_idst, h_isrc->i_flags); -+ } -+ /* no delegation since it is just created */ -+ err = vfsub_notify_change(&h_path, &ia, /*delegated*/NULL); -+ -+ /* is this nfs only? */ -+ if (!err && sbits && au_test_nfs(h_path.dentry->d_sb)) { -+ ia.ia_valid = ATTR_FORCE | ATTR_MODE; -+ ia.ia_mode = h_isrc->i_mode; -+ err = vfsub_notify_change(&h_path, &ia, /*delegated*/NULL); -+ } -+ -+ icex = br->br_perm & AuBrAttr_ICEX; -+ if (!err) { -+ mnt_flags = au_mntflags(dst->d_sb); -+ verbose = !!au_opt_test(mnt_flags, VERBOSE); -+ err = au_cpup_xattr(h_path.dentry, h_src, icex, verbose); -+ } -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int au_do_copy_file(struct file *dst, struct file *src, loff_t len, -+ char *buf, unsigned long blksize) -+{ -+ int err; -+ size_t sz, rbytes, wbytes; -+ unsigned char all_zero; -+ char *p, *zp; -+ struct inode *h_inode; -+ /* reduce stack usage */ -+ struct iattr *ia; -+ -+ zp = page_address(ZERO_PAGE(0)); -+ if (unlikely(!zp)) -+ return -ENOMEM; /* possible? */ -+ -+ err = 0; -+ all_zero = 0; -+ while (len) { -+ AuDbg("len %lld\n", len); -+ sz = blksize; -+ if (len < blksize) -+ sz = len; -+ -+ rbytes = 0; -+ /* todo: signal_pending? */ -+ while (!rbytes || err == -EAGAIN || err == -EINTR) { -+ rbytes = vfsub_read_k(src, buf, sz, &src->f_pos); -+ err = rbytes; -+ } -+ if (unlikely(err < 0)) -+ break; -+ -+ all_zero = 0; -+ if (len >= rbytes && rbytes == blksize) -+ all_zero = !memcmp(buf, zp, rbytes); -+ if (!all_zero) { -+ wbytes = rbytes; -+ p = buf; -+ while (wbytes) { -+ size_t b; -+ -+ b = vfsub_write_k(dst, p, wbytes, &dst->f_pos); -+ err = b; -+ /* todo: signal_pending? */ -+ if (unlikely(err == -EAGAIN || err == -EINTR)) -+ continue; -+ if (unlikely(err < 0)) -+ break; -+ wbytes -= b; -+ p += b; -+ } -+ if (unlikely(err < 0)) -+ break; -+ } else { -+ loff_t res; -+ -+ AuLabel(hole); -+ res = vfsub_llseek(dst, rbytes, SEEK_CUR); -+ err = res; -+ if (unlikely(res < 0)) -+ break; -+ } -+ len -= rbytes; -+ err = 0; -+ } -+ -+ /* the last block may be a hole */ -+ if (!err && all_zero) { -+ AuLabel(last hole); -+ -+ err = 1; -+ if (au_test_nfs(dst->f_path.dentry->d_sb)) { -+ /* nfs requires this step to make last hole */ -+ /* is this only nfs? */ -+ do { -+ /* todo: signal_pending? */ -+ err = vfsub_write_k(dst, "\0", 1, &dst->f_pos); -+ } while (err == -EAGAIN || err == -EINTR); -+ if (err == 1) -+ dst->f_pos--; -+ } -+ -+ if (err == 1) { -+ ia = (void *)buf; -+ ia->ia_size = dst->f_pos; -+ ia->ia_valid = ATTR_SIZE | ATTR_FILE; -+ ia->ia_file = dst; -+ h_inode = file_inode(dst); -+ inode_lock_nested(h_inode, AuLsc_I_CHILD2); -+ /* no delegation since it is just created */ -+ err = vfsub_notify_change(&dst->f_path, ia, -+ /*delegated*/NULL); -+ inode_unlock(h_inode); -+ } -+ } -+ -+ return err; -+} -+ -+int au_copy_file(struct file *dst, struct file *src, loff_t len) -+{ -+ int err; -+ unsigned long blksize; -+ unsigned char do_kfree; -+ char *buf; -+ struct super_block *h_sb; -+ -+ err = -ENOMEM; -+ h_sb = file_inode(dst)->i_sb; -+ blksize = h_sb->s_blocksize; -+ if (!blksize || PAGE_SIZE < blksize) -+ blksize = PAGE_SIZE; -+ AuDbg("blksize %lu\n", blksize); -+ do_kfree = (blksize != PAGE_SIZE && blksize >= sizeof(struct iattr *)); -+ if (do_kfree) -+ buf = kmalloc(blksize, GFP_NOFS); -+ else -+ buf = (void *)__get_free_page(GFP_NOFS); -+ if (unlikely(!buf)) -+ goto out; -+ -+ if (len > (1 << 22)) -+ AuDbg("copying a large file %lld\n", (long long)len); -+ -+ src->f_pos = 0; -+ dst->f_pos = 0; -+ err = au_do_copy_file(dst, src, len, buf, blksize); -+ if (do_kfree) { -+ AuDebugOn(!au_kfree_do_sz_test(blksize)); -+ au_kfree_do_rcu(buf); -+ } else -+ free_page((unsigned long)buf); -+ -+out: -+ return err; -+} -+ -+static int au_do_copy(struct file *dst, struct file *src, loff_t len) -+{ -+ int err; -+ struct super_block *h_src_sb; -+ struct inode *h_src_inode; -+ -+ h_src_inode = file_inode(src); -+ h_src_sb = h_src_inode->i_sb; -+ -+ /* XFS acquires inode_lock */ -+ if (!au_test_xfs(h_src_sb)) -+ err = au_copy_file(dst, src, len); -+ else { -+ inode_unlock_shared(h_src_inode); -+ err = au_copy_file(dst, src, len); -+ inode_lock_shared_nested(h_src_inode, AuLsc_I_CHILD); -+ } -+ -+ return err; -+} -+ -+static int au_clone_or_copy(struct file *dst, struct file *src, loff_t len) -+{ -+ int err; -+ loff_t lo; -+ struct super_block *h_src_sb; -+ struct inode *h_src_inode; -+ -+ h_src_inode = file_inode(src); -+ h_src_sb = h_src_inode->i_sb; -+ if (h_src_sb != file_inode(dst)->i_sb -+ || !dst->f_op->remap_file_range) { -+ err = au_do_copy(dst, src, len); -+ goto out; -+ } -+ -+ if (!au_test_nfs(h_src_sb)) { -+ inode_unlock_shared(h_src_inode); -+ lo = vfsub_clone_file_range(src, dst, len); -+ inode_lock_shared_nested(h_src_inode, AuLsc_I_CHILD); -+ } else -+ lo = vfsub_clone_file_range(src, dst, len); -+ if (lo == len) { -+ err = 0; -+ goto out; /* success */ -+ } else if (lo >= 0) -+ /* todo: possible? */ -+ /* paritially succeeded */ -+ AuDbg("lo %lld, len %lld. Retrying.\n", lo, len); -+ else if (lo != -EOPNOTSUPP) { -+ /* older XFS has a condition in cloning */ -+ err = lo; -+ goto out; -+ } -+ -+ /* the backend fs on NFS may not support cloning */ -+ err = au_do_copy(dst, src, len); -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+/* -+ * to support a sparse file which is opened with O_APPEND, -+ * we need to close the file. -+ */ -+static int au_cp_regular(struct au_cp_generic *cpg) -+{ -+ int err, i; -+ enum { SRC, DST }; -+ struct { -+ aufs_bindex_t bindex; -+ unsigned int flags; -+ struct dentry *dentry; -+ int force_wr; -+ struct file *file; -+ } *f, file[] = { -+ { -+ .bindex = cpg->bsrc, -+ .flags = O_RDONLY | O_NOATIME | O_LARGEFILE, -+ }, -+ { -+ .bindex = cpg->bdst, -+ .flags = O_WRONLY | O_NOATIME | O_LARGEFILE, -+ .force_wr = !!au_ftest_cpup(cpg->flags, RWDST), -+ } -+ }; -+ struct au_branch *br; -+ struct super_block *sb, *h_src_sb; -+ struct inode *h_src_inode; -+ struct task_struct *tsk = current; -+ -+ /* bsrc branch can be ro/rw. */ -+ sb = cpg->dentry->d_sb; -+ f = file; -+ for (i = 0; i < 2; i++, f++) { -+ f->dentry = au_h_dptr(cpg->dentry, f->bindex); -+ f->file = au_h_open(cpg->dentry, f->bindex, f->flags, -+ /*file*/NULL, f->force_wr); -+ if (IS_ERR(f->file)) { -+ err = PTR_ERR(f->file); -+ if (i == SRC) -+ goto out; -+ else -+ goto out_src; -+ } -+ } -+ -+ /* try stopping to update while we copyup */ -+ h_src_inode = d_inode(file[SRC].dentry); -+ h_src_sb = h_src_inode->i_sb; -+ if (!au_test_nfs(h_src_sb)) -+ IMustLock(h_src_inode); -+ err = au_clone_or_copy(file[DST].file, file[SRC].file, cpg->len); -+ -+ /* i wonder if we had O_NO_DELAY_FPUT flag */ -+ if (tsk->flags & PF_KTHREAD) -+ __fput_sync(file[DST].file); -+ else { -+ /* it happened actually */ -+ fput(file[DST].file); -+ /* -+ * too bad. -+ * we have to call both since we don't know which place the file -+ * was added to. -+ */ -+ task_work_run(); -+ flush_delayed_fput(); -+ } -+ br = au_sbr(sb, file[DST].bindex); -+ au_lcnt_dec(&br->br_nfiles); -+ -+out_src: -+ fput(file[SRC].file); -+ br = au_sbr(sb, file[SRC].bindex); -+ au_lcnt_dec(&br->br_nfiles); -+out: -+ return err; -+} -+ -+static int au_do_cpup_regular(struct au_cp_generic *cpg, -+ struct au_cpup_reg_attr *h_src_attr) -+{ -+ int err, rerr; -+ loff_t l; -+ struct path h_path; -+ struct inode *h_src_inode, *h_dst_inode; -+ -+ err = 0; -+ h_src_inode = au_h_iptr(d_inode(cpg->dentry), cpg->bsrc); -+ l = i_size_read(h_src_inode); -+ if (cpg->len == -1 || l < cpg->len) -+ cpg->len = l; -+ if (cpg->len) { -+ /* try stopping to update while we are referencing */ -+ inode_lock_shared_nested(h_src_inode, AuLsc_I_CHILD); -+ au_pin_hdir_unlock(cpg->pin); -+ -+ h_path.dentry = au_h_dptr(cpg->dentry, cpg->bsrc); -+ h_path.mnt = au_sbr_mnt(cpg->dentry->d_sb, cpg->bsrc); -+ h_src_attr->iflags = h_src_inode->i_flags; -+ if (!au_test_nfs(h_src_inode->i_sb)) -+ err = vfsub_getattr(&h_path, &h_src_attr->st); -+ else { -+ inode_unlock_shared(h_src_inode); -+ err = vfsub_getattr(&h_path, &h_src_attr->st); -+ inode_lock_shared_nested(h_src_inode, AuLsc_I_CHILD); -+ } -+ if (unlikely(err)) { -+ inode_unlock_shared(h_src_inode); -+ goto out; -+ } -+ h_src_attr->valid = 1; -+ if (!au_test_nfs(h_src_inode->i_sb)) { -+ err = au_cp_regular(cpg); -+ inode_unlock_shared(h_src_inode); -+ } else { -+ inode_unlock_shared(h_src_inode); -+ err = au_cp_regular(cpg); -+ } -+ rerr = au_pin_hdir_relock(cpg->pin); -+ if (!err && rerr) -+ err = rerr; -+ } -+ if (!err && (h_src_inode->i_state & I_LINKABLE)) { -+ h_path.dentry = au_h_dptr(cpg->dentry, cpg->bdst); -+ h_dst_inode = d_inode(h_path.dentry); -+ spin_lock(&h_dst_inode->i_lock); -+ h_dst_inode->i_state |= I_LINKABLE; -+ spin_unlock(&h_dst_inode->i_lock); -+ } -+ -+out: -+ return err; -+} -+ -+static int au_do_cpup_symlink(struct path *h_path, struct dentry *h_src, -+ struct inode *h_dir) -+{ -+ int err, symlen; -+ mm_segment_t old_fs; -+ union { -+ char *k; -+ char __user *u; -+ } sym; -+ -+ err = -ENOMEM; -+ sym.k = (void *)__get_free_page(GFP_NOFS); -+ if (unlikely(!sym.k)) -+ goto out; -+ -+ /* unnecessary to support mmap_sem since symlink is not mmap-able */ -+ old_fs = get_fs(); -+ set_fs(KERNEL_DS); -+ symlen = vfs_readlink(h_src, sym.u, PATH_MAX); -+ err = symlen; -+ set_fs(old_fs); -+ -+ if (symlen > 0) { -+ sym.k[symlen] = 0; -+ err = vfsub_symlink(h_dir, h_path, sym.k); -+ } -+ free_page((unsigned long)sym.k); -+ -+out: -+ return err; -+} -+ -+/* -+ * regardless 'acl' option, reset all ACL. -+ * All ACL will be copied up later from the original entry on the lower branch. -+ */ -+static int au_reset_acl(struct inode *h_dir, struct path *h_path, umode_t mode) -+{ -+ int err; -+ struct dentry *h_dentry; -+ struct inode *h_inode; -+ -+ h_dentry = h_path->dentry; -+ h_inode = d_inode(h_dentry); -+ /* forget_all_cached_acls(h_inode)); */ -+ err = vfsub_removexattr(h_dentry, XATTR_NAME_POSIX_ACL_ACCESS); -+ AuTraceErr(err); -+ if (err == -EOPNOTSUPP) -+ err = 0; -+ if (!err) -+ err = vfsub_acl_chmod(h_inode, mode); -+ -+ AuTraceErr(err); -+ return err; -+} -+ -+static int au_do_cpup_dir(struct au_cp_generic *cpg, struct dentry *dst_parent, -+ struct inode *h_dir, struct path *h_path) -+{ -+ int err; -+ struct inode *dir, *inode; -+ -+ err = vfsub_removexattr(h_path->dentry, XATTR_NAME_POSIX_ACL_DEFAULT); -+ AuTraceErr(err); -+ if (err == -EOPNOTSUPP) -+ err = 0; -+ if (unlikely(err)) -+ goto out; -+ -+ /* -+ * strange behaviour from the users view, -+ * particularly setattr case -+ */ -+ dir = d_inode(dst_parent); -+ if (au_ibtop(dir) == cpg->bdst) -+ au_cpup_attr_nlink(dir, /*force*/1); -+ inode = d_inode(cpg->dentry); -+ au_cpup_attr_nlink(inode, /*force*/1); -+ -+out: -+ return err; -+} -+ -+static noinline_for_stack -+int cpup_entry(struct au_cp_generic *cpg, struct dentry *dst_parent, -+ struct au_cpup_reg_attr *h_src_attr) -+{ -+ int err; -+ umode_t mode; -+ unsigned int mnt_flags; -+ unsigned char isdir, isreg, force; -+ const unsigned char do_dt = !!au_ftest_cpup(cpg->flags, DTIME); -+ struct au_dtime dt; -+ struct path h_path; -+ struct dentry *h_src, *h_dst, *h_parent; -+ struct inode *h_inode, *h_dir; -+ struct super_block *sb; -+ -+ /* bsrc branch can be ro/rw. */ -+ h_src = au_h_dptr(cpg->dentry, cpg->bsrc); -+ h_inode = d_inode(h_src); -+ AuDebugOn(h_inode != au_h_iptr(d_inode(cpg->dentry), cpg->bsrc)); -+ -+ /* try stopping to be referenced while we are creating */ -+ h_dst = au_h_dptr(cpg->dentry, cpg->bdst); -+ if (au_ftest_cpup(cpg->flags, RENAME)) -+ AuDebugOn(strncmp(h_dst->d_name.name, AUFS_WH_PFX, -+ AUFS_WH_PFX_LEN)); -+ h_parent = h_dst->d_parent; /* dir inode is locked */ -+ h_dir = d_inode(h_parent); -+ IMustLock(h_dir); -+ AuDebugOn(h_parent != h_dst->d_parent); -+ -+ sb = cpg->dentry->d_sb; -+ h_path.mnt = au_sbr_mnt(sb, cpg->bdst); -+ if (do_dt) { -+ h_path.dentry = h_parent; -+ au_dtime_store(&dt, dst_parent, &h_path); -+ } -+ h_path.dentry = h_dst; -+ -+ isreg = 0; -+ isdir = 0; -+ mode = h_inode->i_mode; -+ switch (mode & S_IFMT) { -+ case S_IFREG: -+ isreg = 1; -+ err = vfsub_create(h_dir, &h_path, 0600, /*want_excl*/true); -+ if (!err) -+ err = au_do_cpup_regular(cpg, h_src_attr); -+ break; -+ case S_IFDIR: -+ isdir = 1; -+ err = vfsub_mkdir(h_dir, &h_path, mode); -+ if (!err) -+ err = au_do_cpup_dir(cpg, dst_parent, h_dir, &h_path); -+ break; -+ case S_IFLNK: -+ err = au_do_cpup_symlink(&h_path, h_src, h_dir); -+ break; -+ case S_IFCHR: -+ case S_IFBLK: -+ AuDebugOn(!capable(CAP_MKNOD)); -+ /*FALLTHROUGH*/ -+ case S_IFIFO: -+ case S_IFSOCK: -+ err = vfsub_mknod(h_dir, &h_path, mode, h_inode->i_rdev); -+ break; -+ default: -+ AuIOErr("Unknown inode type 0%o\n", mode); -+ err = -EIO; -+ } -+ if (!err) -+ err = au_reset_acl(h_dir, &h_path, mode); -+ -+ mnt_flags = au_mntflags(sb); -+ if (!au_opt_test(mnt_flags, UDBA_NONE) -+ && !isdir -+ && au_opt_test(mnt_flags, XINO) -+ && (h_inode->i_nlink == 1 -+ || (h_inode->i_state & I_LINKABLE)) -+ /* todo: unnecessary? */ -+ /* && d_inode(cpg->dentry)->i_nlink == 1 */ -+ && cpg->bdst < cpg->bsrc -+ && !au_ftest_cpup(cpg->flags, KEEPLINO)) -+ au_xino_write(sb, cpg->bsrc, h_inode->i_ino, /*ino*/0); -+ /* ignore this error */ -+ -+ if (!err) { -+ force = 0; -+ if (isreg) { -+ force = !!cpg->len; -+ if (cpg->len == -1) -+ force = !!i_size_read(h_inode); -+ } -+ au_fhsm_wrote(sb, cpg->bdst, force); -+ } -+ -+ if (do_dt) -+ au_dtime_revert(&dt); -+ return err; -+} -+ -+static int au_do_ren_after_cpup(struct au_cp_generic *cpg, struct path *h_path) -+{ -+ int err; -+ struct dentry *dentry, *h_dentry, *h_parent, *parent; -+ struct inode *h_dir; -+ aufs_bindex_t bdst; -+ -+ dentry = cpg->dentry; -+ bdst = cpg->bdst; -+ h_dentry = au_h_dptr(dentry, bdst); -+ if (!au_ftest_cpup(cpg->flags, OVERWRITE)) { -+ dget(h_dentry); -+ au_set_h_dptr(dentry, bdst, NULL); -+ err = au_lkup_neg(dentry, bdst, /*wh*/0); -+ if (!err) -+ h_path->dentry = dget(au_h_dptr(dentry, bdst)); -+ au_set_h_dptr(dentry, bdst, h_dentry); -+ } else { -+ err = 0; -+ parent = dget_parent(dentry); -+ h_parent = au_h_dptr(parent, bdst); -+ dput(parent); -+ h_path->dentry = vfsub_lkup_one(&dentry->d_name, h_parent); -+ if (IS_ERR(h_path->dentry)) -+ err = PTR_ERR(h_path->dentry); -+ } -+ if (unlikely(err)) -+ goto out; -+ -+ h_parent = h_dentry->d_parent; /* dir inode is locked */ -+ h_dir = d_inode(h_parent); -+ IMustLock(h_dir); -+ AuDbg("%pd %pd\n", h_dentry, h_path->dentry); -+ /* no delegation since it is just created */ -+ err = vfsub_rename(h_dir, h_dentry, h_dir, h_path, /*delegated*/NULL, -+ /*flags*/0); -+ dput(h_path->dentry); -+ -+out: -+ return err; -+} -+ -+/* -+ * copyup the @dentry from @bsrc to @bdst. -+ * the caller must set the both of lower dentries. -+ * @len is for truncating when it is -1 copyup the entire file. -+ * in link/rename cases, @dst_parent may be different from the real one. -+ * basic->bsrc can be larger than basic->bdst. -+ * aufs doesn't touch the credential so -+ * security_inode_copy_up{,_xattr}() are unnecessary. -+ */ -+static int au_cpup_single(struct au_cp_generic *cpg, struct dentry *dst_parent) -+{ -+ int err, rerr; -+ aufs_bindex_t old_ibtop; -+ unsigned char isdir, plink; -+ struct dentry *h_src, *h_dst, *h_parent; -+ struct inode *dst_inode, *h_dir, *inode, *delegated, *src_inode; -+ struct super_block *sb; -+ struct au_branch *br; -+ /* to reduce stack size */ -+ struct { -+ struct au_dtime dt; -+ struct path h_path; -+ struct au_cpup_reg_attr h_src_attr; -+ } *a; -+ -+ err = -ENOMEM; -+ a = kmalloc(sizeof(*a), GFP_NOFS); -+ if (unlikely(!a)) -+ goto out; -+ a->h_src_attr.valid = 0; -+ -+ sb = cpg->dentry->d_sb; -+ br = au_sbr(sb, cpg->bdst); -+ a->h_path.mnt = au_br_mnt(br); -+ h_dst = au_h_dptr(cpg->dentry, cpg->bdst); -+ h_parent = h_dst->d_parent; /* dir inode is locked */ -+ h_dir = d_inode(h_parent); -+ IMustLock(h_dir); -+ -+ h_src = au_h_dptr(cpg->dentry, cpg->bsrc); -+ inode = d_inode(cpg->dentry); -+ -+ if (!dst_parent) -+ dst_parent = dget_parent(cpg->dentry); -+ else -+ dget(dst_parent); -+ -+ plink = !!au_opt_test(au_mntflags(sb), PLINK); -+ dst_inode = au_h_iptr(inode, cpg->bdst); -+ if (dst_inode) { -+ if (unlikely(!plink)) { -+ err = -EIO; -+ AuIOErr("hi%lu(i%lu) exists on b%d " -+ "but plink is disabled\n", -+ dst_inode->i_ino, inode->i_ino, cpg->bdst); -+ goto out_parent; -+ } -+ -+ if (dst_inode->i_nlink) { -+ const int do_dt = au_ftest_cpup(cpg->flags, DTIME); -+ -+ h_src = au_plink_lkup(inode, cpg->bdst); -+ err = PTR_ERR(h_src); -+ if (IS_ERR(h_src)) -+ goto out_parent; -+ if (unlikely(d_is_negative(h_src))) { -+ err = -EIO; -+ AuIOErr("i%lu exists on b%d " -+ "but not pseudo-linked\n", -+ inode->i_ino, cpg->bdst); -+ dput(h_src); -+ goto out_parent; -+ } -+ -+ if (do_dt) { -+ a->h_path.dentry = h_parent; -+ au_dtime_store(&a->dt, dst_parent, &a->h_path); -+ } -+ -+ a->h_path.dentry = h_dst; -+ delegated = NULL; -+ err = vfsub_link(h_src, h_dir, &a->h_path, &delegated); -+ if (!err && au_ftest_cpup(cpg->flags, RENAME)) -+ err = au_do_ren_after_cpup(cpg, &a->h_path); -+ if (do_dt) -+ au_dtime_revert(&a->dt); -+ if (unlikely(err == -EWOULDBLOCK)) { -+ pr_warn("cannot retry for NFSv4 delegation" -+ " for an internal link\n"); -+ iput(delegated); -+ } -+ dput(h_src); -+ goto out_parent; -+ } else -+ /* todo: cpup_wh_file? */ -+ /* udba work */ -+ au_update_ibrange(inode, /*do_put_zero*/1); -+ } -+ -+ isdir = S_ISDIR(inode->i_mode); -+ old_ibtop = au_ibtop(inode); -+ err = cpup_entry(cpg, dst_parent, &a->h_src_attr); -+ if (unlikely(err)) -+ goto out_rev; -+ dst_inode = d_inode(h_dst); -+ inode_lock_nested(dst_inode, AuLsc_I_CHILD2); -+ /* todo: necessary? */ -+ /* au_pin_hdir_unlock(cpg->pin); */ -+ -+ err = cpup_iattr(cpg->dentry, cpg->bdst, h_src, &a->h_src_attr); -+ if (unlikely(err)) { -+ /* todo: necessary? */ -+ /* au_pin_hdir_relock(cpg->pin); */ /* ignore an error */ -+ inode_unlock(dst_inode); -+ goto out_rev; -+ } -+ -+ if (cpg->bdst < old_ibtop) { -+ if (S_ISREG(inode->i_mode)) { -+ err = au_dy_iaop(inode, cpg->bdst, dst_inode); -+ if (unlikely(err)) { -+ /* ignore an error */ -+ /* au_pin_hdir_relock(cpg->pin); */ -+ inode_unlock(dst_inode); -+ goto out_rev; -+ } -+ } -+ au_set_ibtop(inode, cpg->bdst); -+ } else -+ au_set_ibbot(inode, cpg->bdst); -+ au_set_h_iptr(inode, cpg->bdst, au_igrab(dst_inode), -+ au_hi_flags(inode, isdir)); -+ -+ /* todo: necessary? */ -+ /* err = au_pin_hdir_relock(cpg->pin); */ -+ inode_unlock(dst_inode); -+ if (unlikely(err)) -+ goto out_rev; -+ -+ src_inode = d_inode(h_src); -+ if (!isdir -+ && (src_inode->i_nlink > 1 -+ || src_inode->i_state & I_LINKABLE) -+ && plink) -+ au_plink_append(inode, cpg->bdst, h_dst); -+ -+ if (au_ftest_cpup(cpg->flags, RENAME)) { -+ a->h_path.dentry = h_dst; -+ err = au_do_ren_after_cpup(cpg, &a->h_path); -+ } -+ if (!err) -+ goto out_parent; /* success */ -+ -+ /* revert */ -+out_rev: -+ a->h_path.dentry = h_parent; -+ au_dtime_store(&a->dt, dst_parent, &a->h_path); -+ a->h_path.dentry = h_dst; -+ rerr = 0; -+ if (d_is_positive(h_dst)) { -+ if (!isdir) { -+ /* no delegation since it is just created */ -+ rerr = vfsub_unlink(h_dir, &a->h_path, -+ /*delegated*/NULL, /*force*/0); -+ } else -+ rerr = vfsub_rmdir(h_dir, &a->h_path); -+ } -+ au_dtime_revert(&a->dt); -+ if (rerr) { -+ AuIOErr("failed removing broken entry(%d, %d)\n", err, rerr); -+ err = -EIO; -+ } -+out_parent: -+ dput(dst_parent); -+ au_kfree_rcu(a); -+out: -+ return err; -+} -+ -+#if 0 /* reserved */ -+struct au_cpup_single_args { -+ int *errp; -+ struct au_cp_generic *cpg; -+ struct dentry *dst_parent; -+}; -+ -+static void au_call_cpup_single(void *args) -+{ -+ struct au_cpup_single_args *a = args; -+ -+ au_pin_hdir_acquire_nest(a->cpg->pin); -+ *a->errp = au_cpup_single(a->cpg, a->dst_parent); -+ au_pin_hdir_release(a->cpg->pin); -+} -+#endif -+ -+/* -+ * prevent SIGXFSZ in copy-up. -+ * testing CAP_MKNOD is for generic fs, -+ * but CAP_FSETID is for xfs only, currently. -+ */ -+static int au_cpup_sio_test(struct au_pin *pin, umode_t mode) -+{ -+ int do_sio; -+ struct super_block *sb; -+ struct inode *h_dir; -+ -+ do_sio = 0; -+ sb = au_pinned_parent(pin)->d_sb; -+ if (!au_wkq_test() -+ && (!au_sbi(sb)->si_plink_maint_pid -+ || au_plink_maint(sb, AuLock_NOPLM))) { -+ switch (mode & S_IFMT) { -+ case S_IFREG: -+ /* no condition about RLIMIT_FSIZE and the file size */ -+ do_sio = 1; -+ break; -+ case S_IFCHR: -+ case S_IFBLK: -+ do_sio = !capable(CAP_MKNOD); -+ break; -+ } -+ if (!do_sio) -+ do_sio = ((mode & (S_ISUID | S_ISGID)) -+ && !capable(CAP_FSETID)); -+ /* this workaround may be removed in the future */ -+ if (!do_sio) { -+ h_dir = au_pinned_h_dir(pin); -+ do_sio = h_dir->i_mode & S_ISVTX; -+ } -+ } -+ -+ return do_sio; -+} -+ -+#if 0 /* reserved */ -+int au_sio_cpup_single(struct au_cp_generic *cpg, struct dentry *dst_parent) -+{ -+ int err, wkq_err; -+ struct dentry *h_dentry; -+ -+ h_dentry = au_h_dptr(cpg->dentry, cpg->bsrc); -+ if (!au_cpup_sio_test(pin, d_inode(h_dentry)->i_mode)) -+ err = au_cpup_single(cpg, dst_parent); -+ else { -+ struct au_cpup_single_args args = { -+ .errp = &err, -+ .cpg = cpg, -+ .dst_parent = dst_parent -+ }; -+ wkq_err = au_wkq_wait(au_call_cpup_single, &args); -+ if (unlikely(wkq_err)) -+ err = wkq_err; -+ } -+ -+ return err; -+} -+#endif -+ -+/* -+ * copyup the @dentry from the first active lower branch to @bdst, -+ * using au_cpup_single(). -+ */ -+static int au_cpup_simple(struct au_cp_generic *cpg) -+{ -+ int err; -+ unsigned int flags_orig; -+ struct dentry *dentry; -+ -+ AuDebugOn(cpg->bsrc < 0); -+ -+ dentry = cpg->dentry; -+ DiMustWriteLock(dentry); -+ -+ err = au_lkup_neg(dentry, cpg->bdst, /*wh*/1); -+ if (!err) { -+ flags_orig = cpg->flags; -+ au_fset_cpup(cpg->flags, RENAME); -+ err = au_cpup_single(cpg, NULL); -+ cpg->flags = flags_orig; -+ if (!err) -+ return 0; /* success */ -+ -+ /* revert */ -+ au_set_h_dptr(dentry, cpg->bdst, NULL); -+ au_set_dbtop(dentry, cpg->bsrc); -+ } -+ -+ return err; -+} -+ -+struct au_cpup_simple_args { -+ int *errp; -+ struct au_cp_generic *cpg; -+}; -+ -+static void au_call_cpup_simple(void *args) -+{ -+ struct au_cpup_simple_args *a = args; -+ -+ au_pin_hdir_acquire_nest(a->cpg->pin); -+ *a->errp = au_cpup_simple(a->cpg); -+ au_pin_hdir_release(a->cpg->pin); -+} -+ -+static int au_do_sio_cpup_simple(struct au_cp_generic *cpg) -+{ -+ int err, wkq_err; -+ struct dentry *dentry, *parent; -+ struct file *h_file; -+ struct inode *h_dir; -+ -+ dentry = cpg->dentry; -+ h_file = NULL; -+ if (au_ftest_cpup(cpg->flags, HOPEN)) { -+ AuDebugOn(cpg->bsrc < 0); -+ h_file = au_h_open_pre(dentry, cpg->bsrc, /*force_wr*/0); -+ err = PTR_ERR(h_file); -+ if (IS_ERR(h_file)) -+ goto out; -+ } -+ -+ parent = dget_parent(dentry); -+ h_dir = au_h_iptr(d_inode(parent), cpg->bdst); -+ if (!au_test_h_perm_sio(h_dir, MAY_EXEC | MAY_WRITE) -+ && !au_cpup_sio_test(cpg->pin, d_inode(dentry)->i_mode)) -+ err = au_cpup_simple(cpg); -+ else { -+ struct au_cpup_simple_args args = { -+ .errp = &err, -+ .cpg = cpg -+ }; -+ wkq_err = au_wkq_wait(au_call_cpup_simple, &args); -+ if (unlikely(wkq_err)) -+ err = wkq_err; -+ } -+ -+ dput(parent); -+ if (h_file) -+ au_h_open_post(dentry, cpg->bsrc, h_file); -+ -+out: -+ return err; -+} -+ -+int au_sio_cpup_simple(struct au_cp_generic *cpg) -+{ -+ aufs_bindex_t bsrc, bbot; -+ struct dentry *dentry, *h_dentry; -+ -+ if (cpg->bsrc < 0) { -+ dentry = cpg->dentry; -+ bbot = au_dbbot(dentry); -+ for (bsrc = cpg->bdst + 1; bsrc <= bbot; bsrc++) { -+ h_dentry = au_h_dptr(dentry, bsrc); -+ if (h_dentry) { -+ AuDebugOn(d_is_negative(h_dentry)); -+ break; -+ } -+ } -+ AuDebugOn(bsrc > bbot); -+ cpg->bsrc = bsrc; -+ } -+ AuDebugOn(cpg->bsrc <= cpg->bdst); -+ return au_do_sio_cpup_simple(cpg); -+} -+ -+int au_sio_cpdown_simple(struct au_cp_generic *cpg) -+{ -+ AuDebugOn(cpg->bdst <= cpg->bsrc); -+ return au_do_sio_cpup_simple(cpg); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * copyup the deleted file for writing. -+ */ -+static int au_do_cpup_wh(struct au_cp_generic *cpg, struct dentry *wh_dentry, -+ struct file *file) -+{ -+ int err; -+ unsigned int flags_orig; -+ aufs_bindex_t bsrc_orig; -+ struct au_dinfo *dinfo; -+ struct { -+ struct au_hdentry *hd; -+ struct dentry *h_dentry; -+ } hdst, hsrc; -+ -+ dinfo = au_di(cpg->dentry); -+ AuRwMustWriteLock(&dinfo->di_rwsem); -+ -+ bsrc_orig = cpg->bsrc; -+ cpg->bsrc = dinfo->di_btop; -+ hdst.hd = au_hdentry(dinfo, cpg->bdst); -+ hdst.h_dentry = hdst.hd->hd_dentry; -+ hdst.hd->hd_dentry = wh_dentry; -+ dinfo->di_btop = cpg->bdst; -+ -+ hsrc.h_dentry = NULL; -+ if (file) { -+ hsrc.hd = au_hdentry(dinfo, cpg->bsrc); -+ hsrc.h_dentry = hsrc.hd->hd_dentry; -+ hsrc.hd->hd_dentry = au_hf_top(file)->f_path.dentry; -+ } -+ flags_orig = cpg->flags; -+ cpg->flags = !AuCpup_DTIME; -+ err = au_cpup_single(cpg, /*h_parent*/NULL); -+ cpg->flags = flags_orig; -+ if (file) { -+ if (!err) -+ err = au_reopen_nondir(file); -+ hsrc.hd->hd_dentry = hsrc.h_dentry; -+ } -+ hdst.hd->hd_dentry = hdst.h_dentry; -+ dinfo->di_btop = cpg->bsrc; -+ cpg->bsrc = bsrc_orig; -+ -+ return err; -+} -+ -+static int au_cpup_wh(struct au_cp_generic *cpg, struct file *file) -+{ -+ int err; -+ aufs_bindex_t bdst; -+ struct au_dtime dt; -+ struct dentry *dentry, *parent, *h_parent, *wh_dentry; -+ struct au_branch *br; -+ struct path h_path; -+ -+ dentry = cpg->dentry; -+ bdst = cpg->bdst; -+ br = au_sbr(dentry->d_sb, bdst); -+ parent = dget_parent(dentry); -+ h_parent = au_h_dptr(parent, bdst); -+ wh_dentry = au_whtmp_lkup(h_parent, br, &dentry->d_name); -+ err = PTR_ERR(wh_dentry); -+ if (IS_ERR(wh_dentry)) -+ goto out; -+ -+ h_path.dentry = h_parent; -+ h_path.mnt = au_br_mnt(br); -+ au_dtime_store(&dt, parent, &h_path); -+ err = au_do_cpup_wh(cpg, wh_dentry, file); -+ if (unlikely(err)) -+ goto out_wh; -+ -+ dget(wh_dentry); -+ h_path.dentry = wh_dentry; -+ if (!d_is_dir(wh_dentry)) { -+ /* no delegation since it is just created */ -+ err = vfsub_unlink(d_inode(h_parent), &h_path, -+ /*delegated*/NULL, /*force*/0); -+ } else -+ err = vfsub_rmdir(d_inode(h_parent), &h_path); -+ if (unlikely(err)) { -+ AuIOErr("failed remove copied-up tmp file %pd(%d)\n", -+ wh_dentry, err); -+ err = -EIO; -+ } -+ au_dtime_revert(&dt); -+ au_set_hi_wh(d_inode(dentry), bdst, wh_dentry); -+ -+out_wh: -+ dput(wh_dentry); -+out: -+ dput(parent); -+ return err; -+} -+ -+struct au_cpup_wh_args { -+ int *errp; -+ struct au_cp_generic *cpg; -+ struct file *file; -+}; -+ -+static void au_call_cpup_wh(void *args) -+{ -+ struct au_cpup_wh_args *a = args; -+ -+ au_pin_hdir_acquire_nest(a->cpg->pin); -+ *a->errp = au_cpup_wh(a->cpg, a->file); -+ au_pin_hdir_release(a->cpg->pin); -+} -+ -+int au_sio_cpup_wh(struct au_cp_generic *cpg, struct file *file) -+{ -+ int err, wkq_err; -+ aufs_bindex_t bdst; -+ struct dentry *dentry, *parent, *h_orph, *h_parent; -+ struct inode *dir, *h_dir, *h_tmpdir; -+ struct au_wbr *wbr; -+ struct au_pin wh_pin, *pin_orig; -+ -+ dentry = cpg->dentry; -+ bdst = cpg->bdst; -+ parent = dget_parent(dentry); -+ dir = d_inode(parent); -+ h_orph = NULL; -+ h_parent = NULL; -+ h_dir = au_igrab(au_h_iptr(dir, bdst)); -+ h_tmpdir = h_dir; -+ pin_orig = NULL; -+ if (!h_dir->i_nlink) { -+ wbr = au_sbr(dentry->d_sb, bdst)->br_wbr; -+ h_orph = wbr->wbr_orph; -+ -+ h_parent = dget(au_h_dptr(parent, bdst)); -+ au_set_h_dptr(parent, bdst, dget(h_orph)); -+ h_tmpdir = d_inode(h_orph); -+ au_set_h_iptr(dir, bdst, au_igrab(h_tmpdir), /*flags*/0); -+ -+ inode_lock_nested(h_tmpdir, AuLsc_I_PARENT3); -+ /* todo: au_h_open_pre()? */ -+ -+ pin_orig = cpg->pin; -+ au_pin_init(&wh_pin, dentry, bdst, AuLsc_DI_PARENT, -+ AuLsc_I_PARENT3, cpg->pin->udba, AuPin_DI_LOCKED); -+ cpg->pin = &wh_pin; -+ } -+ -+ if (!au_test_h_perm_sio(h_tmpdir, MAY_EXEC | MAY_WRITE) -+ && !au_cpup_sio_test(cpg->pin, d_inode(dentry)->i_mode)) -+ err = au_cpup_wh(cpg, file); -+ else { -+ struct au_cpup_wh_args args = { -+ .errp = &err, -+ .cpg = cpg, -+ .file = file -+ }; -+ wkq_err = au_wkq_wait(au_call_cpup_wh, &args); -+ if (unlikely(wkq_err)) -+ err = wkq_err; -+ } -+ -+ if (h_orph) { -+ inode_unlock(h_tmpdir); -+ /* todo: au_h_open_post()? */ -+ au_set_h_iptr(dir, bdst, au_igrab(h_dir), /*flags*/0); -+ au_set_h_dptr(parent, bdst, h_parent); -+ AuDebugOn(!pin_orig); -+ cpg->pin = pin_orig; -+ } -+ iput(h_dir); -+ dput(parent); -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * generic routine for both of copy-up and copy-down. -+ */ -+/* cf. revalidate function in file.c */ -+int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst, -+ int (*cp)(struct dentry *dentry, aufs_bindex_t bdst, -+ struct au_pin *pin, -+ struct dentry *h_parent, void *arg), -+ void *arg) -+{ -+ int err; -+ struct au_pin pin; -+ struct dentry *d, *parent, *h_parent, *real_parent, *h_dentry; -+ -+ err = 0; -+ parent = dget_parent(dentry); -+ if (IS_ROOT(parent)) -+ goto out; -+ -+ au_pin_init(&pin, dentry, bdst, AuLsc_DI_PARENT2, AuLsc_I_PARENT2, -+ au_opt_udba(dentry->d_sb), AuPin_MNT_WRITE); -+ -+ /* do not use au_dpage */ -+ real_parent = parent; -+ while (1) { -+ dput(parent); -+ parent = dget_parent(dentry); -+ h_parent = au_h_dptr(parent, bdst); -+ if (h_parent) -+ goto out; /* success */ -+ -+ /* find top dir which is necessary to cpup */ -+ do { -+ d = parent; -+ dput(parent); -+ parent = dget_parent(d); -+ di_read_lock_parent3(parent, !AuLock_IR); -+ h_parent = au_h_dptr(parent, bdst); -+ di_read_unlock(parent, !AuLock_IR); -+ } while (!h_parent); -+ -+ if (d != real_parent) -+ di_write_lock_child3(d); -+ -+ /* somebody else might create while we were sleeping */ -+ h_dentry = au_h_dptr(d, bdst); -+ if (!h_dentry || d_is_negative(h_dentry)) { -+ if (h_dentry) -+ au_update_dbtop(d); -+ -+ au_pin_set_dentry(&pin, d); -+ err = au_do_pin(&pin); -+ if (!err) { -+ err = cp(d, bdst, &pin, h_parent, arg); -+ au_unpin(&pin); -+ } -+ } -+ -+ if (d != real_parent) -+ di_write_unlock(d); -+ if (unlikely(err)) -+ break; -+ } -+ -+out: -+ dput(parent); -+ return err; -+} -+ -+static int au_cpup_dir(struct dentry *dentry, aufs_bindex_t bdst, -+ struct au_pin *pin, -+ struct dentry *h_parent __maybe_unused, -+ void *arg __maybe_unused) -+{ -+ struct au_cp_generic cpg = { -+ .dentry = dentry, -+ .bdst = bdst, -+ .bsrc = -1, -+ .len = 0, -+ .pin = pin, -+ .flags = AuCpup_DTIME -+ }; -+ return au_sio_cpup_simple(&cpg); -+} -+ -+int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst) -+{ -+ return au_cp_dirs(dentry, bdst, au_cpup_dir, NULL); -+} -+ -+int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst) -+{ -+ int err; -+ struct dentry *parent; -+ struct inode *dir; -+ -+ parent = dget_parent(dentry); -+ dir = d_inode(parent); -+ err = 0; -+ if (au_h_iptr(dir, bdst)) -+ goto out; -+ -+ di_read_unlock(parent, AuLock_IR); -+ di_write_lock_parent(parent); -+ /* someone else might change our inode while we were sleeping */ -+ if (!au_h_iptr(dir, bdst)) -+ err = au_cpup_dirs(dentry, bdst); -+ di_downgrade_lock(parent, AuLock_IR); -+ -+out: -+ dput(parent); -+ return err; -+} -diff -Nurp linux-5.6.3/fs/aufs/cpup.h linux-5.6.3-aufs/fs/aufs/cpup.h ---- linux-5.6.3/fs/aufs/cpup.h 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/cpup.h 2020-04-10 12:40:52.188049315 +0300 -@@ -0,0 +1,87 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * copy-up/down functions -+ */ -+ -+#ifndef __AUFS_CPUP_H__ -+#define __AUFS_CPUP_H__ -+ -+#ifdef __KERNEL__ -+ -+#include -+ -+struct inode; -+struct file; -+struct au_pin; -+ -+void au_cpup_attr_flags(struct inode *dst, unsigned int iflags); -+void au_cpup_attr_timesizes(struct inode *inode); -+void au_cpup_attr_nlink(struct inode *inode, int force); -+void au_cpup_attr_changeable(struct inode *inode); -+void au_cpup_igen(struct inode *inode, struct inode *h_inode); -+void au_cpup_attr_all(struct inode *inode, int force); -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct au_cp_generic { -+ struct dentry *dentry; -+ aufs_bindex_t bdst, bsrc; -+ loff_t len; -+ struct au_pin *pin; -+ unsigned int flags; -+}; -+ -+/* cpup flags */ -+#define AuCpup_DTIME 1 /* do dtime_store/revert */ -+#define AuCpup_KEEPLINO (1 << 1) /* do not clear the lower xino, -+ for link(2) */ -+#define AuCpup_RENAME (1 << 2) /* rename after cpup */ -+#define AuCpup_HOPEN (1 << 3) /* call h_open_pre/post() in -+ cpup */ -+#define AuCpup_OVERWRITE (1 << 4) /* allow overwriting the -+ existing entry */ -+#define AuCpup_RWDST (1 << 5) /* force write target even if -+ the branch is marked as RO */ -+ -+#ifndef CONFIG_AUFS_BR_HFSPLUS -+#undef AuCpup_HOPEN -+#define AuCpup_HOPEN 0 -+#endif -+ -+#define au_ftest_cpup(flags, name) ((flags) & AuCpup_##name) -+#define au_fset_cpup(flags, name) \ -+ do { (flags) |= AuCpup_##name; } while (0) -+#define au_fclr_cpup(flags, name) \ -+ do { (flags) &= ~AuCpup_##name; } while (0) -+ -+int au_copy_file(struct file *dst, struct file *src, loff_t len); -+int au_sio_cpup_simple(struct au_cp_generic *cpg); -+int au_sio_cpdown_simple(struct au_cp_generic *cpg); -+int au_sio_cpup_wh(struct au_cp_generic *cpg, struct file *file); -+ -+int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst, -+ int (*cp)(struct dentry *dentry, aufs_bindex_t bdst, -+ struct au_pin *pin, -+ struct dentry *h_parent, void *arg), -+ void *arg); -+int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst); -+int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst); -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* keep timestamps when copyup */ -+struct au_dtime { -+ struct dentry *dt_dentry; -+ struct path dt_h_path; -+ struct timespec64 dt_atime, dt_mtime; -+}; -+void au_dtime_store(struct au_dtime *dt, struct dentry *dentry, -+ struct path *h_path); -+void au_dtime_revert(struct au_dtime *dt); -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_CPUP_H__ */ -diff -Nurp linux-5.6.3/fs/aufs/dbgaufs.c linux-5.6.3-aufs/fs/aufs/dbgaufs.c ---- linux-5.6.3/fs/aufs/dbgaufs.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/dbgaufs.c 2020-04-10 12:40:52.188049315 +0300 -@@ -0,0 +1,513 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * debugfs interface -+ */ -+ -+#include -+#include "aufs.h" -+ -+#ifndef CONFIG_SYSFS -+#error DEBUG_FS depends upon SYSFS -+#endif -+ -+static struct dentry *dbgaufs; -+static const mode_t dbgaufs_mode = 0444; -+ -+/* 20 is max digits length of ulong 64 */ -+struct dbgaufs_arg { -+ int n; -+ char a[20 * 4]; -+}; -+ -+/* -+ * common function for all XINO files -+ */ -+static int dbgaufs_xi_release(struct inode *inode __maybe_unused, -+ struct file *file) -+{ -+ void *p; -+ -+ p = file->private_data; -+ if (p) { -+ /* this is struct dbgaufs_arg */ -+ AuDebugOn(!au_kfree_sz_test(p)); -+ au_kfree_do_rcu(p); -+ } -+ return 0; -+} -+ -+static int dbgaufs_xi_open(struct file *xf, struct file *file, int do_fcnt, -+ int cnt) -+{ -+ int err; -+ struct kstat st; -+ struct dbgaufs_arg *p; -+ -+ err = -ENOMEM; -+ p = kmalloc(sizeof(*p), GFP_NOFS); -+ if (unlikely(!p)) -+ goto out; -+ -+ err = 0; -+ p->n = 0; -+ file->private_data = p; -+ if (!xf) -+ goto out; -+ -+ err = vfsub_getattr(&xf->f_path, &st); -+ if (!err) { -+ if (do_fcnt) -+ p->n = snprintf -+ (p->a, sizeof(p->a), "%d, %llux%u %lld\n", -+ cnt, st.blocks, st.blksize, -+ (long long)st.size); -+ else -+ p->n = snprintf(p->a, sizeof(p->a), "%llux%u %lld\n", -+ st.blocks, st.blksize, -+ (long long)st.size); -+ AuDebugOn(p->n >= sizeof(p->a)); -+ } else { -+ p->n = snprintf(p->a, sizeof(p->a), "err %d\n", err); -+ err = 0; -+ } -+ -+out: -+ return err; -+} -+ -+static ssize_t dbgaufs_xi_read(struct file *file, char __user *buf, -+ size_t count, loff_t *ppos) -+{ -+ struct dbgaufs_arg *p; -+ -+ p = file->private_data; -+ return simple_read_from_buffer(buf, count, ppos, p->a, p->n); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct dbgaufs_plink_arg { -+ int n; -+ char a[]; -+}; -+ -+static int dbgaufs_plink_release(struct inode *inode __maybe_unused, -+ struct file *file) -+{ -+ free_page((unsigned long)file->private_data); -+ return 0; -+} -+ -+static int dbgaufs_plink_open(struct inode *inode, struct file *file) -+{ -+ int err, i, limit; -+ unsigned long n, sum; -+ struct dbgaufs_plink_arg *p; -+ struct au_sbinfo *sbinfo; -+ struct super_block *sb; -+ struct hlist_bl_head *hbl; -+ -+ err = -ENOMEM; -+ p = (void *)get_zeroed_page(GFP_NOFS); -+ if (unlikely(!p)) -+ goto out; -+ -+ err = -EFBIG; -+ sbinfo = inode->i_private; -+ sb = sbinfo->si_sb; -+ si_noflush_read_lock(sb); -+ if (au_opt_test(au_mntflags(sb), PLINK)) { -+ limit = PAGE_SIZE - sizeof(p->n); -+ -+ /* the number of buckets */ -+ n = snprintf(p->a + p->n, limit, "%d\n", AuPlink_NHASH); -+ p->n += n; -+ limit -= n; -+ -+ sum = 0; -+ for (i = 0, hbl = sbinfo->si_plink; i < AuPlink_NHASH; -+ i++, hbl++) { -+ n = au_hbl_count(hbl); -+ sum += n; -+ -+ n = snprintf(p->a + p->n, limit, "%lu ", n); -+ p->n += n; -+ limit -= n; -+ if (unlikely(limit <= 0)) -+ goto out_free; -+ } -+ p->a[p->n - 1] = '\n'; -+ -+ /* the sum of plinks */ -+ n = snprintf(p->a + p->n, limit, "%lu\n", sum); -+ p->n += n; -+ limit -= n; -+ if (unlikely(limit <= 0)) -+ goto out_free; -+ } else { -+#define str "1\n0\n0\n" -+ p->n = sizeof(str) - 1; -+ strcpy(p->a, str); -+#undef str -+ } -+ si_read_unlock(sb); -+ -+ err = 0; -+ file->private_data = p; -+ goto out; /* success */ -+ -+out_free: -+ free_page((unsigned long)p); -+out: -+ return err; -+} -+ -+static ssize_t dbgaufs_plink_read(struct file *file, char __user *buf, -+ size_t count, loff_t *ppos) -+{ -+ struct dbgaufs_plink_arg *p; -+ -+ p = file->private_data; -+ return simple_read_from_buffer(buf, count, ppos, p->a, p->n); -+} -+ -+static const struct file_operations dbgaufs_plink_fop = { -+ .owner = THIS_MODULE, -+ .open = dbgaufs_plink_open, -+ .release = dbgaufs_plink_release, -+ .read = dbgaufs_plink_read -+}; -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int dbgaufs_xib_open(struct inode *inode, struct file *file) -+{ -+ int err; -+ struct au_sbinfo *sbinfo; -+ struct super_block *sb; -+ -+ sbinfo = inode->i_private; -+ sb = sbinfo->si_sb; -+ si_noflush_read_lock(sb); -+ err = dbgaufs_xi_open(sbinfo->si_xib, file, /*do_fcnt*/0, /*cnt*/0); -+ si_read_unlock(sb); -+ return err; -+} -+ -+static const struct file_operations dbgaufs_xib_fop = { -+ .owner = THIS_MODULE, -+ .open = dbgaufs_xib_open, -+ .release = dbgaufs_xi_release, -+ .read = dbgaufs_xi_read -+}; -+ -+/* ---------------------------------------------------------------------- */ -+ -+#define DbgaufsXi_PREFIX "xi" -+ -+static int dbgaufs_xino_open(struct inode *inode, struct file *file) -+{ -+ int err, idx; -+ long l; -+ aufs_bindex_t bindex; -+ char *p, a[sizeof(DbgaufsXi_PREFIX) + 8]; -+ struct au_sbinfo *sbinfo; -+ struct super_block *sb; -+ struct au_xino *xi; -+ struct file *xf; -+ struct qstr *name; -+ struct au_branch *br; -+ -+ err = -ENOENT; -+ name = &file->f_path.dentry->d_name; -+ if (unlikely(name->len < sizeof(DbgaufsXi_PREFIX) -+ || memcmp(name->name, DbgaufsXi_PREFIX, -+ sizeof(DbgaufsXi_PREFIX) - 1))) -+ goto out; -+ -+ AuDebugOn(name->len >= sizeof(a)); -+ memcpy(a, name->name, name->len); -+ a[name->len] = '\0'; -+ p = strchr(a, '-'); -+ if (p) -+ *p = '\0'; -+ err = kstrtol(a + sizeof(DbgaufsXi_PREFIX) - 1, 10, &l); -+ if (unlikely(err)) -+ goto out; -+ bindex = l; -+ idx = 0; -+ if (p) { -+ err = kstrtol(p + 1, 10, &l); -+ if (unlikely(err)) -+ goto out; -+ idx = l; -+ } -+ -+ err = -ENOENT; -+ sbinfo = inode->i_private; -+ sb = sbinfo->si_sb; -+ si_noflush_read_lock(sb); -+ if (unlikely(bindex < 0 || bindex > au_sbbot(sb))) -+ goto out_si; -+ br = au_sbr(sb, bindex); -+ xi = br->br_xino; -+ if (unlikely(idx >= xi->xi_nfile)) -+ goto out_si; -+ xf = au_xino_file(xi, idx); -+ if (xf) -+ err = dbgaufs_xi_open(xf, file, /*do_fcnt*/1, -+ au_xino_count(br)); -+ -+out_si: -+ si_read_unlock(sb); -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+static const struct file_operations dbgaufs_xino_fop = { -+ .owner = THIS_MODULE, -+ .open = dbgaufs_xino_open, -+ .release = dbgaufs_xi_release, -+ .read = dbgaufs_xi_read -+}; -+ -+void dbgaufs_xino_del(struct au_branch *br) -+{ -+ struct dentry *dbgaufs; -+ -+ dbgaufs = br->br_dbgaufs; -+ if (!dbgaufs) -+ return; -+ -+ br->br_dbgaufs = NULL; -+ /* debugfs acquires the parent i_mutex */ -+ lockdep_off(); -+ debugfs_remove(dbgaufs); -+ lockdep_on(); -+} -+ -+void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex) -+{ -+ aufs_bindex_t bbot; -+ struct au_branch *br; -+ -+ if (!au_sbi(sb)->si_dbgaufs) -+ return; -+ -+ bbot = au_sbbot(sb); -+ for (; bindex <= bbot; bindex++) { -+ br = au_sbr(sb, bindex); -+ dbgaufs_xino_del(br); -+ } -+} -+ -+static void dbgaufs_br_do_add(struct super_block *sb, aufs_bindex_t bindex, -+ unsigned int idx, struct dentry *parent, -+ struct au_sbinfo *sbinfo) -+{ -+ struct au_branch *br; -+ struct dentry *d; -+ /* "xi" bindex(5) "-" idx(2) NULL */ -+ char name[sizeof(DbgaufsXi_PREFIX) + 8]; -+ -+ if (!idx) -+ snprintf(name, sizeof(name), DbgaufsXi_PREFIX "%d", bindex); -+ else -+ snprintf(name, sizeof(name), DbgaufsXi_PREFIX "%d-%u", -+ bindex, idx); -+ br = au_sbr(sb, bindex); -+ if (br->br_dbgaufs) { -+ struct qstr qstr = QSTR_INIT(name, strlen(name)); -+ -+ if (!au_qstreq(&br->br_dbgaufs->d_name, &qstr)) { -+ /* debugfs acquires the parent i_mutex */ -+ lockdep_off(); -+ d = debugfs_rename(parent, br->br_dbgaufs, parent, -+ name); -+ lockdep_on(); -+ if (unlikely(!d)) -+ pr_warn("failed renaming %pd/%s, ignored.\n", -+ parent, name); -+ } -+ } else { -+ lockdep_off(); -+ br->br_dbgaufs = debugfs_create_file(name, dbgaufs_mode, parent, -+ sbinfo, &dbgaufs_xino_fop); -+ lockdep_on(); -+ if (unlikely(!br->br_dbgaufs)) -+ pr_warn("failed creating %pd/%s, ignored.\n", -+ parent, name); -+ } -+} -+ -+static void dbgaufs_br_add(struct super_block *sb, aufs_bindex_t bindex, -+ struct dentry *parent, struct au_sbinfo *sbinfo) -+{ -+ struct au_branch *br; -+ struct au_xino *xi; -+ unsigned int u; -+ -+ br = au_sbr(sb, bindex); -+ xi = br->br_xino; -+ for (u = 0; u < xi->xi_nfile; u++) -+ dbgaufs_br_do_add(sb, bindex, u, parent, sbinfo); -+} -+ -+void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex, int topdown) -+{ -+ struct au_sbinfo *sbinfo; -+ struct dentry *parent; -+ aufs_bindex_t bbot; -+ -+ if (!au_opt_test(au_mntflags(sb), XINO)) -+ return; -+ -+ sbinfo = au_sbi(sb); -+ parent = sbinfo->si_dbgaufs; -+ if (!parent) -+ return; -+ -+ bbot = au_sbbot(sb); -+ if (topdown) -+ for (; bindex <= bbot; bindex++) -+ dbgaufs_br_add(sb, bindex, parent, sbinfo); -+ else -+ for (; bbot >= bindex; bbot--) -+ dbgaufs_br_add(sb, bbot, parent, sbinfo); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+#ifdef CONFIG_AUFS_EXPORT -+static int dbgaufs_xigen_open(struct inode *inode, struct file *file) -+{ -+ int err; -+ struct au_sbinfo *sbinfo; -+ struct super_block *sb; -+ -+ sbinfo = inode->i_private; -+ sb = sbinfo->si_sb; -+ si_noflush_read_lock(sb); -+ err = dbgaufs_xi_open(sbinfo->si_xigen, file, /*do_fcnt*/0, /*cnt*/0); -+ si_read_unlock(sb); -+ return err; -+} -+ -+static const struct file_operations dbgaufs_xigen_fop = { -+ .owner = THIS_MODULE, -+ .open = dbgaufs_xigen_open, -+ .release = dbgaufs_xi_release, -+ .read = dbgaufs_xi_read -+}; -+ -+static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo) -+{ -+ int err; -+ -+ /* -+ * This function is a dynamic '__init' function actually, -+ * so the tiny check for si_rwsem is unnecessary. -+ */ -+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */ -+ -+ err = -EIO; -+ sbinfo->si_dbgaufs_xigen = debugfs_create_file -+ ("xigen", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo, -+ &dbgaufs_xigen_fop); -+ if (sbinfo->si_dbgaufs_xigen) -+ err = 0; -+ -+ return err; -+} -+#else -+static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo) -+{ -+ return 0; -+} -+#endif /* CONFIG_AUFS_EXPORT */ -+ -+/* ---------------------------------------------------------------------- */ -+ -+void dbgaufs_si_fin(struct au_sbinfo *sbinfo) -+{ -+ /* -+ * This function is a dynamic '__fin' function actually, -+ * so the tiny check for si_rwsem is unnecessary. -+ */ -+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */ -+ -+ debugfs_remove_recursive(sbinfo->si_dbgaufs); -+ sbinfo->si_dbgaufs = NULL; -+} -+ -+int dbgaufs_si_init(struct au_sbinfo *sbinfo) -+{ -+ int err; -+ char name[SysaufsSiNameLen]; -+ -+ /* -+ * This function is a dynamic '__init' function actually, -+ * so the tiny check for si_rwsem is unnecessary. -+ */ -+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */ -+ -+ err = -ENOENT; -+ if (!dbgaufs) { -+ AuErr1("/debug/aufs is uninitialized\n"); -+ goto out; -+ } -+ -+ err = -EIO; -+ sysaufs_name(sbinfo, name); -+ sbinfo->si_dbgaufs = debugfs_create_dir(name, dbgaufs); -+ if (unlikely(!sbinfo->si_dbgaufs)) -+ goto out; -+ -+ /* regardless plink/noplink option */ -+ sbinfo->si_dbgaufs_plink = debugfs_create_file -+ ("plink", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo, -+ &dbgaufs_plink_fop); -+ if (unlikely(!sbinfo->si_dbgaufs_plink)) -+ goto out_dir; -+ -+ /* regardless xino/noxino option */ -+ sbinfo->si_dbgaufs_xib = debugfs_create_file -+ ("xib", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo, -+ &dbgaufs_xib_fop); -+ if (unlikely(!sbinfo->si_dbgaufs_xib)) -+ goto out_dir; -+ -+ err = dbgaufs_xigen_init(sbinfo); -+ if (!err) -+ goto out; /* success */ -+ -+out_dir: -+ dbgaufs_si_fin(sbinfo); -+out: -+ if (unlikely(err)) -+ pr_err("debugfs/aufs failed\n"); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+void dbgaufs_fin(void) -+{ -+ debugfs_remove(dbgaufs); -+} -+ -+int __init dbgaufs_init(void) -+{ -+ int err; -+ -+ err = -EIO; -+ dbgaufs = debugfs_create_dir(AUFS_NAME, NULL); -+ if (dbgaufs) -+ err = 0; -+ return err; -+} -diff -Nurp linux-5.6.3/fs/aufs/dbgaufs.h linux-5.6.3-aufs/fs/aufs/dbgaufs.h ---- linux-5.6.3/fs/aufs/dbgaufs.h 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/dbgaufs.h 2020-04-10 12:40:52.188049315 +0300 -@@ -0,0 +1,40 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * debugfs interface -+ */ -+ -+#ifndef __DBGAUFS_H__ -+#define __DBGAUFS_H__ -+ -+#ifdef __KERNEL__ -+ -+struct super_block; -+struct au_sbinfo; -+struct au_branch; -+ -+#ifdef CONFIG_DEBUG_FS -+/* dbgaufs.c */ -+void dbgaufs_xino_del(struct au_branch *br); -+void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex); -+void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex, int topdown); -+void dbgaufs_si_fin(struct au_sbinfo *sbinfo); -+int dbgaufs_si_init(struct au_sbinfo *sbinfo); -+void dbgaufs_fin(void); -+int __init dbgaufs_init(void); -+#else -+AuStubVoid(dbgaufs_xino_del, struct au_branch *br) -+AuStubVoid(dbgaufs_brs_del, struct super_block *sb, aufs_bindex_t bindex) -+AuStubVoid(dbgaufs_brs_add, struct super_block *sb, aufs_bindex_t bindex, -+ int topdown) -+AuStubVoid(dbgaufs_si_fin, struct au_sbinfo *sbinfo) -+AuStubInt0(dbgaufs_si_init, struct au_sbinfo *sbinfo) -+AuStubVoid(dbgaufs_fin, void) -+AuStubInt0(__init dbgaufs_init, void) -+#endif /* CONFIG_DEBUG_FS */ -+ -+#endif /* __KERNEL__ */ -+#endif /* __DBGAUFS_H__ */ -diff -Nurp linux-5.6.3/fs/aufs/dcsub.c linux-5.6.3-aufs/fs/aufs/dcsub.c ---- linux-5.6.3/fs/aufs/dcsub.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/dcsub.c 2020-04-10 12:40:52.189049362 +0300 -@@ -0,0 +1,212 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * sub-routines for dentry cache -+ */ -+ -+#include "aufs.h" -+ -+static void au_dpage_free(struct au_dpage *dpage) -+{ -+ int i; -+ struct dentry **p; -+ -+ p = dpage->dentries; -+ for (i = 0; i < dpage->ndentry; i++) -+ dput(*p++); -+ free_page((unsigned long)dpage->dentries); -+} -+ -+int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp) -+{ -+ int err; -+ void *p; -+ -+ err = -ENOMEM; -+ dpages->dpages = kmalloc(sizeof(*dpages->dpages), gfp); -+ if (unlikely(!dpages->dpages)) -+ goto out; -+ -+ p = (void *)__get_free_page(gfp); -+ if (unlikely(!p)) -+ goto out_dpages; -+ -+ dpages->dpages[0].ndentry = 0; -+ dpages->dpages[0].dentries = p; -+ dpages->ndpage = 1; -+ return 0; /* success */ -+ -+out_dpages: -+ au_kfree_try_rcu(dpages->dpages); -+out: -+ return err; -+} -+ -+void au_dpages_free(struct au_dcsub_pages *dpages) -+{ -+ int i; -+ struct au_dpage *p; -+ -+ p = dpages->dpages; -+ for (i = 0; i < dpages->ndpage; i++) -+ au_dpage_free(p++); -+ au_kfree_try_rcu(dpages->dpages); -+} -+ -+static int au_dpages_append(struct au_dcsub_pages *dpages, -+ struct dentry *dentry, gfp_t gfp) -+{ -+ int err, sz; -+ struct au_dpage *dpage; -+ void *p; -+ -+ dpage = dpages->dpages + dpages->ndpage - 1; -+ sz = PAGE_SIZE / sizeof(dentry); -+ if (unlikely(dpage->ndentry >= sz)) { -+ AuLabel(new dpage); -+ err = -ENOMEM; -+ sz = dpages->ndpage * sizeof(*dpages->dpages); -+ p = au_kzrealloc(dpages->dpages, sz, -+ sz + sizeof(*dpages->dpages), gfp, -+ /*may_shrink*/0); -+ if (unlikely(!p)) -+ goto out; -+ -+ dpages->dpages = p; -+ dpage = dpages->dpages + dpages->ndpage; -+ p = (void *)__get_free_page(gfp); -+ if (unlikely(!p)) -+ goto out; -+ -+ dpage->ndentry = 0; -+ dpage->dentries = p; -+ dpages->ndpage++; -+ } -+ -+ AuDebugOn(au_dcount(dentry) <= 0); -+ dpage->dentries[dpage->ndentry++] = dget_dlock(dentry); -+ return 0; /* success */ -+ -+out: -+ return err; -+} -+ -+/* todo: BAD approach */ -+/* copied from linux/fs/dcache.c */ -+enum d_walk_ret { -+ D_WALK_CONTINUE, -+ D_WALK_QUIT, -+ D_WALK_NORETRY, -+ D_WALK_SKIP, -+}; -+ -+extern void d_walk(struct dentry *parent, void *data, -+ enum d_walk_ret (*enter)(void *, struct dentry *)); -+ -+struct ac_dpages_arg { -+ int err; -+ struct au_dcsub_pages *dpages; -+ struct super_block *sb; -+ au_dpages_test test; -+ void *arg; -+}; -+ -+static enum d_walk_ret au_call_dpages_append(void *_arg, struct dentry *dentry) -+{ -+ enum d_walk_ret ret; -+ struct ac_dpages_arg *arg = _arg; -+ -+ ret = D_WALK_CONTINUE; -+ if (dentry->d_sb == arg->sb -+ && !IS_ROOT(dentry) -+ && au_dcount(dentry) > 0 -+ && au_di(dentry) -+ && (!arg->test || arg->test(dentry, arg->arg))) { -+ arg->err = au_dpages_append(arg->dpages, dentry, GFP_ATOMIC); -+ if (unlikely(arg->err)) -+ ret = D_WALK_QUIT; -+ } -+ -+ return ret; -+} -+ -+int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root, -+ au_dpages_test test, void *arg) -+{ -+ struct ac_dpages_arg args = { -+ .err = 0, -+ .dpages = dpages, -+ .sb = root->d_sb, -+ .test = test, -+ .arg = arg -+ }; -+ -+ d_walk(root, &args, au_call_dpages_append); -+ -+ return args.err; -+} -+ -+int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry, -+ int do_include, au_dpages_test test, void *arg) -+{ -+ int err; -+ -+ err = 0; -+ write_seqlock(&rename_lock); -+ spin_lock(&dentry->d_lock); -+ if (do_include -+ && au_dcount(dentry) > 0 -+ && (!test || test(dentry, arg))) -+ err = au_dpages_append(dpages, dentry, GFP_ATOMIC); -+ spin_unlock(&dentry->d_lock); -+ if (unlikely(err)) -+ goto out; -+ -+ /* -+ * RCU for vfsmount is unnecessary since this is a traverse in a single -+ * mount -+ */ -+ while (!IS_ROOT(dentry)) { -+ dentry = dentry->d_parent; /* rename_lock is locked */ -+ spin_lock(&dentry->d_lock); -+ if (au_dcount(dentry) > 0 -+ && (!test || test(dentry, arg))) -+ err = au_dpages_append(dpages, dentry, GFP_ATOMIC); -+ spin_unlock(&dentry->d_lock); -+ if (unlikely(err)) -+ break; -+ } -+ -+out: -+ write_sequnlock(&rename_lock); -+ return err; -+} -+ -+static inline int au_dcsub_dpages_aufs(struct dentry *dentry, void *arg) -+{ -+ return au_di(dentry) && dentry->d_sb == arg; -+} -+ -+int au_dcsub_pages_rev_aufs(struct au_dcsub_pages *dpages, -+ struct dentry *dentry, int do_include) -+{ -+ return au_dcsub_pages_rev(dpages, dentry, do_include, -+ au_dcsub_dpages_aufs, dentry->d_sb); -+} -+ -+int au_test_subdir(struct dentry *d1, struct dentry *d2) -+{ -+ struct path path[2] = { -+ { -+ .dentry = d1 -+ }, -+ { -+ .dentry = d2 -+ } -+ }; -+ -+ return path_is_under(path + 0, path + 1); -+} -diff -Nurp linux-5.6.3/fs/aufs/dcsub.h linux-5.6.3-aufs/fs/aufs/dcsub.h ---- linux-5.6.3/fs/aufs/dcsub.h 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/dcsub.h 2020-04-10 12:40:52.189049362 +0300 -@@ -0,0 +1,124 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * sub-routines for dentry cache -+ */ -+ -+#ifndef __AUFS_DCSUB_H__ -+#define __AUFS_DCSUB_H__ -+ -+#ifdef __KERNEL__ -+ -+#include -+#include -+ -+struct au_dpage { -+ int ndentry; -+ struct dentry **dentries; -+}; -+ -+struct au_dcsub_pages { -+ int ndpage; -+ struct au_dpage *dpages; -+}; -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* dcsub.c */ -+int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp); -+void au_dpages_free(struct au_dcsub_pages *dpages); -+typedef int (*au_dpages_test)(struct dentry *dentry, void *arg); -+int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root, -+ au_dpages_test test, void *arg); -+int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry, -+ int do_include, au_dpages_test test, void *arg); -+int au_dcsub_pages_rev_aufs(struct au_dcsub_pages *dpages, -+ struct dentry *dentry, int do_include); -+int au_test_subdir(struct dentry *d1, struct dentry *d2); -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * todo: in linux-3.13, several similar (but faster) helpers are added to -+ * include/linux/dcache.h. Try them (in the future). -+ */ -+ -+static inline int au_d_hashed_positive(struct dentry *d) -+{ -+ int err; -+ struct inode *inode = d_inode(d); -+ -+ err = 0; -+ if (unlikely(d_unhashed(d) -+ || d_is_negative(d) -+ || !inode->i_nlink)) -+ err = -ENOENT; -+ return err; -+} -+ -+static inline int au_d_linkable(struct dentry *d) -+{ -+ int err; -+ struct inode *inode = d_inode(d); -+ -+ err = au_d_hashed_positive(d); -+ if (err -+ && d_is_positive(d) -+ && (inode->i_state & I_LINKABLE)) -+ err = 0; -+ return err; -+} -+ -+static inline int au_d_alive(struct dentry *d) -+{ -+ int err; -+ struct inode *inode; -+ -+ err = 0; -+ if (!IS_ROOT(d)) -+ err = au_d_hashed_positive(d); -+ else { -+ inode = d_inode(d); -+ if (unlikely(d_unlinked(d) -+ || d_is_negative(d) -+ || !inode->i_nlink)) -+ err = -ENOENT; -+ } -+ return err; -+} -+ -+static inline int au_alive_dir(struct dentry *d) -+{ -+ int err; -+ -+ err = au_d_alive(d); -+ if (unlikely(err || IS_DEADDIR(d_inode(d)))) -+ err = -ENOENT; -+ return err; -+} -+ -+static inline int au_qstreq(struct qstr *a, struct qstr *b) -+{ -+ return a->len == b->len -+ && !memcmp(a->name, b->name, a->len); -+} -+ -+/* -+ * by the commit -+ * 360f547 2015-01-25 dcache: let the dentry count go down to zero without -+ * taking d_lock -+ * the type of d_lockref.count became int, but the inlined function d_count() -+ * still returns unsigned int. -+ * I don't know why. Maybe it is for every d_count() users? -+ * Anyway au_dcount() lives on. -+ */ -+static inline int au_dcount(struct dentry *d) -+{ -+ return (int)d_count(d); -+} -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_DCSUB_H__ */ -diff -Nurp linux-5.6.3/fs/aufs/debug.c linux-5.6.3-aufs/fs/aufs/debug.c ---- linux-5.6.3/fs/aufs/debug.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/debug.c 2020-04-10 12:40:52.189049362 +0300 -@@ -0,0 +1,428 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * debug print functions -+ */ -+ -+#include -+#include "aufs.h" -+ -+/* Returns 0, or -errno. arg is in kp->arg. */ -+static int param_atomic_t_set(const char *val, const struct kernel_param *kp) -+{ -+ int err, n; -+ -+ err = kstrtoint(val, 0, &n); -+ if (!err) { -+ if (n > 0) -+ au_debug_on(); -+ else -+ au_debug_off(); -+ } -+ return err; -+} -+ -+/* Returns length written or -errno. Buffer is 4k (ie. be short!) */ -+static int param_atomic_t_get(char *buffer, const struct kernel_param *kp) -+{ -+ atomic_t *a; -+ -+ a = kp->arg; -+ return sprintf(buffer, "%d", atomic_read(a)); -+} -+ -+static struct kernel_param_ops param_ops_atomic_t = { -+ .set = param_atomic_t_set, -+ .get = param_atomic_t_get -+ /* void (*free)(void *arg) */ -+}; -+ -+atomic_t aufs_debug = ATOMIC_INIT(0); -+MODULE_PARM_DESC(debug, "debug print"); -+module_param_named(debug, aufs_debug, atomic_t, 0664); -+ -+DEFINE_MUTEX(au_dbg_mtx); /* just to serialize the dbg msgs */ -+char *au_plevel = KERN_DEBUG; -+#define dpri(fmt, ...) do { \ -+ if ((au_plevel \ -+ && strcmp(au_plevel, KERN_DEBUG)) \ -+ || au_debug_test()) \ -+ printk("%s" fmt, au_plevel, ##__VA_ARGS__); \ -+} while (0) -+ -+/* ---------------------------------------------------------------------- */ -+ -+void au_dpri_whlist(struct au_nhash *whlist) -+{ -+ unsigned long ul, n; -+ struct hlist_head *head; -+ struct au_vdir_wh *pos; -+ -+ n = whlist->nh_num; -+ head = whlist->nh_head; -+ for (ul = 0; ul < n; ul++) { -+ hlist_for_each_entry(pos, head, wh_hash) -+ dpri("b%d, %.*s, %d\n", -+ pos->wh_bindex, -+ pos->wh_str.len, pos->wh_str.name, -+ pos->wh_str.len); -+ head++; -+ } -+} -+ -+void au_dpri_vdir(struct au_vdir *vdir) -+{ -+ unsigned long ul; -+ union au_vdir_deblk_p p; -+ unsigned char *o; -+ -+ if (!vdir || IS_ERR(vdir)) { -+ dpri("err %ld\n", PTR_ERR(vdir)); -+ return; -+ } -+ -+ dpri("deblk %u, nblk %lu, deblk %p, last{%lu, %p}, ver %llu\n", -+ vdir->vd_deblk_sz, vdir->vd_nblk, vdir->vd_deblk, -+ vdir->vd_last.ul, vdir->vd_last.p.deblk, vdir->vd_version); -+ for (ul = 0; ul < vdir->vd_nblk; ul++) { -+ p.deblk = vdir->vd_deblk[ul]; -+ o = p.deblk; -+ dpri("[%lu]: %p\n", ul, o); -+ } -+} -+ -+static int do_pri_inode(aufs_bindex_t bindex, struct inode *inode, int hn, -+ struct dentry *wh) -+{ -+ char *n = NULL; -+ int l = 0; -+ -+ if (!inode || IS_ERR(inode)) { -+ dpri("i%d: err %ld\n", bindex, PTR_ERR(inode)); -+ return -1; -+ } -+ -+ /* the type of i_blocks depends upon CONFIG_LBDAF */ -+ BUILD_BUG_ON(sizeof(inode->i_blocks) != sizeof(unsigned long) -+ && sizeof(inode->i_blocks) != sizeof(u64)); -+ if (wh) { -+ n = (void *)wh->d_name.name; -+ l = wh->d_name.len; -+ } -+ -+ dpri("i%d: %p, i%lu, %s, cnt %d, nl %u, 0%o, sz %llu, blk %llu," -+ " hn %d, ct %lld, np %lu, st 0x%lx, f 0x%x, v %llu, g %x%s%.*s\n", -+ bindex, inode, -+ inode->i_ino, inode->i_sb ? au_sbtype(inode->i_sb) : "??", -+ atomic_read(&inode->i_count), inode->i_nlink, inode->i_mode, -+ i_size_read(inode), (unsigned long long)inode->i_blocks, -+ hn, (long long)timespec64_to_ns(&inode->i_ctime) & 0x0ffff, -+ inode->i_mapping ? inode->i_mapping->nrpages : 0, -+ inode->i_state, inode->i_flags, inode_peek_iversion(inode), -+ inode->i_generation, -+ l ? ", wh " : "", l, n); -+ return 0; -+} -+ -+void au_dpri_inode(struct inode *inode) -+{ -+ struct au_iinfo *iinfo; -+ struct au_hinode *hi; -+ aufs_bindex_t bindex; -+ int err, hn; -+ -+ err = do_pri_inode(-1, inode, -1, NULL); -+ if (err || !au_test_aufs(inode->i_sb) || au_is_bad_inode(inode)) -+ return; -+ -+ iinfo = au_ii(inode); -+ dpri("i-1: btop %d, bbot %d, gen %d\n", -+ iinfo->ii_btop, iinfo->ii_bbot, au_iigen(inode, NULL)); -+ if (iinfo->ii_btop < 0) -+ return; -+ hn = 0; -+ for (bindex = iinfo->ii_btop; bindex <= iinfo->ii_bbot; bindex++) { -+ hi = au_hinode(iinfo, bindex); -+ hn = !!au_hn(hi); -+ do_pri_inode(bindex, hi->hi_inode, hn, hi->hi_whdentry); -+ } -+} -+ -+void au_dpri_dalias(struct inode *inode) -+{ -+ struct dentry *d; -+ -+ spin_lock(&inode->i_lock); -+ hlist_for_each_entry(d, &inode->i_dentry, d_u.d_alias) -+ au_dpri_dentry(d); -+ spin_unlock(&inode->i_lock); -+} -+ -+static int do_pri_dentry(aufs_bindex_t bindex, struct dentry *dentry) -+{ -+ struct dentry *wh = NULL; -+ int hn; -+ struct inode *inode; -+ struct au_iinfo *iinfo; -+ struct au_hinode *hi; -+ -+ if (!dentry || IS_ERR(dentry)) { -+ dpri("d%d: err %ld\n", bindex, PTR_ERR(dentry)); -+ return -1; -+ } -+ /* do not call dget_parent() here */ -+ /* note: access d_xxx without d_lock */ -+ dpri("d%d: %p, %pd2?, %s, cnt %d, flags 0x%x, %shashed\n", -+ bindex, dentry, dentry, -+ dentry->d_sb ? au_sbtype(dentry->d_sb) : "??", -+ au_dcount(dentry), dentry->d_flags, -+ d_unhashed(dentry) ? "un" : ""); -+ hn = -1; -+ inode = NULL; -+ if (d_is_positive(dentry)) -+ inode = d_inode(dentry); -+ if (inode -+ && au_test_aufs(dentry->d_sb) -+ && bindex >= 0 -+ && !au_is_bad_inode(inode)) { -+ iinfo = au_ii(inode); -+ hi = au_hinode(iinfo, bindex); -+ hn = !!au_hn(hi); -+ wh = hi->hi_whdentry; -+ } -+ do_pri_inode(bindex, inode, hn, wh); -+ return 0; -+} -+ -+void au_dpri_dentry(struct dentry *dentry) -+{ -+ struct au_dinfo *dinfo; -+ aufs_bindex_t bindex; -+ int err; -+ -+ err = do_pri_dentry(-1, dentry); -+ if (err || !au_test_aufs(dentry->d_sb)) -+ return; -+ -+ dinfo = au_di(dentry); -+ if (!dinfo) -+ return; -+ dpri("d-1: btop %d, bbot %d, bwh %d, bdiropq %d, gen %d, tmp %d\n", -+ dinfo->di_btop, dinfo->di_bbot, -+ dinfo->di_bwh, dinfo->di_bdiropq, au_digen(dentry), -+ dinfo->di_tmpfile); -+ if (dinfo->di_btop < 0) -+ return; -+ for (bindex = dinfo->di_btop; bindex <= dinfo->di_bbot; bindex++) -+ do_pri_dentry(bindex, au_hdentry(dinfo, bindex)->hd_dentry); -+} -+ -+static int do_pri_file(aufs_bindex_t bindex, struct file *file) -+{ -+ char a[32]; -+ -+ if (!file || IS_ERR(file)) { -+ dpri("f%d: err %ld\n", bindex, PTR_ERR(file)); -+ return -1; -+ } -+ a[0] = 0; -+ if (bindex < 0 -+ && !IS_ERR_OR_NULL(file->f_path.dentry) -+ && au_test_aufs(file->f_path.dentry->d_sb) -+ && au_fi(file)) -+ snprintf(a, sizeof(a), ", gen %d, mmapped %d", -+ au_figen(file), atomic_read(&au_fi(file)->fi_mmapped)); -+ dpri("f%d: mode 0x%x, flags 0%o, cnt %ld, v %llu, pos %llu%s\n", -+ bindex, file->f_mode, file->f_flags, (long)file_count(file), -+ file->f_version, file->f_pos, a); -+ if (!IS_ERR_OR_NULL(file->f_path.dentry)) -+ do_pri_dentry(bindex, file->f_path.dentry); -+ return 0; -+} -+ -+void au_dpri_file(struct file *file) -+{ -+ struct au_finfo *finfo; -+ struct au_fidir *fidir; -+ struct au_hfile *hfile; -+ aufs_bindex_t bindex; -+ int err; -+ -+ err = do_pri_file(-1, file); -+ if (err -+ || IS_ERR_OR_NULL(file->f_path.dentry) -+ || !au_test_aufs(file->f_path.dentry->d_sb)) -+ return; -+ -+ finfo = au_fi(file); -+ if (!finfo) -+ return; -+ if (finfo->fi_btop < 0) -+ return; -+ fidir = finfo->fi_hdir; -+ if (!fidir) -+ do_pri_file(finfo->fi_btop, finfo->fi_htop.hf_file); -+ else -+ for (bindex = finfo->fi_btop; -+ bindex >= 0 && bindex <= fidir->fd_bbot; -+ bindex++) { -+ hfile = fidir->fd_hfile + bindex; -+ do_pri_file(bindex, hfile ? hfile->hf_file : NULL); -+ } -+} -+ -+static int do_pri_br(aufs_bindex_t bindex, struct au_branch *br) -+{ -+ struct vfsmount *mnt; -+ struct super_block *sb; -+ -+ if (!br || IS_ERR(br)) -+ goto out; -+ mnt = au_br_mnt(br); -+ if (!mnt || IS_ERR(mnt)) -+ goto out; -+ sb = mnt->mnt_sb; -+ if (!sb || IS_ERR(sb)) -+ goto out; -+ -+ dpri("s%d: {perm 0x%x, id %d, wbr %p}, " -+ "%s, dev 0x%02x%02x, flags 0x%lx, cnt %d, active %d, " -+ "xino %d\n", -+ bindex, br->br_perm, br->br_id, br->br_wbr, -+ au_sbtype(sb), MAJOR(sb->s_dev), MINOR(sb->s_dev), -+ sb->s_flags, sb->s_count, -+ atomic_read(&sb->s_active), -+ !!au_xino_file(br->br_xino, /*idx*/-1)); -+ return 0; -+ -+out: -+ dpri("s%d: err %ld\n", bindex, PTR_ERR(br)); -+ return -1; -+} -+ -+void au_dpri_sb(struct super_block *sb) -+{ -+ struct au_sbinfo *sbinfo; -+ aufs_bindex_t bindex; -+ int err; -+ /* to reduce stack size */ -+ struct { -+ struct vfsmount mnt; -+ struct au_branch fake; -+ } *a; -+ -+ /* this function can be called from magic sysrq */ -+ a = kzalloc(sizeof(*a), GFP_ATOMIC); -+ if (unlikely(!a)) { -+ dpri("no memory\n"); -+ return; -+ } -+ -+ a->mnt.mnt_sb = sb; -+ a->fake.br_path.mnt = &a->mnt; -+ err = do_pri_br(-1, &a->fake); -+ au_kfree_rcu(a); -+ dpri("dev 0x%x\n", sb->s_dev); -+ if (err || !au_test_aufs(sb)) -+ return; -+ -+ sbinfo = au_sbi(sb); -+ if (!sbinfo) -+ return; -+ dpri("nw %d, gen %u, kobj %d\n", -+ atomic_read(&sbinfo->si_nowait.nw_len), sbinfo->si_generation, -+ kref_read(&sbinfo->si_kobj.kref)); -+ for (bindex = 0; bindex <= sbinfo->si_bbot; bindex++) -+ do_pri_br(bindex, sbinfo->si_branch[0 + bindex]); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+void __au_dbg_verify_dinode(struct dentry *dentry, const char *func, int line) -+{ -+ struct inode *h_inode, *inode = d_inode(dentry); -+ struct dentry *h_dentry; -+ aufs_bindex_t bindex, bbot, bi; -+ -+ if (!inode /* || au_di(dentry)->di_lsc == AuLsc_DI_TMP */) -+ return; -+ -+ bbot = au_dbbot(dentry); -+ bi = au_ibbot(inode); -+ if (bi < bbot) -+ bbot = bi; -+ bindex = au_dbtop(dentry); -+ bi = au_ibtop(inode); -+ if (bi > bindex) -+ bindex = bi; -+ -+ for (; bindex <= bbot; bindex++) { -+ h_dentry = au_h_dptr(dentry, bindex); -+ if (!h_dentry) -+ continue; -+ h_inode = au_h_iptr(inode, bindex); -+ if (unlikely(h_inode != d_inode(h_dentry))) { -+ au_debug_on(); -+ AuDbg("b%d, %s:%d\n", bindex, func, line); -+ AuDbgDentry(dentry); -+ AuDbgInode(inode); -+ au_debug_off(); -+ BUG(); -+ } -+ } -+} -+ -+void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen) -+{ -+ int err, i, j; -+ struct au_dcsub_pages dpages; -+ struct au_dpage *dpage; -+ struct dentry **dentries; -+ -+ err = au_dpages_init(&dpages, GFP_NOFS); -+ AuDebugOn(err); -+ err = au_dcsub_pages_rev_aufs(&dpages, parent, /*do_include*/1); -+ AuDebugOn(err); -+ for (i = dpages.ndpage - 1; !err && i >= 0; i--) { -+ dpage = dpages.dpages + i; -+ dentries = dpage->dentries; -+ for (j = dpage->ndentry - 1; !err && j >= 0; j--) -+ AuDebugOn(au_digen_test(dentries[j], sigen)); -+ } -+ au_dpages_free(&dpages); -+} -+ -+void au_dbg_verify_kthread(void) -+{ -+ if (au_wkq_test()) { -+ au_dbg_blocked(); -+ /* -+ * It may be recursive, but udba=notify between two aufs mounts, -+ * where a single ro branch is shared, is not a problem. -+ */ -+ /* WARN_ON(1); */ -+ } -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+int __init au_debug_init(void) -+{ -+ aufs_bindex_t bindex; -+ struct au_vdir_destr destr; -+ -+ bindex = -1; -+ AuDebugOn(bindex >= 0); -+ -+ destr.len = -1; -+ AuDebugOn(destr.len < NAME_MAX); -+ -+#ifdef CONFIG_4KSTACKS -+ pr_warn("CONFIG_4KSTACKS is defined.\n"); -+#endif -+ -+ return 0; -+} -diff -Nurp linux-5.6.3/fs/aufs/debug.h linux-5.6.3-aufs/fs/aufs/debug.h ---- linux-5.6.3/fs/aufs/debug.h 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/debug.h 2020-04-10 12:40:52.189049362 +0300 -@@ -0,0 +1,213 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * debug print functions -+ */ -+ -+#ifndef __AUFS_DEBUG_H__ -+#define __AUFS_DEBUG_H__ -+ -+#ifdef __KERNEL__ -+ -+#include -+#include -+#include -+#include -+ -+#ifdef CONFIG_AUFS_DEBUG -+#define AuDebugOn(a) BUG_ON(a) -+ -+/* module parameter */ -+extern atomic_t aufs_debug; -+static inline void au_debug_on(void) -+{ -+ atomic_inc(&aufs_debug); -+} -+static inline void au_debug_off(void) -+{ -+ atomic_dec_if_positive(&aufs_debug); -+} -+ -+static inline int au_debug_test(void) -+{ -+ return atomic_read(&aufs_debug) > 0; -+} -+#else -+#define AuDebugOn(a) do {} while (0) -+AuStubVoid(au_debug_on, void) -+AuStubVoid(au_debug_off, void) -+AuStubInt0(au_debug_test, void) -+#endif /* CONFIG_AUFS_DEBUG */ -+ -+#define param_check_atomic_t(name, p) __param_check(name, p, atomic_t) -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* debug print */ -+ -+#define AuDbg(fmt, ...) do { \ -+ if (au_debug_test()) \ -+ pr_debug("DEBUG: " fmt, ##__VA_ARGS__); \ -+} while (0) -+#define AuLabel(l) AuDbg(#l "\n") -+#define AuIOErr(fmt, ...) pr_err("I/O Error, " fmt, ##__VA_ARGS__) -+#define AuWarn1(fmt, ...) do { \ -+ static unsigned char _c; \ -+ if (!_c++) \ -+ pr_warn(fmt, ##__VA_ARGS__); \ -+} while (0) -+ -+#define AuErr1(fmt, ...) do { \ -+ static unsigned char _c; \ -+ if (!_c++) \ -+ pr_err(fmt, ##__VA_ARGS__); \ -+} while (0) -+ -+#define AuIOErr1(fmt, ...) do { \ -+ static unsigned char _c; \ -+ if (!_c++) \ -+ AuIOErr(fmt, ##__VA_ARGS__); \ -+} while (0) -+ -+#define AuUnsupportMsg "This operation is not supported." \ -+ " Please report this application to aufs-users ML." -+#define AuUnsupport(fmt, ...) do { \ -+ pr_err(AuUnsupportMsg "\n" fmt, ##__VA_ARGS__); \ -+ dump_stack(); \ -+} while (0) -+ -+#define AuTraceErr(e) do { \ -+ if (unlikely((e) < 0)) \ -+ AuDbg("err %d\n", (int)(e)); \ -+} while (0) -+ -+#define AuTraceErrPtr(p) do { \ -+ if (IS_ERR(p)) \ -+ AuDbg("err %ld\n", PTR_ERR(p)); \ -+} while (0) -+ -+/* dirty macros for debug print, use with "%.*s" and caution */ -+#define AuLNPair(qstr) (qstr)->len, (qstr)->name -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct dentry; -+#ifdef CONFIG_AUFS_DEBUG -+extern struct mutex au_dbg_mtx; -+extern char *au_plevel; -+struct au_nhash; -+void au_dpri_whlist(struct au_nhash *whlist); -+struct au_vdir; -+void au_dpri_vdir(struct au_vdir *vdir); -+struct inode; -+void au_dpri_inode(struct inode *inode); -+void au_dpri_dalias(struct inode *inode); -+void au_dpri_dentry(struct dentry *dentry); -+struct file; -+void au_dpri_file(struct file *filp); -+struct super_block; -+void au_dpri_sb(struct super_block *sb); -+ -+#define au_dbg_verify_dinode(d) __au_dbg_verify_dinode(d, __func__, __LINE__) -+void __au_dbg_verify_dinode(struct dentry *dentry, const char *func, int line); -+void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen); -+void au_dbg_verify_kthread(void); -+ -+int __init au_debug_init(void); -+ -+#define AuDbgWhlist(w) do { \ -+ mutex_lock(&au_dbg_mtx); \ -+ AuDbg(#w "\n"); \ -+ au_dpri_whlist(w); \ -+ mutex_unlock(&au_dbg_mtx); \ -+} while (0) -+ -+#define AuDbgVdir(v) do { \ -+ mutex_lock(&au_dbg_mtx); \ -+ AuDbg(#v "\n"); \ -+ au_dpri_vdir(v); \ -+ mutex_unlock(&au_dbg_mtx); \ -+} while (0) -+ -+#define AuDbgInode(i) do { \ -+ mutex_lock(&au_dbg_mtx); \ -+ AuDbg(#i "\n"); \ -+ au_dpri_inode(i); \ -+ mutex_unlock(&au_dbg_mtx); \ -+} while (0) -+ -+#define AuDbgDAlias(i) do { \ -+ mutex_lock(&au_dbg_mtx); \ -+ AuDbg(#i "\n"); \ -+ au_dpri_dalias(i); \ -+ mutex_unlock(&au_dbg_mtx); \ -+} while (0) -+ -+#define AuDbgDentry(d) do { \ -+ mutex_lock(&au_dbg_mtx); \ -+ AuDbg(#d "\n"); \ -+ au_dpri_dentry(d); \ -+ mutex_unlock(&au_dbg_mtx); \ -+} while (0) -+ -+#define AuDbgFile(f) do { \ -+ mutex_lock(&au_dbg_mtx); \ -+ AuDbg(#f "\n"); \ -+ au_dpri_file(f); \ -+ mutex_unlock(&au_dbg_mtx); \ -+} while (0) -+ -+#define AuDbgSb(sb) do { \ -+ mutex_lock(&au_dbg_mtx); \ -+ AuDbg(#sb "\n"); \ -+ au_dpri_sb(sb); \ -+ mutex_unlock(&au_dbg_mtx); \ -+} while (0) -+ -+#define AuDbgSym(addr) do { \ -+ char sym[KSYM_SYMBOL_LEN]; \ -+ sprint_symbol(sym, (unsigned long)addr); \ -+ AuDbg("%s\n", sym); \ -+} while (0) -+#else -+AuStubVoid(au_dbg_verify_dinode, struct dentry *dentry) -+AuStubVoid(au_dbg_verify_gen, struct dentry *parent, unsigned int sigen) -+AuStubVoid(au_dbg_verify_kthread, void) -+AuStubInt0(__init au_debug_init, void) -+ -+#define AuDbgWhlist(w) do {} while (0) -+#define AuDbgVdir(v) do {} while (0) -+#define AuDbgInode(i) do {} while (0) -+#define AuDbgDAlias(i) do {} while (0) -+#define AuDbgDentry(d) do {} while (0) -+#define AuDbgFile(f) do {} while (0) -+#define AuDbgSb(sb) do {} while (0) -+#define AuDbgSym(addr) do {} while (0) -+#endif /* CONFIG_AUFS_DEBUG */ -+ -+/* ---------------------------------------------------------------------- */ -+ -+#ifdef CONFIG_AUFS_MAGIC_SYSRQ -+int __init au_sysrq_init(void); -+void au_sysrq_fin(void); -+ -+#ifdef CONFIG_HW_CONSOLE -+#define au_dbg_blocked() do { \ -+ WARN_ON(1); \ -+ handle_sysrq('w'); \ -+} while (0) -+#else -+AuStubVoid(au_dbg_blocked, void) -+#endif -+ -+#else -+AuStubInt0(__init au_sysrq_init, void) -+AuStubVoid(au_sysrq_fin, void) -+AuStubVoid(au_dbg_blocked, void) -+#endif /* CONFIG_AUFS_MAGIC_SYSRQ */ -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_DEBUG_H__ */ -diff -Nurp linux-5.6.3/fs/aufs/dentry.c linux-5.6.3-aufs/fs/aufs/dentry.c ---- linux-5.6.3/fs/aufs/dentry.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/dentry.c 2020-04-10 12:40:52.189049362 +0300 -@@ -0,0 +1,1141 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * lookup and dentry operations -+ */ -+ -+#include -+#include -+#include "aufs.h" -+ -+/* -+ * returns positive/negative dentry, NULL or an error. -+ * NULL means whiteout-ed or not-found. -+ */ -+static struct dentry* -+au_do_lookup(struct dentry *h_parent, struct dentry *dentry, -+ aufs_bindex_t bindex, struct au_do_lookup_args *args) -+{ -+ struct dentry *h_dentry; -+ struct inode *h_inode; -+ struct au_branch *br; -+ int wh_found, opq; -+ unsigned char wh_able; -+ const unsigned char allow_neg = !!au_ftest_lkup(args->flags, ALLOW_NEG); -+ const unsigned char ignore_perm = !!au_ftest_lkup(args->flags, -+ IGNORE_PERM); -+ -+ wh_found = 0; -+ br = au_sbr(dentry->d_sb, bindex); -+ wh_able = !!au_br_whable(br->br_perm); -+ if (wh_able) -+ wh_found = au_wh_test(h_parent, &args->whname, ignore_perm); -+ h_dentry = ERR_PTR(wh_found); -+ if (!wh_found) -+ goto real_lookup; -+ if (unlikely(wh_found < 0)) -+ goto out; -+ -+ /* We found a whiteout */ -+ /* au_set_dbbot(dentry, bindex); */ -+ au_set_dbwh(dentry, bindex); -+ if (!allow_neg) -+ return NULL; /* success */ -+ -+real_lookup: -+ if (!ignore_perm) -+ h_dentry = vfsub_lkup_one(args->name, h_parent); -+ else -+ h_dentry = au_sio_lkup_one(args->name, h_parent); -+ if (IS_ERR(h_dentry)) { -+ if (PTR_ERR(h_dentry) == -ENAMETOOLONG -+ && !allow_neg) -+ h_dentry = NULL; -+ goto out; -+ } -+ -+ h_inode = d_inode(h_dentry); -+ if (d_is_negative(h_dentry)) { -+ if (!allow_neg) -+ goto out_neg; -+ } else if (wh_found -+ || (args->type && args->type != (h_inode->i_mode & S_IFMT))) -+ goto out_neg; -+ else if (au_ftest_lkup(args->flags, DIRREN) -+ /* && h_inode */ -+ && !au_dr_lkup_h_ino(args, bindex, h_inode->i_ino)) { -+ AuDbg("b%d %pd ignored hi%llu\n", bindex, h_dentry, -+ (unsigned long long)h_inode->i_ino); -+ goto out_neg; -+ } -+ -+ if (au_dbbot(dentry) <= bindex) -+ au_set_dbbot(dentry, bindex); -+ if (au_dbtop(dentry) < 0 || bindex < au_dbtop(dentry)) -+ au_set_dbtop(dentry, bindex); -+ au_set_h_dptr(dentry, bindex, h_dentry); -+ -+ if (!d_is_dir(h_dentry) -+ || !wh_able -+ || (d_really_is_positive(dentry) && !d_is_dir(dentry))) -+ goto out; /* success */ -+ -+ inode_lock_shared_nested(h_inode, AuLsc_I_CHILD); -+ opq = au_diropq_test(h_dentry); -+ inode_unlock_shared(h_inode); -+ if (opq > 0) -+ au_set_dbdiropq(dentry, bindex); -+ else if (unlikely(opq < 0)) { -+ au_set_h_dptr(dentry, bindex, NULL); -+ h_dentry = ERR_PTR(opq); -+ } -+ goto out; -+ -+out_neg: -+ dput(h_dentry); -+ h_dentry = NULL; -+out: -+ return h_dentry; -+} -+ -+static int au_test_shwh(struct super_block *sb, const struct qstr *name) -+{ -+ if (unlikely(!au_opt_test(au_mntflags(sb), SHWH) -+ && !strncmp(name->name, AUFS_WH_PFX, AUFS_WH_PFX_LEN))) -+ return -EPERM; -+ return 0; -+} -+ -+/* -+ * returns the number of lower positive dentries, -+ * otherwise an error. -+ * can be called at unlinking with @type is zero. -+ */ -+int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t btop, -+ unsigned int flags) -+{ -+ int npositive, err; -+ aufs_bindex_t bindex, btail, bdiropq; -+ unsigned char isdir, dirperm1, dirren; -+ struct au_do_lookup_args args = { -+ .flags = flags, -+ .name = &dentry->d_name -+ }; -+ struct dentry *parent; -+ struct super_block *sb; -+ -+ sb = dentry->d_sb; -+ err = au_test_shwh(sb, args.name); -+ if (unlikely(err)) -+ goto out; -+ -+ err = au_wh_name_alloc(&args.whname, args.name); -+ if (unlikely(err)) -+ goto out; -+ -+ isdir = !!d_is_dir(dentry); -+ dirperm1 = !!au_opt_test(au_mntflags(sb), DIRPERM1); -+ dirren = !!au_opt_test(au_mntflags(sb), DIRREN); -+ if (dirren) -+ au_fset_lkup(args.flags, DIRREN); -+ -+ npositive = 0; -+ parent = dget_parent(dentry); -+ btail = au_dbtaildir(parent); -+ for (bindex = btop; bindex <= btail; bindex++) { -+ struct dentry *h_parent, *h_dentry; -+ struct inode *h_inode, *h_dir; -+ struct au_branch *br; -+ -+ h_dentry = au_h_dptr(dentry, bindex); -+ if (h_dentry) { -+ if (d_is_positive(h_dentry)) -+ npositive++; -+ break; -+ } -+ h_parent = au_h_dptr(parent, bindex); -+ if (!h_parent || !d_is_dir(h_parent)) -+ continue; -+ -+ if (dirren) { -+ /* if the inum matches, then use the prepared name */ -+ err = au_dr_lkup_name(&args, bindex); -+ if (unlikely(err)) -+ goto out_parent; -+ } -+ -+ h_dir = d_inode(h_parent); -+ inode_lock_shared_nested(h_dir, AuLsc_I_PARENT); -+ h_dentry = au_do_lookup(h_parent, dentry, bindex, &args); -+ inode_unlock_shared(h_dir); -+ err = PTR_ERR(h_dentry); -+ if (IS_ERR(h_dentry)) -+ goto out_parent; -+ if (h_dentry) -+ au_fclr_lkup(args.flags, ALLOW_NEG); -+ if (dirperm1) -+ au_fset_lkup(args.flags, IGNORE_PERM); -+ -+ if (au_dbwh(dentry) == bindex) -+ break; -+ if (!h_dentry) -+ continue; -+ if (d_is_negative(h_dentry)) -+ continue; -+ h_inode = d_inode(h_dentry); -+ npositive++; -+ if (!args.type) -+ args.type = h_inode->i_mode & S_IFMT; -+ if (args.type != S_IFDIR) -+ break; -+ else if (isdir) { -+ /* the type of lower may be different */ -+ bdiropq = au_dbdiropq(dentry); -+ if (bdiropq >= 0 && bdiropq <= bindex) -+ break; -+ } -+ br = au_sbr(sb, bindex); -+ if (dirren -+ && au_dr_hino_test_add(&br->br_dirren, h_inode->i_ino, -+ /*add_ent*/NULL)) { -+ /* prepare next name to lookup */ -+ err = au_dr_lkup(&args, dentry, bindex); -+ if (unlikely(err)) -+ goto out_parent; -+ } -+ } -+ -+ if (npositive) { -+ AuLabel(positive); -+ au_update_dbtop(dentry); -+ } -+ err = npositive; -+ if (unlikely(!au_opt_test(au_mntflags(sb), UDBA_NONE) -+ && au_dbtop(dentry) < 0)) { -+ err = -EIO; -+ AuIOErr("both of real entry and whiteout found, %pd, err %d\n", -+ dentry, err); -+ } -+ -+out_parent: -+ dput(parent); -+ au_kfree_try_rcu(args.whname.name); -+ if (dirren) -+ au_dr_lkup_fin(&args); -+out: -+ return err; -+} -+ -+struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent) -+{ -+ struct dentry *dentry; -+ int wkq_err; -+ -+ if (!au_test_h_perm_sio(d_inode(parent), MAY_EXEC)) -+ dentry = vfsub_lkup_one(name, parent); -+ else { -+ struct vfsub_lkup_one_args args = { -+ .errp = &dentry, -+ .name = name, -+ .parent = parent -+ }; -+ -+ wkq_err = au_wkq_wait(vfsub_call_lkup_one, &args); -+ if (unlikely(wkq_err)) -+ dentry = ERR_PTR(wkq_err); -+ } -+ -+ return dentry; -+} -+ -+/* -+ * lookup @dentry on @bindex which should be negative. -+ */ -+int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex, int wh) -+{ -+ int err; -+ struct dentry *parent, *h_parent, *h_dentry; -+ struct au_branch *br; -+ -+ parent = dget_parent(dentry); -+ h_parent = au_h_dptr(parent, bindex); -+ br = au_sbr(dentry->d_sb, bindex); -+ if (wh) -+ h_dentry = au_whtmp_lkup(h_parent, br, &dentry->d_name); -+ else -+ h_dentry = au_sio_lkup_one(&dentry->d_name, h_parent); -+ err = PTR_ERR(h_dentry); -+ if (IS_ERR(h_dentry)) -+ goto out; -+ if (unlikely(d_is_positive(h_dentry))) { -+ err = -EIO; -+ AuIOErr("%pd should be negative on b%d.\n", h_dentry, bindex); -+ dput(h_dentry); -+ goto out; -+ } -+ -+ err = 0; -+ if (bindex < au_dbtop(dentry)) -+ au_set_dbtop(dentry, bindex); -+ if (au_dbbot(dentry) < bindex) -+ au_set_dbbot(dentry, bindex); -+ au_set_h_dptr(dentry, bindex, h_dentry); -+ -+out: -+ dput(parent); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* subset of struct inode */ -+struct au_iattr { -+ unsigned long i_ino; -+ /* unsigned int i_nlink; */ -+ kuid_t i_uid; -+ kgid_t i_gid; -+ u64 i_version; -+/* -+ loff_t i_size; -+ blkcnt_t i_blocks; -+*/ -+ umode_t i_mode; -+}; -+ -+static void au_iattr_save(struct au_iattr *ia, struct inode *h_inode) -+{ -+ ia->i_ino = h_inode->i_ino; -+ /* ia->i_nlink = h_inode->i_nlink; */ -+ ia->i_uid = h_inode->i_uid; -+ ia->i_gid = h_inode->i_gid; -+ ia->i_version = inode_query_iversion(h_inode); -+/* -+ ia->i_size = h_inode->i_size; -+ ia->i_blocks = h_inode->i_blocks; -+*/ -+ ia->i_mode = (h_inode->i_mode & S_IFMT); -+} -+ -+static int au_iattr_test(struct au_iattr *ia, struct inode *h_inode) -+{ -+ return ia->i_ino != h_inode->i_ino -+ /* || ia->i_nlink != h_inode->i_nlink */ -+ || !uid_eq(ia->i_uid, h_inode->i_uid) -+ || !gid_eq(ia->i_gid, h_inode->i_gid) -+ || !inode_eq_iversion(h_inode, ia->i_version) -+/* -+ || ia->i_size != h_inode->i_size -+ || ia->i_blocks != h_inode->i_blocks -+*/ -+ || ia->i_mode != (h_inode->i_mode & S_IFMT); -+} -+ -+static int au_h_verify_dentry(struct dentry *h_dentry, struct dentry *h_parent, -+ struct au_branch *br) -+{ -+ int err; -+ struct au_iattr ia; -+ struct inode *h_inode; -+ struct dentry *h_d; -+ struct super_block *h_sb; -+ -+ err = 0; -+ memset(&ia, -1, sizeof(ia)); -+ h_sb = h_dentry->d_sb; -+ h_inode = NULL; -+ if (d_is_positive(h_dentry)) { -+ h_inode = d_inode(h_dentry); -+ au_iattr_save(&ia, h_inode); -+ } else if (au_test_nfs(h_sb) || au_test_fuse(h_sb)) -+ /* nfs d_revalidate may return 0 for negative dentry */ -+ /* fuse d_revalidate always return 0 for negative dentry */ -+ goto out; -+ -+ /* main purpose is namei.c:cached_lookup() and d_revalidate */ -+ h_d = vfsub_lkup_one(&h_dentry->d_name, h_parent); -+ err = PTR_ERR(h_d); -+ if (IS_ERR(h_d)) -+ goto out; -+ -+ err = 0; -+ if (unlikely(h_d != h_dentry -+ || d_inode(h_d) != h_inode -+ || (h_inode && au_iattr_test(&ia, h_inode)))) -+ err = au_busy_or_stale(); -+ dput(h_d); -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir, -+ struct dentry *h_parent, struct au_branch *br) -+{ -+ int err; -+ -+ err = 0; -+ if (udba == AuOpt_UDBA_REVAL -+ && !au_test_fs_remote(h_dentry->d_sb)) { -+ IMustLock(h_dir); -+ err = (d_inode(h_dentry->d_parent) != h_dir); -+ } else if (udba != AuOpt_UDBA_NONE) -+ err = au_h_verify_dentry(h_dentry, h_parent, br); -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int au_do_refresh_hdentry(struct dentry *dentry, struct dentry *parent) -+{ -+ int err; -+ aufs_bindex_t new_bindex, bindex, bbot, bwh, bdiropq; -+ struct au_hdentry tmp, *p, *q; -+ struct au_dinfo *dinfo; -+ struct super_block *sb; -+ -+ DiMustWriteLock(dentry); -+ -+ sb = dentry->d_sb; -+ dinfo = au_di(dentry); -+ bbot = dinfo->di_bbot; -+ bwh = dinfo->di_bwh; -+ bdiropq = dinfo->di_bdiropq; -+ bindex = dinfo->di_btop; -+ p = au_hdentry(dinfo, bindex); -+ for (; bindex <= bbot; bindex++, p++) { -+ if (!p->hd_dentry) -+ continue; -+ -+ new_bindex = au_br_index(sb, p->hd_id); -+ if (new_bindex == bindex) -+ continue; -+ -+ if (dinfo->di_bwh == bindex) -+ bwh = new_bindex; -+ if (dinfo->di_bdiropq == bindex) -+ bdiropq = new_bindex; -+ if (new_bindex < 0) { -+ au_hdput(p); -+ p->hd_dentry = NULL; -+ continue; -+ } -+ -+ /* swap two lower dentries, and loop again */ -+ q = au_hdentry(dinfo, new_bindex); -+ tmp = *q; -+ *q = *p; -+ *p = tmp; -+ if (tmp.hd_dentry) { -+ bindex--; -+ p--; -+ } -+ } -+ -+ dinfo->di_bwh = -1; -+ if (bwh >= 0 && bwh <= au_sbbot(sb) && au_sbr_whable(sb, bwh)) -+ dinfo->di_bwh = bwh; -+ -+ dinfo->di_bdiropq = -1; -+ if (bdiropq >= 0 -+ && bdiropq <= au_sbbot(sb) -+ && au_sbr_whable(sb, bdiropq)) -+ dinfo->di_bdiropq = bdiropq; -+ -+ err = -EIO; -+ dinfo->di_btop = -1; -+ dinfo->di_bbot = -1; -+ bbot = au_dbbot(parent); -+ bindex = 0; -+ p = au_hdentry(dinfo, bindex); -+ for (; bindex <= bbot; bindex++, p++) -+ if (p->hd_dentry) { -+ dinfo->di_btop = bindex; -+ break; -+ } -+ -+ if (dinfo->di_btop >= 0) { -+ bindex = bbot; -+ p = au_hdentry(dinfo, bindex); -+ for (; bindex >= 0; bindex--, p--) -+ if (p->hd_dentry) { -+ dinfo->di_bbot = bindex; -+ err = 0; -+ break; -+ } -+ } -+ -+ return err; -+} -+ -+static void au_do_hide(struct dentry *dentry) -+{ -+ struct inode *inode; -+ -+ if (d_really_is_positive(dentry)) { -+ inode = d_inode(dentry); -+ if (!d_is_dir(dentry)) { -+ if (inode->i_nlink && !d_unhashed(dentry)) -+ drop_nlink(inode); -+ } else { -+ clear_nlink(inode); -+ /* stop next lookup */ -+ inode->i_flags |= S_DEAD; -+ } -+ smp_mb(); /* necessary? */ -+ } -+ d_drop(dentry); -+} -+ -+static int au_hide_children(struct dentry *parent) -+{ -+ int err, i, j, ndentry; -+ struct au_dcsub_pages dpages; -+ struct au_dpage *dpage; -+ struct dentry *dentry; -+ -+ err = au_dpages_init(&dpages, GFP_NOFS); -+ if (unlikely(err)) -+ goto out; -+ err = au_dcsub_pages(&dpages, parent, NULL, NULL); -+ if (unlikely(err)) -+ goto out_dpages; -+ -+ /* in reverse order */ -+ for (i = dpages.ndpage - 1; i >= 0; i--) { -+ dpage = dpages.dpages + i; -+ ndentry = dpage->ndentry; -+ for (j = ndentry - 1; j >= 0; j--) { -+ dentry = dpage->dentries[j]; -+ if (dentry != parent) -+ au_do_hide(dentry); -+ } -+ } -+ -+out_dpages: -+ au_dpages_free(&dpages); -+out: -+ return err; -+} -+ -+static void au_hide(struct dentry *dentry) -+{ -+ int err; -+ -+ AuDbgDentry(dentry); -+ if (d_is_dir(dentry)) { -+ /* shrink_dcache_parent(dentry); */ -+ err = au_hide_children(dentry); -+ if (unlikely(err)) -+ AuIOErr("%pd, failed hiding children, ignored %d\n", -+ dentry, err); -+ } -+ au_do_hide(dentry); -+} -+ -+/* -+ * By adding a dirty branch, a cached dentry may be affected in various ways. -+ * -+ * a dirty branch is added -+ * - on the top of layers -+ * - in the middle of layers -+ * - to the bottom of layers -+ * -+ * on the added branch there exists -+ * - a whiteout -+ * - a diropq -+ * - a same named entry -+ * + exist -+ * * negative --> positive -+ * * positive --> positive -+ * - type is unchanged -+ * - type is changed -+ * + doesn't exist -+ * * negative --> negative -+ * * positive --> negative (rejected by au_br_del() for non-dir case) -+ * - none -+ */ -+static int au_refresh_by_dinfo(struct dentry *dentry, struct au_dinfo *dinfo, -+ struct au_dinfo *tmp) -+{ -+ int err; -+ aufs_bindex_t bindex, bbot; -+ struct { -+ struct dentry *dentry; -+ struct inode *inode; -+ mode_t mode; -+ } orig_h, tmp_h = { -+ .dentry = NULL -+ }; -+ struct au_hdentry *hd; -+ struct inode *inode, *h_inode; -+ struct dentry *h_dentry; -+ -+ err = 0; -+ AuDebugOn(dinfo->di_btop < 0); -+ orig_h.mode = 0; -+ orig_h.dentry = au_hdentry(dinfo, dinfo->di_btop)->hd_dentry; -+ orig_h.inode = NULL; -+ if (d_is_positive(orig_h.dentry)) { -+ orig_h.inode = d_inode(orig_h.dentry); -+ orig_h.mode = orig_h.inode->i_mode & S_IFMT; -+ } -+ if (tmp->di_btop >= 0) { -+ tmp_h.dentry = au_hdentry(tmp, tmp->di_btop)->hd_dentry; -+ if (d_is_positive(tmp_h.dentry)) { -+ tmp_h.inode = d_inode(tmp_h.dentry); -+ tmp_h.mode = tmp_h.inode->i_mode & S_IFMT; -+ } -+ } -+ -+ inode = NULL; -+ if (d_really_is_positive(dentry)) -+ inode = d_inode(dentry); -+ if (!orig_h.inode) { -+ AuDbg("negative originally\n"); -+ if (inode) { -+ au_hide(dentry); -+ goto out; -+ } -+ AuDebugOn(inode); -+ AuDebugOn(dinfo->di_btop != dinfo->di_bbot); -+ AuDebugOn(dinfo->di_bdiropq != -1); -+ -+ if (!tmp_h.inode) { -+ AuDbg("negative --> negative\n"); -+ /* should have only one negative lower */ -+ if (tmp->di_btop >= 0 -+ && tmp->di_btop < dinfo->di_btop) { -+ AuDebugOn(tmp->di_btop != tmp->di_bbot); -+ AuDebugOn(dinfo->di_btop != dinfo->di_bbot); -+ au_set_h_dptr(dentry, dinfo->di_btop, NULL); -+ au_di_cp(dinfo, tmp); -+ hd = au_hdentry(tmp, tmp->di_btop); -+ au_set_h_dptr(dentry, tmp->di_btop, -+ dget(hd->hd_dentry)); -+ } -+ au_dbg_verify_dinode(dentry); -+ } else { -+ AuDbg("negative --> positive\n"); -+ /* -+ * similar to the behaviour of creating with bypassing -+ * aufs. -+ * unhash it in order to force an error in the -+ * succeeding create operation. -+ * we should not set S_DEAD here. -+ */ -+ d_drop(dentry); -+ /* au_di_swap(tmp, dinfo); */ -+ au_dbg_verify_dinode(dentry); -+ } -+ } else { -+ AuDbg("positive originally\n"); -+ /* inode may be NULL */ -+ AuDebugOn(inode && (inode->i_mode & S_IFMT) != orig_h.mode); -+ if (!tmp_h.inode) { -+ AuDbg("positive --> negative\n"); -+ /* or bypassing aufs */ -+ au_hide(dentry); -+ if (tmp->di_bwh >= 0 && tmp->di_bwh <= dinfo->di_btop) -+ dinfo->di_bwh = tmp->di_bwh; -+ if (inode) -+ err = au_refresh_hinode_self(inode); -+ au_dbg_verify_dinode(dentry); -+ } else if (orig_h.mode == tmp_h.mode) { -+ AuDbg("positive --> positive, same type\n"); -+ if (!S_ISDIR(orig_h.mode) -+ && dinfo->di_btop > tmp->di_btop) { -+ /* -+ * similar to the behaviour of removing and -+ * creating. -+ */ -+ au_hide(dentry); -+ if (inode) -+ err = au_refresh_hinode_self(inode); -+ au_dbg_verify_dinode(dentry); -+ } else { -+ /* fill empty slots */ -+ if (dinfo->di_btop > tmp->di_btop) -+ dinfo->di_btop = tmp->di_btop; -+ if (dinfo->di_bbot < tmp->di_bbot) -+ dinfo->di_bbot = tmp->di_bbot; -+ dinfo->di_bwh = tmp->di_bwh; -+ dinfo->di_bdiropq = tmp->di_bdiropq; -+ bbot = dinfo->di_bbot; -+ bindex = tmp->di_btop; -+ hd = au_hdentry(tmp, bindex); -+ for (; bindex <= bbot; bindex++, hd++) { -+ if (au_h_dptr(dentry, bindex)) -+ continue; -+ h_dentry = hd->hd_dentry; -+ if (!h_dentry) -+ continue; -+ AuDebugOn(d_is_negative(h_dentry)); -+ h_inode = d_inode(h_dentry); -+ AuDebugOn(orig_h.mode -+ != (h_inode->i_mode -+ & S_IFMT)); -+ au_set_h_dptr(dentry, bindex, -+ dget(h_dentry)); -+ } -+ if (inode) -+ err = au_refresh_hinode(inode, dentry); -+ au_dbg_verify_dinode(dentry); -+ } -+ } else { -+ AuDbg("positive --> positive, different type\n"); -+ /* similar to the behaviour of removing and creating */ -+ au_hide(dentry); -+ if (inode) -+ err = au_refresh_hinode_self(inode); -+ au_dbg_verify_dinode(dentry); -+ } -+ } -+ -+out: -+ return err; -+} -+ -+void au_refresh_dop(struct dentry *dentry, int force_reval) -+{ -+ const struct dentry_operations *dop -+ = force_reval ? &aufs_dop : dentry->d_sb->s_d_op; -+ static const unsigned int mask -+ = DCACHE_OP_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE; -+ -+ BUILD_BUG_ON(sizeof(mask) != sizeof(dentry->d_flags)); -+ -+ if (dentry->d_op == dop) -+ return; -+ -+ AuDbg("%pd\n", dentry); -+ spin_lock(&dentry->d_lock); -+ if (dop == &aufs_dop) -+ dentry->d_flags |= mask; -+ else -+ dentry->d_flags &= ~mask; -+ dentry->d_op = dop; -+ spin_unlock(&dentry->d_lock); -+} -+ -+int au_refresh_dentry(struct dentry *dentry, struct dentry *parent) -+{ -+ int err, ebrange, nbr; -+ unsigned int sigen; -+ struct au_dinfo *dinfo, *tmp; -+ struct super_block *sb; -+ struct inode *inode; -+ -+ DiMustWriteLock(dentry); -+ AuDebugOn(IS_ROOT(dentry)); -+ AuDebugOn(d_really_is_negative(parent)); -+ -+ sb = dentry->d_sb; -+ sigen = au_sigen(sb); -+ err = au_digen_test(parent, sigen); -+ if (unlikely(err)) -+ goto out; -+ -+ nbr = au_sbbot(sb) + 1; -+ dinfo = au_di(dentry); -+ err = au_di_realloc(dinfo, nbr, /*may_shrink*/0); -+ if (unlikely(err)) -+ goto out; -+ ebrange = au_dbrange_test(dentry); -+ if (!ebrange) -+ ebrange = au_do_refresh_hdentry(dentry, parent); -+ -+ if (d_unhashed(dentry) || ebrange /* || dinfo->di_tmpfile */) { -+ AuDebugOn(au_dbtop(dentry) < 0 && au_dbbot(dentry) >= 0); -+ if (d_really_is_positive(dentry)) { -+ inode = d_inode(dentry); -+ err = au_refresh_hinode_self(inode); -+ } -+ au_dbg_verify_dinode(dentry); -+ if (!err) -+ goto out_dgen; /* success */ -+ goto out; -+ } -+ -+ /* temporary dinfo */ -+ AuDbgDentry(dentry); -+ err = -ENOMEM; -+ tmp = au_di_alloc(sb, AuLsc_DI_TMP); -+ if (unlikely(!tmp)) -+ goto out; -+ au_di_swap(tmp, dinfo); -+ /* returns the number of positive dentries */ -+ /* -+ * if current working dir is removed, it returns an error. -+ * but the dentry is legal. -+ */ -+ err = au_lkup_dentry(dentry, /*btop*/0, AuLkup_ALLOW_NEG); -+ AuDbgDentry(dentry); -+ au_di_swap(tmp, dinfo); -+ if (err == -ENOENT) -+ err = 0; -+ if (err >= 0) { -+ /* compare/refresh by dinfo */ -+ AuDbgDentry(dentry); -+ err = au_refresh_by_dinfo(dentry, dinfo, tmp); -+ au_dbg_verify_dinode(dentry); -+ AuTraceErr(err); -+ } -+ au_di_realloc(dinfo, nbr, /*may_shrink*/1); /* harmless if err */ -+ au_rw_write_unlock(&tmp->di_rwsem); -+ au_di_free(tmp); -+ if (unlikely(err)) -+ goto out; -+ -+out_dgen: -+ au_update_digen(dentry); -+out: -+ if (unlikely(err && !(dentry->d_flags & DCACHE_NFSFS_RENAMED))) { -+ AuIOErr("failed refreshing %pd, %d\n", dentry, err); -+ AuDbgDentry(dentry); -+ } -+ AuTraceErr(err); -+ return err; -+} -+ -+static int au_do_h_d_reval(struct dentry *h_dentry, unsigned int flags, -+ struct dentry *dentry, aufs_bindex_t bindex) -+{ -+ int err, valid; -+ -+ err = 0; -+ if (!(h_dentry->d_flags & DCACHE_OP_REVALIDATE)) -+ goto out; -+ -+ AuDbg("b%d\n", bindex); -+ /* -+ * gave up supporting LOOKUP_CREATE/OPEN for lower fs, -+ * due to whiteout and branch permission. -+ */ -+ flags &= ~(/*LOOKUP_PARENT |*/ LOOKUP_OPEN | LOOKUP_CREATE -+ | LOOKUP_FOLLOW | LOOKUP_EXCL); -+ /* it may return tri-state */ -+ valid = h_dentry->d_op->d_revalidate(h_dentry, flags); -+ -+ if (unlikely(valid < 0)) -+ err = valid; -+ else if (!valid) -+ err = -EINVAL; -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+/* todo: remove this */ -+static int h_d_revalidate(struct dentry *dentry, struct inode *inode, -+ unsigned int flags, int do_udba, int dirren) -+{ -+ int err; -+ umode_t mode, h_mode; -+ aufs_bindex_t bindex, btail, btop, ibs, ibe; -+ unsigned char plus, unhashed, is_root, h_plus, h_nfs, tmpfile; -+ struct inode *h_inode, *h_cached_inode; -+ struct dentry *h_dentry; -+ struct qstr *name, *h_name; -+ -+ err = 0; -+ plus = 0; -+ mode = 0; -+ ibs = -1; -+ ibe = -1; -+ unhashed = !!d_unhashed(dentry); -+ is_root = !!IS_ROOT(dentry); -+ name = &dentry->d_name; -+ tmpfile = au_di(dentry)->di_tmpfile; -+ -+ /* -+ * Theoretically, REVAL test should be unnecessary in case of -+ * {FS,I}NOTIFY. -+ * But {fs,i}notify doesn't fire some necessary events, -+ * IN_ATTRIB for atime/nlink/pageio -+ * Let's do REVAL test too. -+ */ -+ if (do_udba && inode) { -+ mode = (inode->i_mode & S_IFMT); -+ plus = (inode->i_nlink > 0); -+ ibs = au_ibtop(inode); -+ ibe = au_ibbot(inode); -+ } -+ -+ btop = au_dbtop(dentry); -+ btail = btop; -+ if (inode && S_ISDIR(inode->i_mode)) -+ btail = au_dbtaildir(dentry); -+ for (bindex = btop; bindex <= btail; bindex++) { -+ h_dentry = au_h_dptr(dentry, bindex); -+ if (!h_dentry) -+ continue; -+ -+ AuDbg("b%d, %pd\n", bindex, h_dentry); -+ h_nfs = !!au_test_nfs(h_dentry->d_sb); -+ spin_lock(&h_dentry->d_lock); -+ h_name = &h_dentry->d_name; -+ if (unlikely(do_udba -+ && !is_root -+ && ((!h_nfs -+ && (unhashed != !!d_unhashed(h_dentry) -+ || (!tmpfile && !dirren -+ && !au_qstreq(name, h_name)) -+ )) -+ || (h_nfs -+ && !(flags & LOOKUP_OPEN) -+ && (h_dentry->d_flags -+ & DCACHE_NFSFS_RENAMED))) -+ )) { -+ int h_unhashed; -+ -+ h_unhashed = d_unhashed(h_dentry); -+ spin_unlock(&h_dentry->d_lock); -+ AuDbg("unhash 0x%x 0x%x, %pd %pd\n", -+ unhashed, h_unhashed, dentry, h_dentry); -+ goto err; -+ } -+ spin_unlock(&h_dentry->d_lock); -+ -+ err = au_do_h_d_reval(h_dentry, flags, dentry, bindex); -+ if (unlikely(err)) -+ /* do not goto err, to keep the errno */ -+ break; -+ -+ /* todo: plink too? */ -+ if (!do_udba) -+ continue; -+ -+ /* UDBA tests */ -+ if (unlikely(!!inode != d_is_positive(h_dentry))) -+ goto err; -+ -+ h_inode = NULL; -+ if (d_is_positive(h_dentry)) -+ h_inode = d_inode(h_dentry); -+ h_plus = plus; -+ h_mode = mode; -+ h_cached_inode = h_inode; -+ if (h_inode) { -+ h_mode = (h_inode->i_mode & S_IFMT); -+ h_plus = (h_inode->i_nlink > 0); -+ } -+ if (inode && ibs <= bindex && bindex <= ibe) -+ h_cached_inode = au_h_iptr(inode, bindex); -+ -+ if (!h_nfs) { -+ if (unlikely(plus != h_plus && !tmpfile)) -+ goto err; -+ } else { -+ if (unlikely(!(h_dentry->d_flags & DCACHE_NFSFS_RENAMED) -+ && !is_root -+ && !IS_ROOT(h_dentry) -+ && unhashed != d_unhashed(h_dentry))) -+ goto err; -+ } -+ if (unlikely(mode != h_mode -+ || h_cached_inode != h_inode)) -+ goto err; -+ continue; -+ -+err: -+ err = -EINVAL; -+ break; -+ } -+ -+ AuTraceErr(err); -+ return err; -+} -+ -+/* todo: consolidate with do_refresh() and au_reval_for_attr() */ -+static int simple_reval_dpath(struct dentry *dentry, unsigned int sigen) -+{ -+ int err; -+ struct dentry *parent; -+ -+ if (!au_digen_test(dentry, sigen)) -+ return 0; -+ -+ parent = dget_parent(dentry); -+ di_read_lock_parent(parent, AuLock_IR); -+ AuDebugOn(au_digen_test(parent, sigen)); -+ au_dbg_verify_gen(parent, sigen); -+ err = au_refresh_dentry(dentry, parent); -+ di_read_unlock(parent, AuLock_IR); -+ dput(parent); -+ AuTraceErr(err); -+ return err; -+} -+ -+int au_reval_dpath(struct dentry *dentry, unsigned int sigen) -+{ -+ int err; -+ struct dentry *d, *parent; -+ -+ if (!au_ftest_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIR)) -+ return simple_reval_dpath(dentry, sigen); -+ -+ /* slow loop, keep it simple and stupid */ -+ /* cf: au_cpup_dirs() */ -+ err = 0; -+ parent = NULL; -+ while (au_digen_test(dentry, sigen)) { -+ d = dentry; -+ while (1) { -+ dput(parent); -+ parent = dget_parent(d); -+ if (!au_digen_test(parent, sigen)) -+ break; -+ d = parent; -+ } -+ -+ if (d != dentry) -+ di_write_lock_child2(d); -+ -+ /* someone might update our dentry while we were sleeping */ -+ if (au_digen_test(d, sigen)) { -+ /* -+ * todo: consolidate with simple_reval_dpath(), -+ * do_refresh() and au_reval_for_attr(). -+ */ -+ di_read_lock_parent(parent, AuLock_IR); -+ err = au_refresh_dentry(d, parent); -+ di_read_unlock(parent, AuLock_IR); -+ } -+ -+ if (d != dentry) -+ di_write_unlock(d); -+ dput(parent); -+ if (unlikely(err)) -+ break; -+ } -+ -+ return err; -+} -+ -+/* -+ * if valid returns 1, otherwise 0. -+ */ -+static int aufs_d_revalidate(struct dentry *dentry, unsigned int flags) -+{ -+ int valid, err; -+ unsigned int sigen; -+ unsigned char do_udba, dirren; -+ struct super_block *sb; -+ struct inode *inode; -+ -+ /* todo: support rcu-walk? */ -+ if (flags & LOOKUP_RCU) -+ return -ECHILD; -+ -+ valid = 0; -+ if (unlikely(!au_di(dentry))) -+ goto out; -+ -+ valid = 1; -+ sb = dentry->d_sb; -+ /* -+ * todo: very ugly -+ * i_mutex of parent dir may be held, -+ * but we should not return 'invalid' due to busy. -+ */ -+ err = aufs_read_lock(dentry, AuLock_FLUSH | AuLock_DW | AuLock_NOPLM); -+ if (unlikely(err)) { -+ valid = err; -+ AuTraceErr(err); -+ goto out; -+ } -+ inode = NULL; -+ if (d_really_is_positive(dentry)) -+ inode = d_inode(dentry); -+ if (unlikely(inode && au_is_bad_inode(inode))) { -+ err = -EINVAL; -+ AuTraceErr(err); -+ goto out_dgrade; -+ } -+ if (unlikely(au_dbrange_test(dentry))) { -+ err = -EINVAL; -+ AuTraceErr(err); -+ goto out_dgrade; -+ } -+ -+ sigen = au_sigen(sb); -+ if (au_digen_test(dentry, sigen)) { -+ AuDebugOn(IS_ROOT(dentry)); -+ err = au_reval_dpath(dentry, sigen); -+ if (unlikely(err)) { -+ AuTraceErr(err); -+ goto out_dgrade; -+ } -+ } -+ di_downgrade_lock(dentry, AuLock_IR); -+ -+ err = -EINVAL; -+ if (!(flags & (LOOKUP_OPEN | LOOKUP_EMPTY)) -+ && inode -+ && !(inode->i_state && I_LINKABLE) -+ && (IS_DEADDIR(inode) || !inode->i_nlink)) { -+ AuTraceErr(err); -+ goto out_inval; -+ } -+ -+ do_udba = !au_opt_test(au_mntflags(sb), UDBA_NONE); -+ if (do_udba && inode) { -+ aufs_bindex_t btop = au_ibtop(inode); -+ struct inode *h_inode; -+ -+ if (btop >= 0) { -+ h_inode = au_h_iptr(inode, btop); -+ if (h_inode && au_test_higen(inode, h_inode)) { -+ AuTraceErr(err); -+ goto out_inval; -+ } -+ } -+ } -+ -+ dirren = !!au_opt_test(au_mntflags(sb), DIRREN); -+ err = h_d_revalidate(dentry, inode, flags, do_udba, dirren); -+ if (unlikely(!err && do_udba && au_dbtop(dentry) < 0)) { -+ err = -EIO; -+ AuDbg("both of real entry and whiteout found, %p, err %d\n", -+ dentry, err); -+ } -+ goto out_inval; -+ -+out_dgrade: -+ di_downgrade_lock(dentry, AuLock_IR); -+out_inval: -+ aufs_read_unlock(dentry, AuLock_IR); -+ AuTraceErr(err); -+ valid = !err; -+out: -+ if (!valid) { -+ AuDbg("%pd invalid, %d\n", dentry, valid); -+ d_drop(dentry); -+ } -+ return valid; -+} -+ -+static void aufs_d_release(struct dentry *dentry) -+{ -+ if (au_di(dentry)) { -+ au_di_fin(dentry); -+ au_hn_di_reinit(dentry); -+ } -+} -+ -+const struct dentry_operations aufs_dop = { -+ .d_revalidate = aufs_d_revalidate, -+ .d_weak_revalidate = aufs_d_revalidate, -+ .d_release = aufs_d_release -+}; -+ -+/* aufs_dop without d_revalidate */ -+const struct dentry_operations aufs_dop_noreval = { -+ .d_release = aufs_d_release -+}; -diff -Nurp linux-5.6.3/fs/aufs/dentry.h linux-5.6.3-aufs/fs/aufs/dentry.h ---- linux-5.6.3/fs/aufs/dentry.h 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/dentry.h 2020-04-10 12:40:52.189049362 +0300 -@@ -0,0 +1,255 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * lookup and dentry operations -+ */ -+ -+#ifndef __AUFS_DENTRY_H__ -+#define __AUFS_DENTRY_H__ -+ -+#ifdef __KERNEL__ -+ -+#include -+#include "dirren.h" -+#include "rwsem.h" -+ -+struct au_hdentry { -+ struct dentry *hd_dentry; -+ aufs_bindex_t hd_id; -+}; -+ -+struct au_dinfo { -+ atomic_t di_generation; -+ -+ struct au_rwsem di_rwsem; -+ aufs_bindex_t di_btop, di_bbot, di_bwh, di_bdiropq; -+ unsigned char di_tmpfile; /* to allow the different name */ -+ struct au_hdentry *di_hdentry; -+ struct rcu_head rcu; -+} ____cacheline_aligned_in_smp; -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* flags for au_lkup_dentry() */ -+#define AuLkup_ALLOW_NEG 1 -+#define AuLkup_IGNORE_PERM (1 << 1) -+#define AuLkup_DIRREN (1 << 2) -+#define au_ftest_lkup(flags, name) ((flags) & AuLkup_##name) -+#define au_fset_lkup(flags, name) \ -+ do { (flags) |= AuLkup_##name; } while (0) -+#define au_fclr_lkup(flags, name) \ -+ do { (flags) &= ~AuLkup_##name; } while (0) -+ -+#ifndef CONFIG_AUFS_DIRREN -+#undef AuLkup_DIRREN -+#define AuLkup_DIRREN 0 -+#endif -+ -+struct au_do_lookup_args { -+ unsigned int flags; -+ mode_t type; -+ struct qstr whname, *name; -+ struct au_dr_lookup dirren; -+}; -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* dentry.c */ -+extern const struct dentry_operations aufs_dop, aufs_dop_noreval; -+struct au_branch; -+struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent); -+int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir, -+ struct dentry *h_parent, struct au_branch *br); -+ -+int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t btop, -+ unsigned int flags); -+int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex, int wh); -+int au_refresh_dentry(struct dentry *dentry, struct dentry *parent); -+int au_reval_dpath(struct dentry *dentry, unsigned int sigen); -+void au_refresh_dop(struct dentry *dentry, int force_reval); -+ -+/* dinfo.c */ -+void au_di_init_once(void *_di); -+struct au_dinfo *au_di_alloc(struct super_block *sb, unsigned int lsc); -+void au_di_free(struct au_dinfo *dinfo); -+void au_di_swap(struct au_dinfo *a, struct au_dinfo *b); -+void au_di_cp(struct au_dinfo *dst, struct au_dinfo *src); -+int au_di_init(struct dentry *dentry); -+void au_di_fin(struct dentry *dentry); -+int au_di_realloc(struct au_dinfo *dinfo, int nbr, int may_shrink); -+ -+void di_read_lock(struct dentry *d, int flags, unsigned int lsc); -+void di_read_unlock(struct dentry *d, int flags); -+void di_downgrade_lock(struct dentry *d, int flags); -+void di_write_lock(struct dentry *d, unsigned int lsc); -+void di_write_unlock(struct dentry *d); -+void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir); -+void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir); -+void di_write_unlock2(struct dentry *d1, struct dentry *d2); -+ -+struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex); -+struct dentry *au_h_d_alias(struct dentry *dentry, aufs_bindex_t bindex); -+aufs_bindex_t au_dbtail(struct dentry *dentry); -+aufs_bindex_t au_dbtaildir(struct dentry *dentry); -+ -+void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex, -+ struct dentry *h_dentry); -+int au_digen_test(struct dentry *dentry, unsigned int sigen); -+int au_dbrange_test(struct dentry *dentry); -+void au_update_digen(struct dentry *dentry); -+void au_update_dbrange(struct dentry *dentry, int do_put_zero); -+void au_update_dbtop(struct dentry *dentry); -+void au_update_dbbot(struct dentry *dentry); -+int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry); -+ -+/* ---------------------------------------------------------------------- */ -+ -+static inline struct au_dinfo *au_di(struct dentry *dentry) -+{ -+ return dentry->d_fsdata; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* lock subclass for dinfo */ -+enum { -+ AuLsc_DI_CHILD, /* child first */ -+ AuLsc_DI_CHILD2, /* rename(2), link(2), and cpup at hnotify */ -+ AuLsc_DI_CHILD3, /* copyup dirs */ -+ AuLsc_DI_PARENT, -+ AuLsc_DI_PARENT2, -+ AuLsc_DI_PARENT3, -+ AuLsc_DI_TMP /* temp for replacing dinfo */ -+}; -+ -+/* -+ * di_read_lock_child, di_write_lock_child, -+ * di_read_lock_child2, di_write_lock_child2, -+ * di_read_lock_child3, di_write_lock_child3, -+ * di_read_lock_parent, di_write_lock_parent, -+ * di_read_lock_parent2, di_write_lock_parent2, -+ * di_read_lock_parent3, di_write_lock_parent3, -+ */ -+#define AuReadLockFunc(name, lsc) \ -+static inline void di_read_lock_##name(struct dentry *d, int flags) \ -+{ di_read_lock(d, flags, AuLsc_DI_##lsc); } -+ -+#define AuWriteLockFunc(name, lsc) \ -+static inline void di_write_lock_##name(struct dentry *d) \ -+{ di_write_lock(d, AuLsc_DI_##lsc); } -+ -+#define AuRWLockFuncs(name, lsc) \ -+ AuReadLockFunc(name, lsc) \ -+ AuWriteLockFunc(name, lsc) -+ -+AuRWLockFuncs(child, CHILD); -+AuRWLockFuncs(child2, CHILD2); -+AuRWLockFuncs(child3, CHILD3); -+AuRWLockFuncs(parent, PARENT); -+AuRWLockFuncs(parent2, PARENT2); -+AuRWLockFuncs(parent3, PARENT3); -+ -+#undef AuReadLockFunc -+#undef AuWriteLockFunc -+#undef AuRWLockFuncs -+ -+#define DiMustNoWaiters(d) AuRwMustNoWaiters(&au_di(d)->di_rwsem) -+#define DiMustAnyLock(d) AuRwMustAnyLock(&au_di(d)->di_rwsem) -+#define DiMustWriteLock(d) AuRwMustWriteLock(&au_di(d)->di_rwsem) -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* todo: memory barrier? */ -+static inline unsigned int au_digen(struct dentry *d) -+{ -+ return atomic_read(&au_di(d)->di_generation); -+} -+ -+static inline void au_h_dentry_init(struct au_hdentry *hdentry) -+{ -+ hdentry->hd_dentry = NULL; -+} -+ -+static inline struct au_hdentry *au_hdentry(struct au_dinfo *di, -+ aufs_bindex_t bindex) -+{ -+ return di->di_hdentry + bindex; -+} -+ -+static inline void au_hdput(struct au_hdentry *hd) -+{ -+ if (hd) -+ dput(hd->hd_dentry); -+} -+ -+static inline aufs_bindex_t au_dbtop(struct dentry *dentry) -+{ -+ DiMustAnyLock(dentry); -+ return au_di(dentry)->di_btop; -+} -+ -+static inline aufs_bindex_t au_dbbot(struct dentry *dentry) -+{ -+ DiMustAnyLock(dentry); -+ return au_di(dentry)->di_bbot; -+} -+ -+static inline aufs_bindex_t au_dbwh(struct dentry *dentry) -+{ -+ DiMustAnyLock(dentry); -+ return au_di(dentry)->di_bwh; -+} -+ -+static inline aufs_bindex_t au_dbdiropq(struct dentry *dentry) -+{ -+ DiMustAnyLock(dentry); -+ return au_di(dentry)->di_bdiropq; -+} -+ -+/* todo: hard/soft set? */ -+static inline void au_set_dbtop(struct dentry *dentry, aufs_bindex_t bindex) -+{ -+ DiMustWriteLock(dentry); -+ au_di(dentry)->di_btop = bindex; -+} -+ -+static inline void au_set_dbbot(struct dentry *dentry, aufs_bindex_t bindex) -+{ -+ DiMustWriteLock(dentry); -+ au_di(dentry)->di_bbot = bindex; -+} -+ -+static inline void au_set_dbwh(struct dentry *dentry, aufs_bindex_t bindex) -+{ -+ DiMustWriteLock(dentry); -+ /* dbwh can be outside of btop - bbot range */ -+ au_di(dentry)->di_bwh = bindex; -+} -+ -+static inline void au_set_dbdiropq(struct dentry *dentry, aufs_bindex_t bindex) -+{ -+ DiMustWriteLock(dentry); -+ au_di(dentry)->di_bdiropq = bindex; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+#ifdef CONFIG_AUFS_HNOTIFY -+static inline void au_digen_dec(struct dentry *d) -+{ -+ atomic_dec(&au_di(d)->di_generation); -+} -+ -+static inline void au_hn_di_reinit(struct dentry *dentry) -+{ -+ dentry->d_fsdata = NULL; -+} -+#else -+AuStubVoid(au_hn_di_reinit, struct dentry *dentry __maybe_unused) -+#endif /* CONFIG_AUFS_HNOTIFY */ -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_DENTRY_H__ */ -diff -Nurp linux-5.6.3/fs/aufs/dinfo.c linux-5.6.3-aufs/fs/aufs/dinfo.c ---- linux-5.6.3/fs/aufs/dinfo.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/dinfo.c 2020-04-10 12:40:52.189049362 +0300 -@@ -0,0 +1,541 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * dentry private data -+ */ -+ -+#include "aufs.h" -+ -+void au_di_init_once(void *_dinfo) -+{ -+ struct au_dinfo *dinfo = _dinfo; -+ -+ au_rw_init(&dinfo->di_rwsem); -+} -+ -+struct au_dinfo *au_di_alloc(struct super_block *sb, unsigned int lsc) -+{ -+ struct au_dinfo *dinfo; -+ int nbr, i; -+ -+ dinfo = au_cache_alloc_dinfo(); -+ if (unlikely(!dinfo)) -+ goto out; -+ -+ nbr = au_sbbot(sb) + 1; -+ if (nbr <= 0) -+ nbr = 1; -+ dinfo->di_hdentry = kcalloc(nbr, sizeof(*dinfo->di_hdentry), GFP_NOFS); -+ if (dinfo->di_hdentry) { -+ au_rw_write_lock_nested(&dinfo->di_rwsem, lsc); -+ dinfo->di_btop = -1; -+ dinfo->di_bbot = -1; -+ dinfo->di_bwh = -1; -+ dinfo->di_bdiropq = -1; -+ dinfo->di_tmpfile = 0; -+ for (i = 0; i < nbr; i++) -+ dinfo->di_hdentry[i].hd_id = -1; -+ goto out; -+ } -+ -+ au_cache_free_dinfo(dinfo); -+ dinfo = NULL; -+ -+out: -+ return dinfo; -+} -+ -+void au_di_free(struct au_dinfo *dinfo) -+{ -+ struct au_hdentry *p; -+ aufs_bindex_t bbot, bindex; -+ -+ /* dentry may not be revalidated */ -+ bindex = dinfo->di_btop; -+ if (bindex >= 0) { -+ bbot = dinfo->di_bbot; -+ p = au_hdentry(dinfo, bindex); -+ while (bindex++ <= bbot) -+ au_hdput(p++); -+ } -+ au_kfree_try_rcu(dinfo->di_hdentry); -+ au_cache_free_dinfo(dinfo); -+} -+ -+void au_di_swap(struct au_dinfo *a, struct au_dinfo *b) -+{ -+ struct au_hdentry *p; -+ aufs_bindex_t bi; -+ -+ AuRwMustWriteLock(&a->di_rwsem); -+ AuRwMustWriteLock(&b->di_rwsem); -+ -+#define DiSwap(v, name) \ -+ do { \ -+ v = a->di_##name; \ -+ a->di_##name = b->di_##name; \ -+ b->di_##name = v; \ -+ } while (0) -+ -+ DiSwap(p, hdentry); -+ DiSwap(bi, btop); -+ DiSwap(bi, bbot); -+ DiSwap(bi, bwh); -+ DiSwap(bi, bdiropq); -+ /* smp_mb(); */ -+ -+#undef DiSwap -+} -+ -+void au_di_cp(struct au_dinfo *dst, struct au_dinfo *src) -+{ -+ AuRwMustWriteLock(&dst->di_rwsem); -+ AuRwMustWriteLock(&src->di_rwsem); -+ -+ dst->di_btop = src->di_btop; -+ dst->di_bbot = src->di_bbot; -+ dst->di_bwh = src->di_bwh; -+ dst->di_bdiropq = src->di_bdiropq; -+ /* smp_mb(); */ -+} -+ -+int au_di_init(struct dentry *dentry) -+{ -+ int err; -+ struct super_block *sb; -+ struct au_dinfo *dinfo; -+ -+ err = 0; -+ sb = dentry->d_sb; -+ dinfo = au_di_alloc(sb, AuLsc_DI_CHILD); -+ if (dinfo) { -+ atomic_set(&dinfo->di_generation, au_sigen(sb)); -+ /* smp_mb(); */ /* atomic_set */ -+ dentry->d_fsdata = dinfo; -+ } else -+ err = -ENOMEM; -+ -+ return err; -+} -+ -+void au_di_fin(struct dentry *dentry) -+{ -+ struct au_dinfo *dinfo; -+ -+ dinfo = au_di(dentry); -+ AuRwDestroy(&dinfo->di_rwsem); -+ au_di_free(dinfo); -+} -+ -+int au_di_realloc(struct au_dinfo *dinfo, int nbr, int may_shrink) -+{ -+ int err, sz; -+ struct au_hdentry *hdp; -+ -+ AuRwMustWriteLock(&dinfo->di_rwsem); -+ -+ err = -ENOMEM; -+ sz = sizeof(*hdp) * (dinfo->di_bbot + 1); -+ if (!sz) -+ sz = sizeof(*hdp); -+ hdp = au_kzrealloc(dinfo->di_hdentry, sz, sizeof(*hdp) * nbr, GFP_NOFS, -+ may_shrink); -+ if (hdp) { -+ dinfo->di_hdentry = hdp; -+ err = 0; -+ } -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static void do_ii_write_lock(struct inode *inode, unsigned int lsc) -+{ -+ switch (lsc) { -+ case AuLsc_DI_CHILD: -+ ii_write_lock_child(inode); -+ break; -+ case AuLsc_DI_CHILD2: -+ ii_write_lock_child2(inode); -+ break; -+ case AuLsc_DI_CHILD3: -+ ii_write_lock_child3(inode); -+ break; -+ case AuLsc_DI_PARENT: -+ ii_write_lock_parent(inode); -+ break; -+ case AuLsc_DI_PARENT2: -+ ii_write_lock_parent2(inode); -+ break; -+ case AuLsc_DI_PARENT3: -+ ii_write_lock_parent3(inode); -+ break; -+ default: -+ BUG(); -+ } -+} -+ -+static void do_ii_read_lock(struct inode *inode, unsigned int lsc) -+{ -+ switch (lsc) { -+ case AuLsc_DI_CHILD: -+ ii_read_lock_child(inode); -+ break; -+ case AuLsc_DI_CHILD2: -+ ii_read_lock_child2(inode); -+ break; -+ case AuLsc_DI_CHILD3: -+ ii_read_lock_child3(inode); -+ break; -+ case AuLsc_DI_PARENT: -+ ii_read_lock_parent(inode); -+ break; -+ case AuLsc_DI_PARENT2: -+ ii_read_lock_parent2(inode); -+ break; -+ case AuLsc_DI_PARENT3: -+ ii_read_lock_parent3(inode); -+ break; -+ default: -+ BUG(); -+ } -+} -+ -+void di_read_lock(struct dentry *d, int flags, unsigned int lsc) -+{ -+ struct inode *inode; -+ -+ au_rw_read_lock_nested(&au_di(d)->di_rwsem, lsc); -+ if (d_really_is_positive(d)) { -+ inode = d_inode(d); -+ if (au_ftest_lock(flags, IW)) -+ do_ii_write_lock(inode, lsc); -+ else if (au_ftest_lock(flags, IR)) -+ do_ii_read_lock(inode, lsc); -+ } -+} -+ -+void di_read_unlock(struct dentry *d, int flags) -+{ -+ struct inode *inode; -+ -+ if (d_really_is_positive(d)) { -+ inode = d_inode(d); -+ if (au_ftest_lock(flags, IW)) { -+ au_dbg_verify_dinode(d); -+ ii_write_unlock(inode); -+ } else if (au_ftest_lock(flags, IR)) { -+ au_dbg_verify_dinode(d); -+ ii_read_unlock(inode); -+ } -+ } -+ au_rw_read_unlock(&au_di(d)->di_rwsem); -+} -+ -+void di_downgrade_lock(struct dentry *d, int flags) -+{ -+ if (d_really_is_positive(d) && au_ftest_lock(flags, IR)) -+ ii_downgrade_lock(d_inode(d)); -+ au_rw_dgrade_lock(&au_di(d)->di_rwsem); -+} -+ -+void di_write_lock(struct dentry *d, unsigned int lsc) -+{ -+ au_rw_write_lock_nested(&au_di(d)->di_rwsem, lsc); -+ if (d_really_is_positive(d)) -+ do_ii_write_lock(d_inode(d), lsc); -+} -+ -+void di_write_unlock(struct dentry *d) -+{ -+ au_dbg_verify_dinode(d); -+ if (d_really_is_positive(d)) -+ ii_write_unlock(d_inode(d)); -+ au_rw_write_unlock(&au_di(d)->di_rwsem); -+} -+ -+void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir) -+{ -+ AuDebugOn(d1 == d2 -+ || d_inode(d1) == d_inode(d2) -+ || d1->d_sb != d2->d_sb); -+ -+ if ((isdir && au_test_subdir(d1, d2)) -+ || d1 < d2) { -+ di_write_lock_child(d1); -+ di_write_lock_child2(d2); -+ } else { -+ di_write_lock_child(d2); -+ di_write_lock_child2(d1); -+ } -+} -+ -+void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir) -+{ -+ AuDebugOn(d1 == d2 -+ || d_inode(d1) == d_inode(d2) -+ || d1->d_sb != d2->d_sb); -+ -+ if ((isdir && au_test_subdir(d1, d2)) -+ || d1 < d2) { -+ di_write_lock_parent(d1); -+ di_write_lock_parent2(d2); -+ } else { -+ di_write_lock_parent(d2); -+ di_write_lock_parent2(d1); -+ } -+} -+ -+void di_write_unlock2(struct dentry *d1, struct dentry *d2) -+{ -+ di_write_unlock(d1); -+ if (d_inode(d1) == d_inode(d2)) -+ au_rw_write_unlock(&au_di(d2)->di_rwsem); -+ else -+ di_write_unlock(d2); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex) -+{ -+ struct dentry *d; -+ -+ DiMustAnyLock(dentry); -+ -+ if (au_dbtop(dentry) < 0 || bindex < au_dbtop(dentry)) -+ return NULL; -+ AuDebugOn(bindex < 0); -+ d = au_hdentry(au_di(dentry), bindex)->hd_dentry; -+ AuDebugOn(d && au_dcount(d) <= 0); -+ return d; -+} -+ -+/* -+ * extended version of au_h_dptr(). -+ * returns a hashed and positive (or linkable) h_dentry in bindex, NULL, or -+ * error. -+ */ -+struct dentry *au_h_d_alias(struct dentry *dentry, aufs_bindex_t bindex) -+{ -+ struct dentry *h_dentry; -+ struct inode *inode, *h_inode; -+ -+ AuDebugOn(d_really_is_negative(dentry)); -+ -+ h_dentry = NULL; -+ if (au_dbtop(dentry) <= bindex -+ && bindex <= au_dbbot(dentry)) -+ h_dentry = au_h_dptr(dentry, bindex); -+ if (h_dentry && !au_d_linkable(h_dentry)) { -+ dget(h_dentry); -+ goto out; /* success */ -+ } -+ -+ inode = d_inode(dentry); -+ AuDebugOn(bindex < au_ibtop(inode)); -+ AuDebugOn(au_ibbot(inode) < bindex); -+ h_inode = au_h_iptr(inode, bindex); -+ h_dentry = d_find_alias(h_inode); -+ if (h_dentry) { -+ if (!IS_ERR(h_dentry)) { -+ if (!au_d_linkable(h_dentry)) -+ goto out; /* success */ -+ dput(h_dentry); -+ } else -+ goto out; -+ } -+ -+ if (au_opt_test(au_mntflags(dentry->d_sb), PLINK)) { -+ h_dentry = au_plink_lkup(inode, bindex); -+ AuDebugOn(!h_dentry); -+ if (!IS_ERR(h_dentry)) { -+ if (!au_d_hashed_positive(h_dentry)) -+ goto out; /* success */ -+ dput(h_dentry); -+ h_dentry = NULL; -+ } -+ } -+ -+out: -+ AuDbgDentry(h_dentry); -+ return h_dentry; -+} -+ -+aufs_bindex_t au_dbtail(struct dentry *dentry) -+{ -+ aufs_bindex_t bbot, bwh; -+ -+ bbot = au_dbbot(dentry); -+ if (0 <= bbot) { -+ bwh = au_dbwh(dentry); -+ if (!bwh) -+ return bwh; -+ if (0 < bwh && bwh < bbot) -+ return bwh - 1; -+ } -+ return bbot; -+} -+ -+aufs_bindex_t au_dbtaildir(struct dentry *dentry) -+{ -+ aufs_bindex_t bbot, bopq; -+ -+ bbot = au_dbtail(dentry); -+ if (0 <= bbot) { -+ bopq = au_dbdiropq(dentry); -+ if (0 <= bopq && bopq < bbot) -+ bbot = bopq; -+ } -+ return bbot; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex, -+ struct dentry *h_dentry) -+{ -+ struct au_dinfo *dinfo; -+ struct au_hdentry *hd; -+ struct au_branch *br; -+ -+ DiMustWriteLock(dentry); -+ -+ dinfo = au_di(dentry); -+ hd = au_hdentry(dinfo, bindex); -+ au_hdput(hd); -+ hd->hd_dentry = h_dentry; -+ if (h_dentry) { -+ br = au_sbr(dentry->d_sb, bindex); -+ hd->hd_id = br->br_id; -+ } -+} -+ -+int au_dbrange_test(struct dentry *dentry) -+{ -+ int err; -+ aufs_bindex_t btop, bbot; -+ -+ err = 0; -+ btop = au_dbtop(dentry); -+ bbot = au_dbbot(dentry); -+ if (btop >= 0) -+ AuDebugOn(bbot < 0 && btop > bbot); -+ else { -+ err = -EIO; -+ AuDebugOn(bbot >= 0); -+ } -+ -+ return err; -+} -+ -+int au_digen_test(struct dentry *dentry, unsigned int sigen) -+{ -+ int err; -+ -+ err = 0; -+ if (unlikely(au_digen(dentry) != sigen -+ || au_iigen_test(d_inode(dentry), sigen))) -+ err = -EIO; -+ -+ return err; -+} -+ -+void au_update_digen(struct dentry *dentry) -+{ -+ atomic_set(&au_di(dentry)->di_generation, au_sigen(dentry->d_sb)); -+ /* smp_mb(); */ /* atomic_set */ -+} -+ -+void au_update_dbrange(struct dentry *dentry, int do_put_zero) -+{ -+ struct au_dinfo *dinfo; -+ struct dentry *h_d; -+ struct au_hdentry *hdp; -+ aufs_bindex_t bindex, bbot; -+ -+ DiMustWriteLock(dentry); -+ -+ dinfo = au_di(dentry); -+ if (!dinfo || dinfo->di_btop < 0) -+ return; -+ -+ if (do_put_zero) { -+ bbot = dinfo->di_bbot; -+ bindex = dinfo->di_btop; -+ hdp = au_hdentry(dinfo, bindex); -+ for (; bindex <= bbot; bindex++, hdp++) { -+ h_d = hdp->hd_dentry; -+ if (h_d && d_is_negative(h_d)) -+ au_set_h_dptr(dentry, bindex, NULL); -+ } -+ } -+ -+ dinfo->di_btop = 0; -+ hdp = au_hdentry(dinfo, dinfo->di_btop); -+ for (; dinfo->di_btop <= dinfo->di_bbot; dinfo->di_btop++, hdp++) -+ if (hdp->hd_dentry) -+ break; -+ if (dinfo->di_btop > dinfo->di_bbot) { -+ dinfo->di_btop = -1; -+ dinfo->di_bbot = -1; -+ return; -+ } -+ -+ hdp = au_hdentry(dinfo, dinfo->di_bbot); -+ for (; dinfo->di_bbot >= 0; dinfo->di_bbot--, hdp--) -+ if (hdp->hd_dentry) -+ break; -+ AuDebugOn(dinfo->di_btop > dinfo->di_bbot || dinfo->di_bbot < 0); -+} -+ -+void au_update_dbtop(struct dentry *dentry) -+{ -+ aufs_bindex_t bindex, bbot; -+ struct dentry *h_dentry; -+ -+ bbot = au_dbbot(dentry); -+ for (bindex = au_dbtop(dentry); bindex <= bbot; bindex++) { -+ h_dentry = au_h_dptr(dentry, bindex); -+ if (!h_dentry) -+ continue; -+ if (d_is_positive(h_dentry)) { -+ au_set_dbtop(dentry, bindex); -+ return; -+ } -+ au_set_h_dptr(dentry, bindex, NULL); -+ } -+} -+ -+void au_update_dbbot(struct dentry *dentry) -+{ -+ aufs_bindex_t bindex, btop; -+ struct dentry *h_dentry; -+ -+ btop = au_dbtop(dentry); -+ for (bindex = au_dbbot(dentry); bindex >= btop; bindex--) { -+ h_dentry = au_h_dptr(dentry, bindex); -+ if (!h_dentry) -+ continue; -+ if (d_is_positive(h_dentry)) { -+ au_set_dbbot(dentry, bindex); -+ return; -+ } -+ au_set_h_dptr(dentry, bindex, NULL); -+ } -+} -+ -+int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry) -+{ -+ aufs_bindex_t bindex, bbot; -+ -+ bbot = au_dbbot(dentry); -+ for (bindex = au_dbtop(dentry); bindex <= bbot; bindex++) -+ if (au_h_dptr(dentry, bindex) == h_dentry) -+ return bindex; -+ return -1; -+} -diff -Nurp linux-5.6.3/fs/aufs/dir.c linux-5.6.3-aufs/fs/aufs/dir.c ---- linux-5.6.3/fs/aufs/dir.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/dir.c 2020-04-10 12:40:52.189049362 +0300 -@@ -0,0 +1,750 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * directory operations -+ */ -+ -+#include -+#include -+#include "aufs.h" -+ -+void au_add_nlink(struct inode *dir, struct inode *h_dir) -+{ -+ unsigned int nlink; -+ -+ AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode)); -+ -+ nlink = dir->i_nlink; -+ nlink += h_dir->i_nlink - 2; -+ if (h_dir->i_nlink < 2) -+ nlink += 2; -+ smp_mb(); /* for i_nlink */ -+ /* 0 can happen in revaliding */ -+ set_nlink(dir, nlink); -+} -+ -+void au_sub_nlink(struct inode *dir, struct inode *h_dir) -+{ -+ unsigned int nlink; -+ -+ AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode)); -+ -+ nlink = dir->i_nlink; -+ nlink -= h_dir->i_nlink - 2; -+ if (h_dir->i_nlink < 2) -+ nlink -= 2; -+ smp_mb(); /* for i_nlink */ -+ /* nlink == 0 means the branch-fs is broken */ -+ set_nlink(dir, nlink); -+} -+ -+loff_t au_dir_size(struct file *file, struct dentry *dentry) -+{ -+ loff_t sz; -+ aufs_bindex_t bindex, bbot; -+ struct file *h_file; -+ struct dentry *h_dentry; -+ -+ sz = 0; -+ if (file) { -+ AuDebugOn(!d_is_dir(file->f_path.dentry)); -+ -+ bbot = au_fbbot_dir(file); -+ for (bindex = au_fbtop(file); -+ bindex <= bbot && sz < KMALLOC_MAX_SIZE; -+ bindex++) { -+ h_file = au_hf_dir(file, bindex); -+ if (h_file && file_inode(h_file)) -+ sz += vfsub_f_size_read(h_file); -+ } -+ } else { -+ AuDebugOn(!dentry); -+ AuDebugOn(!d_is_dir(dentry)); -+ -+ bbot = au_dbtaildir(dentry); -+ for (bindex = au_dbtop(dentry); -+ bindex <= bbot && sz < KMALLOC_MAX_SIZE; -+ bindex++) { -+ h_dentry = au_h_dptr(dentry, bindex); -+ if (h_dentry && d_is_positive(h_dentry)) -+ sz += i_size_read(d_inode(h_dentry)); -+ } -+ } -+ if (sz < KMALLOC_MAX_SIZE) -+ sz = roundup_pow_of_two(sz); -+ if (sz > KMALLOC_MAX_SIZE) -+ sz = KMALLOC_MAX_SIZE; -+ else if (sz < NAME_MAX) { -+ BUILD_BUG_ON(AUFS_RDBLK_DEF < NAME_MAX); -+ sz = AUFS_RDBLK_DEF; -+ } -+ return sz; -+} -+ -+struct au_dir_ts_arg { -+ struct dentry *dentry; -+ aufs_bindex_t brid; -+}; -+ -+static void au_do_dir_ts(void *arg) -+{ -+ struct au_dir_ts_arg *a = arg; -+ struct au_dtime dt; -+ struct path h_path; -+ struct inode *dir, *h_dir; -+ struct super_block *sb; -+ struct au_branch *br; -+ struct au_hinode *hdir; -+ int err; -+ aufs_bindex_t btop, bindex; -+ -+ sb = a->dentry->d_sb; -+ if (d_really_is_negative(a->dentry)) -+ goto out; -+ /* no dir->i_mutex lock */ -+ aufs_read_lock(a->dentry, AuLock_DW); /* noflush */ -+ -+ dir = d_inode(a->dentry); -+ btop = au_ibtop(dir); -+ bindex = au_br_index(sb, a->brid); -+ if (bindex < btop) -+ goto out_unlock; -+ -+ br = au_sbr(sb, bindex); -+ h_path.dentry = au_h_dptr(a->dentry, bindex); -+ if (!h_path.dentry) -+ goto out_unlock; -+ h_path.mnt = au_br_mnt(br); -+ au_dtime_store(&dt, a->dentry, &h_path); -+ -+ br = au_sbr(sb, btop); -+ if (!au_br_writable(br->br_perm)) -+ goto out_unlock; -+ h_path.dentry = au_h_dptr(a->dentry, btop); -+ h_path.mnt = au_br_mnt(br); -+ err = vfsub_mnt_want_write(h_path.mnt); -+ if (err) -+ goto out_unlock; -+ hdir = au_hi(dir, btop); -+ au_hn_inode_lock_nested(hdir, AuLsc_I_PARENT); -+ h_dir = au_h_iptr(dir, btop); -+ if (h_dir->i_nlink -+ && timespec64_compare(&h_dir->i_mtime, &dt.dt_mtime) < 0) { -+ dt.dt_h_path = h_path; -+ au_dtime_revert(&dt); -+ } -+ au_hn_inode_unlock(hdir); -+ vfsub_mnt_drop_write(h_path.mnt); -+ au_cpup_attr_timesizes(dir); -+ -+out_unlock: -+ aufs_read_unlock(a->dentry, AuLock_DW); -+out: -+ dput(a->dentry); -+ au_nwt_done(&au_sbi(sb)->si_nowait); -+ au_kfree_try_rcu(arg); -+} -+ -+void au_dir_ts(struct inode *dir, aufs_bindex_t bindex) -+{ -+ int perm, wkq_err; -+ aufs_bindex_t btop; -+ struct au_dir_ts_arg *arg; -+ struct dentry *dentry; -+ struct super_block *sb; -+ -+ IMustLock(dir); -+ -+ dentry = d_find_any_alias(dir); -+ AuDebugOn(!dentry); -+ sb = dentry->d_sb; -+ btop = au_ibtop(dir); -+ if (btop == bindex) { -+ au_cpup_attr_timesizes(dir); -+ goto out; -+ } -+ -+ perm = au_sbr_perm(sb, btop); -+ if (!au_br_writable(perm)) -+ goto out; -+ -+ arg = kmalloc(sizeof(*arg), GFP_NOFS); -+ if (!arg) -+ goto out; -+ -+ arg->dentry = dget(dentry); /* will be dput-ted by au_do_dir_ts() */ -+ arg->brid = au_sbr_id(sb, bindex); -+ wkq_err = au_wkq_nowait(au_do_dir_ts, arg, sb, /*flags*/0); -+ if (unlikely(wkq_err)) { -+ pr_err("wkq %d\n", wkq_err); -+ dput(dentry); -+ au_kfree_try_rcu(arg); -+ } -+ -+out: -+ dput(dentry); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int reopen_dir(struct file *file) -+{ -+ int err; -+ unsigned int flags; -+ aufs_bindex_t bindex, btail, btop; -+ struct dentry *dentry, *h_dentry; -+ struct file *h_file; -+ -+ /* open all lower dirs */ -+ dentry = file->f_path.dentry; -+ btop = au_dbtop(dentry); -+ for (bindex = au_fbtop(file); bindex < btop; bindex++) -+ au_set_h_fptr(file, bindex, NULL); -+ au_set_fbtop(file, btop); -+ -+ btail = au_dbtaildir(dentry); -+ for (bindex = au_fbbot_dir(file); btail < bindex; bindex--) -+ au_set_h_fptr(file, bindex, NULL); -+ au_set_fbbot_dir(file, btail); -+ -+ flags = vfsub_file_flags(file); -+ for (bindex = btop; bindex <= btail; bindex++) { -+ h_dentry = au_h_dptr(dentry, bindex); -+ if (!h_dentry) -+ continue; -+ h_file = au_hf_dir(file, bindex); -+ if (h_file) -+ continue; -+ -+ h_file = au_h_open(dentry, bindex, flags, file, /*force_wr*/0); -+ err = PTR_ERR(h_file); -+ if (IS_ERR(h_file)) -+ goto out; /* close all? */ -+ au_set_h_fptr(file, bindex, h_file); -+ } -+ au_update_figen(file); -+ /* todo: necessary? */ -+ /* file->f_ra = h_file->f_ra; */ -+ err = 0; -+ -+out: -+ return err; -+} -+ -+static int do_open_dir(struct file *file, int flags, struct file *h_file) -+{ -+ int err; -+ aufs_bindex_t bindex, btail; -+ struct dentry *dentry, *h_dentry; -+ struct vfsmount *mnt; -+ -+ FiMustWriteLock(file); -+ AuDebugOn(h_file); -+ -+ err = 0; -+ mnt = file->f_path.mnt; -+ dentry = file->f_path.dentry; -+ file->f_version = inode_query_iversion(d_inode(dentry)); -+ bindex = au_dbtop(dentry); -+ au_set_fbtop(file, bindex); -+ btail = au_dbtaildir(dentry); -+ au_set_fbbot_dir(file, btail); -+ for (; !err && bindex <= btail; bindex++) { -+ h_dentry = au_h_dptr(dentry, bindex); -+ if (!h_dentry) -+ continue; -+ -+ err = vfsub_test_mntns(mnt, h_dentry->d_sb); -+ if (unlikely(err)) -+ break; -+ h_file = au_h_open(dentry, bindex, flags, file, /*force_wr*/0); -+ if (IS_ERR(h_file)) { -+ err = PTR_ERR(h_file); -+ break; -+ } -+ au_set_h_fptr(file, bindex, h_file); -+ } -+ au_update_figen(file); -+ /* todo: necessary? */ -+ /* file->f_ra = h_file->f_ra; */ -+ if (!err) -+ return 0; /* success */ -+ -+ /* close all */ -+ for (bindex = au_fbtop(file); bindex <= btail; bindex++) -+ au_set_h_fptr(file, bindex, NULL); -+ au_set_fbtop(file, -1); -+ au_set_fbbot_dir(file, -1); -+ -+ return err; -+} -+ -+static int aufs_open_dir(struct inode *inode __maybe_unused, -+ struct file *file) -+{ -+ int err; -+ struct super_block *sb; -+ struct au_fidir *fidir; -+ -+ err = -ENOMEM; -+ sb = file->f_path.dentry->d_sb; -+ si_read_lock(sb, AuLock_FLUSH); -+ fidir = au_fidir_alloc(sb); -+ if (fidir) { -+ struct au_do_open_args args = { -+ .open = do_open_dir, -+ .fidir = fidir -+ }; -+ err = au_do_open(file, &args); -+ if (unlikely(err)) -+ au_kfree_rcu(fidir); -+ } -+ si_read_unlock(sb); -+ return err; -+} -+ -+static int aufs_release_dir(struct inode *inode __maybe_unused, -+ struct file *file) -+{ -+ struct au_vdir *vdir_cache; -+ struct au_finfo *finfo; -+ struct au_fidir *fidir; -+ struct au_hfile *hf; -+ aufs_bindex_t bindex, bbot; -+ -+ finfo = au_fi(file); -+ fidir = finfo->fi_hdir; -+ if (fidir) { -+ au_hbl_del(&finfo->fi_hlist, -+ &au_sbi(file->f_path.dentry->d_sb)->si_files); -+ vdir_cache = fidir->fd_vdir_cache; /* lock-free */ -+ if (vdir_cache) -+ au_vdir_free(vdir_cache); -+ -+ bindex = finfo->fi_btop; -+ if (bindex >= 0) { -+ hf = fidir->fd_hfile + bindex; -+ /* -+ * calls fput() instead of filp_close(), -+ * since no dnotify or lock for the lower file. -+ */ -+ bbot = fidir->fd_bbot; -+ for (; bindex <= bbot; bindex++, hf++) -+ if (hf->hf_file) -+ au_hfput(hf, /*execed*/0); -+ } -+ au_kfree_rcu(fidir); -+ finfo->fi_hdir = NULL; -+ } -+ au_finfo_fin(file); -+ return 0; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int au_do_flush_dir(struct file *file, fl_owner_t id) -+{ -+ int err; -+ aufs_bindex_t bindex, bbot; -+ struct file *h_file; -+ -+ err = 0; -+ bbot = au_fbbot_dir(file); -+ for (bindex = au_fbtop(file); !err && bindex <= bbot; bindex++) { -+ h_file = au_hf_dir(file, bindex); -+ if (h_file) -+ err = vfsub_flush(h_file, id); -+ } -+ return err; -+} -+ -+static int aufs_flush_dir(struct file *file, fl_owner_t id) -+{ -+ return au_do_flush(file, id, au_do_flush_dir); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int au_do_fsync_dir_no_file(struct dentry *dentry, int datasync) -+{ -+ int err; -+ aufs_bindex_t bbot, bindex; -+ struct inode *inode; -+ struct super_block *sb; -+ -+ err = 0; -+ sb = dentry->d_sb; -+ inode = d_inode(dentry); -+ IMustLock(inode); -+ bbot = au_dbbot(dentry); -+ for (bindex = au_dbtop(dentry); !err && bindex <= bbot; bindex++) { -+ struct path h_path; -+ -+ if (au_test_ro(sb, bindex, inode)) -+ continue; -+ h_path.dentry = au_h_dptr(dentry, bindex); -+ if (!h_path.dentry) -+ continue; -+ -+ h_path.mnt = au_sbr_mnt(sb, bindex); -+ err = vfsub_fsync(NULL, &h_path, datasync); -+ } -+ -+ return err; -+} -+ -+static int au_do_fsync_dir(struct file *file, int datasync) -+{ -+ int err; -+ aufs_bindex_t bbot, bindex; -+ struct file *h_file; -+ struct super_block *sb; -+ struct inode *inode; -+ -+ err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1, /*fi_lsc*/0); -+ if (unlikely(err)) -+ goto out; -+ -+ inode = file_inode(file); -+ sb = inode->i_sb; -+ bbot = au_fbbot_dir(file); -+ for (bindex = au_fbtop(file); !err && bindex <= bbot; bindex++) { -+ h_file = au_hf_dir(file, bindex); -+ if (!h_file || au_test_ro(sb, bindex, inode)) -+ continue; -+ -+ err = vfsub_fsync(h_file, &h_file->f_path, datasync); -+ } -+ -+out: -+ return err; -+} -+ -+/* -+ * @file may be NULL -+ */ -+static int aufs_fsync_dir(struct file *file, loff_t start, loff_t end, -+ int datasync) -+{ -+ int err; -+ struct dentry *dentry; -+ struct inode *inode; -+ struct super_block *sb; -+ -+ err = 0; -+ dentry = file->f_path.dentry; -+ inode = d_inode(dentry); -+ inode_lock(inode); -+ sb = dentry->d_sb; -+ si_noflush_read_lock(sb); -+ if (file) -+ err = au_do_fsync_dir(file, datasync); -+ else { -+ di_write_lock_child(dentry); -+ err = au_do_fsync_dir_no_file(dentry, datasync); -+ } -+ au_cpup_attr_timesizes(inode); -+ di_write_unlock(dentry); -+ if (file) -+ fi_write_unlock(file); -+ -+ si_read_unlock(sb); -+ inode_unlock(inode); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int aufs_iterate_shared(struct file *file, struct dir_context *ctx) -+{ -+ int err; -+ struct dentry *dentry; -+ struct inode *inode, *h_inode; -+ struct super_block *sb; -+ -+ AuDbg("%pD, ctx{%ps, %llu}\n", file, ctx->actor, ctx->pos); -+ -+ dentry = file->f_path.dentry; -+ inode = d_inode(dentry); -+ IMustLock(inode); -+ -+ sb = dentry->d_sb; -+ si_read_lock(sb, AuLock_FLUSH); -+ err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1, /*fi_lsc*/0); -+ if (unlikely(err)) -+ goto out; -+ err = au_alive_dir(dentry); -+ if (!err) -+ err = au_vdir_init(file); -+ di_downgrade_lock(dentry, AuLock_IR); -+ if (unlikely(err)) -+ goto out_unlock; -+ -+ h_inode = au_h_iptr(inode, au_ibtop(inode)); -+ if (!au_test_nfsd()) { -+ err = au_vdir_fill_de(file, ctx); -+ fsstack_copy_attr_atime(inode, h_inode); -+ } else { -+ /* -+ * nfsd filldir may call lookup_one_len(), vfs_getattr(), -+ * encode_fh() and others. -+ */ -+ atomic_inc(&h_inode->i_count); -+ di_read_unlock(dentry, AuLock_IR); -+ si_read_unlock(sb); -+ err = au_vdir_fill_de(file, ctx); -+ fsstack_copy_attr_atime(inode, h_inode); -+ fi_write_unlock(file); -+ iput(h_inode); -+ -+ AuTraceErr(err); -+ return err; -+ } -+ -+out_unlock: -+ di_read_unlock(dentry, AuLock_IR); -+ fi_write_unlock(file); -+out: -+ si_read_unlock(sb); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+#define AuTestEmpty_WHONLY 1 -+#define AuTestEmpty_CALLED (1 << 1) -+#define AuTestEmpty_SHWH (1 << 2) -+#define au_ftest_testempty(flags, name) ((flags) & AuTestEmpty_##name) -+#define au_fset_testempty(flags, name) \ -+ do { (flags) |= AuTestEmpty_##name; } while (0) -+#define au_fclr_testempty(flags, name) \ -+ do { (flags) &= ~AuTestEmpty_##name; } while (0) -+ -+#ifndef CONFIG_AUFS_SHWH -+#undef AuTestEmpty_SHWH -+#define AuTestEmpty_SHWH 0 -+#endif -+ -+struct test_empty_arg { -+ struct dir_context ctx; -+ struct au_nhash *whlist; -+ unsigned int flags; -+ int err; -+ aufs_bindex_t bindex; -+}; -+ -+static int test_empty_cb(struct dir_context *ctx, const char *__name, -+ int namelen, loff_t offset __maybe_unused, u64 ino, -+ unsigned int d_type) -+{ -+ struct test_empty_arg *arg = container_of(ctx, struct test_empty_arg, -+ ctx); -+ char *name = (void *)__name; -+ -+ arg->err = 0; -+ au_fset_testempty(arg->flags, CALLED); -+ /* smp_mb(); */ -+ if (name[0] == '.' -+ && (namelen == 1 || (name[1] == '.' && namelen == 2))) -+ goto out; /* success */ -+ -+ if (namelen <= AUFS_WH_PFX_LEN -+ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) { -+ if (au_ftest_testempty(arg->flags, WHONLY) -+ && !au_nhash_test_known_wh(arg->whlist, name, namelen)) -+ arg->err = -ENOTEMPTY; -+ goto out; -+ } -+ -+ name += AUFS_WH_PFX_LEN; -+ namelen -= AUFS_WH_PFX_LEN; -+ if (!au_nhash_test_known_wh(arg->whlist, name, namelen)) -+ arg->err = au_nhash_append_wh -+ (arg->whlist, name, namelen, ino, d_type, arg->bindex, -+ au_ftest_testempty(arg->flags, SHWH)); -+ -+out: -+ /* smp_mb(); */ -+ AuTraceErr(arg->err); -+ return arg->err; -+} -+ -+static int do_test_empty(struct dentry *dentry, struct test_empty_arg *arg) -+{ -+ int err; -+ struct file *h_file; -+ struct au_branch *br; -+ -+ h_file = au_h_open(dentry, arg->bindex, -+ O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_LARGEFILE, -+ /*file*/NULL, /*force_wr*/0); -+ err = PTR_ERR(h_file); -+ if (IS_ERR(h_file)) -+ goto out; -+ -+ err = 0; -+ if (!au_opt_test(au_mntflags(dentry->d_sb), UDBA_NONE) -+ && !file_inode(h_file)->i_nlink) -+ goto out_put; -+ -+ do { -+ arg->err = 0; -+ au_fclr_testempty(arg->flags, CALLED); -+ /* smp_mb(); */ -+ err = vfsub_iterate_dir(h_file, &arg->ctx); -+ if (err >= 0) -+ err = arg->err; -+ } while (!err && au_ftest_testempty(arg->flags, CALLED)); -+ -+out_put: -+ fput(h_file); -+ br = au_sbr(dentry->d_sb, arg->bindex); -+ au_lcnt_dec(&br->br_nfiles); -+out: -+ return err; -+} -+ -+struct do_test_empty_args { -+ int *errp; -+ struct dentry *dentry; -+ struct test_empty_arg *arg; -+}; -+ -+static void call_do_test_empty(void *args) -+{ -+ struct do_test_empty_args *a = args; -+ *a->errp = do_test_empty(a->dentry, a->arg); -+} -+ -+static int sio_test_empty(struct dentry *dentry, struct test_empty_arg *arg) -+{ -+ int err, wkq_err; -+ struct dentry *h_dentry; -+ struct inode *h_inode; -+ -+ h_dentry = au_h_dptr(dentry, arg->bindex); -+ h_inode = d_inode(h_dentry); -+ /* todo: i_mode changes anytime? */ -+ inode_lock_shared_nested(h_inode, AuLsc_I_CHILD); -+ err = au_test_h_perm_sio(h_inode, MAY_EXEC | MAY_READ); -+ inode_unlock_shared(h_inode); -+ if (!err) -+ err = do_test_empty(dentry, arg); -+ else { -+ struct do_test_empty_args args = { -+ .errp = &err, -+ .dentry = dentry, -+ .arg = arg -+ }; -+ unsigned int flags = arg->flags; -+ -+ wkq_err = au_wkq_wait(call_do_test_empty, &args); -+ if (unlikely(wkq_err)) -+ err = wkq_err; -+ arg->flags = flags; -+ } -+ -+ return err; -+} -+ -+int au_test_empty_lower(struct dentry *dentry) -+{ -+ int err; -+ unsigned int rdhash; -+ aufs_bindex_t bindex, btop, btail; -+ struct au_nhash whlist; -+ struct test_empty_arg arg = { -+ .ctx = { -+ .actor = test_empty_cb -+ } -+ }; -+ int (*test_empty)(struct dentry *dentry, struct test_empty_arg *arg); -+ -+ SiMustAnyLock(dentry->d_sb); -+ -+ rdhash = au_sbi(dentry->d_sb)->si_rdhash; -+ if (!rdhash) -+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, dentry)); -+ err = au_nhash_alloc(&whlist, rdhash, GFP_NOFS); -+ if (unlikely(err)) -+ goto out; -+ -+ arg.flags = 0; -+ arg.whlist = &whlist; -+ btop = au_dbtop(dentry); -+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH)) -+ au_fset_testempty(arg.flags, SHWH); -+ test_empty = do_test_empty; -+ if (au_opt_test(au_mntflags(dentry->d_sb), DIRPERM1)) -+ test_empty = sio_test_empty; -+ arg.bindex = btop; -+ err = test_empty(dentry, &arg); -+ if (unlikely(err)) -+ goto out_whlist; -+ -+ au_fset_testempty(arg.flags, WHONLY); -+ btail = au_dbtaildir(dentry); -+ for (bindex = btop + 1; !err && bindex <= btail; bindex++) { -+ struct dentry *h_dentry; -+ -+ h_dentry = au_h_dptr(dentry, bindex); -+ if (h_dentry && d_is_positive(h_dentry)) { -+ arg.bindex = bindex; -+ err = test_empty(dentry, &arg); -+ } -+ } -+ -+out_whlist: -+ au_nhash_wh_free(&whlist); -+out: -+ return err; -+} -+ -+int au_test_empty(struct dentry *dentry, struct au_nhash *whlist) -+{ -+ int err; -+ struct test_empty_arg arg = { -+ .ctx = { -+ .actor = test_empty_cb -+ } -+ }; -+ aufs_bindex_t bindex, btail; -+ -+ err = 0; -+ arg.whlist = whlist; -+ arg.flags = AuTestEmpty_WHONLY; -+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH)) -+ au_fset_testempty(arg.flags, SHWH); -+ btail = au_dbtaildir(dentry); -+ for (bindex = au_dbtop(dentry); !err && bindex <= btail; bindex++) { -+ struct dentry *h_dentry; -+ -+ h_dentry = au_h_dptr(dentry, bindex); -+ if (h_dentry && d_is_positive(h_dentry)) { -+ arg.bindex = bindex; -+ err = sio_test_empty(dentry, &arg); -+ } -+ } -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+const struct file_operations aufs_dir_fop = { -+ .owner = THIS_MODULE, -+ .llseek = default_llseek, -+ .read = generic_read_dir, -+ .iterate_shared = aufs_iterate_shared, -+ .unlocked_ioctl = aufs_ioctl_dir, -+#ifdef CONFIG_COMPAT -+ .compat_ioctl = aufs_compat_ioctl_dir, -+#endif -+ .open = aufs_open_dir, -+ .release = aufs_release_dir, -+ .flush = aufs_flush_dir, -+ .fsync = aufs_fsync_dir -+}; -diff -Nurp linux-5.6.3/fs/aufs/dir.h linux-5.6.3-aufs/fs/aufs/dir.h ---- linux-5.6.3/fs/aufs/dir.h 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/dir.h 2020-04-10 12:40:52.189049362 +0300 -@@ -0,0 +1,121 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * directory operations -+ */ -+ -+#ifndef __AUFS_DIR_H__ -+#define __AUFS_DIR_H__ -+ -+#ifdef __KERNEL__ -+ -+#include -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* need to be faster and smaller */ -+ -+struct au_nhash { -+ unsigned int nh_num; -+ struct hlist_head *nh_head; -+}; -+ -+struct au_vdir_destr { -+ unsigned char len; -+ unsigned char name[0]; -+} __packed; -+ -+struct au_vdir_dehstr { -+ struct hlist_node hash; -+ struct au_vdir_destr *str; -+ struct rcu_head rcu; -+} ____cacheline_aligned_in_smp; -+ -+struct au_vdir_de { -+ ino_t de_ino; -+ unsigned char de_type; -+ /* caution: packed */ -+ struct au_vdir_destr de_str; -+} __packed; -+ -+struct au_vdir_wh { -+ struct hlist_node wh_hash; -+#ifdef CONFIG_AUFS_SHWH -+ ino_t wh_ino; -+ aufs_bindex_t wh_bindex; -+ unsigned char wh_type; -+#else -+ aufs_bindex_t wh_bindex; -+#endif -+ /* caution: packed */ -+ struct au_vdir_destr wh_str; -+} __packed; -+ -+union au_vdir_deblk_p { -+ unsigned char *deblk; -+ struct au_vdir_de *de; -+}; -+ -+struct au_vdir { -+ unsigned char **vd_deblk; -+ unsigned long vd_nblk; -+ struct { -+ unsigned long ul; -+ union au_vdir_deblk_p p; -+ } vd_last; -+ -+ u64 vd_version; -+ unsigned int vd_deblk_sz; -+ unsigned long vd_jiffy; -+ struct rcu_head rcu; -+} ____cacheline_aligned_in_smp; -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* dir.c */ -+extern const struct file_operations aufs_dir_fop; -+void au_add_nlink(struct inode *dir, struct inode *h_dir); -+void au_sub_nlink(struct inode *dir, struct inode *h_dir); -+loff_t au_dir_size(struct file *file, struct dentry *dentry); -+void au_dir_ts(struct inode *dir, aufs_bindex_t bsrc); -+int au_test_empty_lower(struct dentry *dentry); -+int au_test_empty(struct dentry *dentry, struct au_nhash *whlist); -+ -+/* vdir.c */ -+unsigned int au_rdhash_est(loff_t sz); -+int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp); -+void au_nhash_wh_free(struct au_nhash *whlist); -+int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt, -+ int limit); -+int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen); -+int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino, -+ unsigned int d_type, aufs_bindex_t bindex, -+ unsigned char shwh); -+void au_vdir_free(struct au_vdir *vdir); -+int au_vdir_init(struct file *file); -+int au_vdir_fill_de(struct file *file, struct dir_context *ctx); -+ -+/* ioctl.c */ -+long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg); -+ -+#ifdef CONFIG_AUFS_RDU -+/* rdu.c */ -+long au_rdu_ioctl(struct file *file, unsigned int cmd, unsigned long arg); -+#ifdef CONFIG_COMPAT -+long au_rdu_compat_ioctl(struct file *file, unsigned int cmd, -+ unsigned long arg); -+#endif -+#else -+AuStub(long, au_rdu_ioctl, return -EINVAL, struct file *file, -+ unsigned int cmd, unsigned long arg) -+#ifdef CONFIG_COMPAT -+AuStub(long, au_rdu_compat_ioctl, return -EINVAL, struct file *file, -+ unsigned int cmd, unsigned long arg) -+#endif -+#endif -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_DIR_H__ */ -diff -Nurp linux-5.6.3/fs/aufs/dirren.c linux-5.6.3-aufs/fs/aufs/dirren.c ---- linux-5.6.3/fs/aufs/dirren.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/dirren.c 2020-04-10 12:40:52.190049409 +0300 -@@ -0,0 +1,1303 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2017-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * special handling in renaming a directory -+ * in order to support looking-up the before-renamed name on the lower readonly -+ * branches -+ */ -+ -+#include -+#include "aufs.h" -+ -+static void au_dr_hino_del(struct au_dr_br *dr, struct au_dr_hino *ent) -+{ -+ int idx; -+ -+ idx = au_dr_ihash(ent->dr_h_ino); -+ au_hbl_del(&ent->dr_hnode, dr->dr_h_ino + idx); -+} -+ -+static int au_dr_hino_test_empty(struct au_dr_br *dr) -+{ -+ int ret, i; -+ struct hlist_bl_head *hbl; -+ -+ ret = 1; -+ for (i = 0; ret && i < AuDirren_NHASH; i++) { -+ hbl = dr->dr_h_ino + i; -+ hlist_bl_lock(hbl); -+ ret &= hlist_bl_empty(hbl); -+ hlist_bl_unlock(hbl); -+ } -+ -+ return ret; -+} -+ -+static struct au_dr_hino *au_dr_hino_find(struct au_dr_br *dr, ino_t ino) -+{ -+ struct au_dr_hino *found, *ent; -+ struct hlist_bl_head *hbl; -+ struct hlist_bl_node *pos; -+ int idx; -+ -+ found = NULL; -+ idx = au_dr_ihash(ino); -+ hbl = dr->dr_h_ino + idx; -+ hlist_bl_lock(hbl); -+ hlist_bl_for_each_entry(ent, pos, hbl, dr_hnode) -+ if (ent->dr_h_ino == ino) { -+ found = ent; -+ break; -+ } -+ hlist_bl_unlock(hbl); -+ -+ return found; -+} -+ -+int au_dr_hino_test_add(struct au_dr_br *dr, ino_t ino, -+ struct au_dr_hino *add_ent) -+{ -+ int found, idx; -+ struct hlist_bl_head *hbl; -+ struct hlist_bl_node *pos; -+ struct au_dr_hino *ent; -+ -+ found = 0; -+ idx = au_dr_ihash(ino); -+ hbl = dr->dr_h_ino + idx; -+#if 0 /* debug print */ -+ { -+ struct hlist_bl_node *tmp; -+ -+ hlist_bl_for_each_entry_safe(ent, pos, tmp, hbl, dr_hnode) -+ AuDbg("hi%llu\n", (unsigned long long)ent->dr_h_ino); -+ } -+#endif -+ hlist_bl_lock(hbl); -+ hlist_bl_for_each_entry(ent, pos, hbl, dr_hnode) -+ if (ent->dr_h_ino == ino) { -+ found = 1; -+ break; -+ } -+ if (!found && add_ent) -+ hlist_bl_add_head(&add_ent->dr_hnode, hbl); -+ hlist_bl_unlock(hbl); -+ -+ if (!found && add_ent) -+ AuDbg("i%llu added\n", (unsigned long long)add_ent->dr_h_ino); -+ -+ return found; -+} -+ -+void au_dr_hino_free(struct au_dr_br *dr) -+{ -+ int i; -+ struct hlist_bl_head *hbl; -+ struct hlist_bl_node *pos, *tmp; -+ struct au_dr_hino *ent; -+ -+ /* SiMustWriteLock(sb); */ -+ -+ for (i = 0; i < AuDirren_NHASH; i++) { -+ hbl = dr->dr_h_ino + i; -+ /* no spinlock since sbinfo must be write-locked */ -+ hlist_bl_for_each_entry_safe(ent, pos, tmp, hbl, dr_hnode) -+ au_kfree_rcu(ent); -+ INIT_HLIST_BL_HEAD(hbl); -+ } -+} -+ -+/* returns the number of inodes or an error */ -+static int au_dr_hino_store(struct super_block *sb, struct au_branch *br, -+ struct file *hinofile) -+{ -+ int err, i; -+ ssize_t ssz; -+ loff_t pos, oldsize; -+ __be64 u64; -+ struct inode *hinoinode; -+ struct hlist_bl_head *hbl; -+ struct hlist_bl_node *n1, *n2; -+ struct au_dr_hino *ent; -+ -+ SiMustWriteLock(sb); -+ AuDebugOn(!au_br_writable(br->br_perm)); -+ -+ hinoinode = file_inode(hinofile); -+ oldsize = i_size_read(hinoinode); -+ -+ err = 0; -+ pos = 0; -+ hbl = br->br_dirren.dr_h_ino; -+ for (i = 0; !err && i < AuDirren_NHASH; i++, hbl++) { -+ /* no bit-lock since sbinfo must be write-locked */ -+ hlist_bl_for_each_entry_safe(ent, n1, n2, hbl, dr_hnode) { -+ AuDbg("hi%llu, %pD2\n", -+ (unsigned long long)ent->dr_h_ino, hinofile); -+ u64 = cpu_to_be64(ent->dr_h_ino); -+ ssz = vfsub_write_k(hinofile, &u64, sizeof(u64), &pos); -+ if (ssz == sizeof(u64)) -+ continue; -+ -+ /* write error */ -+ pr_err("ssz %zd, %pD2\n", ssz, hinofile); -+ err = -ENOSPC; -+ if (ssz < 0) -+ err = ssz; -+ break; -+ } -+ } -+ /* regardless the error */ -+ if (pos < oldsize) { -+ err = vfsub_trunc(&hinofile->f_path, pos, /*attr*/0, hinofile); -+ AuTraceErr(err); -+ } -+ -+ AuTraceErr(err); -+ return err; -+} -+ -+static int au_dr_hino_load(struct au_dr_br *dr, struct file *hinofile) -+{ -+ int err, hidx; -+ ssize_t ssz; -+ size_t sz, n; -+ loff_t pos; -+ uint64_t u64; -+ struct au_dr_hino *ent; -+ struct inode *hinoinode; -+ struct hlist_bl_head *hbl; -+ -+ err = 0; -+ pos = 0; -+ hbl = dr->dr_h_ino; -+ hinoinode = file_inode(hinofile); -+ sz = i_size_read(hinoinode); -+ AuDebugOn(sz % sizeof(u64)); -+ n = sz / sizeof(u64); -+ while (n--) { -+ ssz = vfsub_read_k(hinofile, &u64, sizeof(u64), &pos); -+ if (unlikely(ssz != sizeof(u64))) { -+ pr_err("ssz %zd, %pD2\n", ssz, hinofile); -+ err = -EINVAL; -+ if (ssz < 0) -+ err = ssz; -+ goto out_free; -+ } -+ -+ ent = kmalloc(sizeof(*ent), GFP_NOFS); -+ if (!ent) { -+ err = -ENOMEM; -+ AuTraceErr(err); -+ goto out_free; -+ } -+ ent->dr_h_ino = be64_to_cpu((__force __be64)u64); -+ AuDbg("hi%llu, %pD2\n", -+ (unsigned long long)ent->dr_h_ino, hinofile); -+ hidx = au_dr_ihash(ent->dr_h_ino); -+ au_hbl_add(&ent->dr_hnode, hbl + hidx); -+ } -+ goto out; /* success */ -+ -+out_free: -+ au_dr_hino_free(dr); -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+/* -+ * @bindex/@br is a switch to distinguish whether suspending hnotify or not. -+ * @path is a switch to distinguish load and store. -+ */ -+static int au_dr_hino(struct super_block *sb, aufs_bindex_t bindex, -+ struct au_branch *br, const struct path *path) -+{ -+ int err, flags; -+ unsigned char load, suspend; -+ struct file *hinofile; -+ struct au_hinode *hdir; -+ struct inode *dir, *delegated; -+ struct path hinopath; -+ struct qstr hinoname = QSTR_INIT(AUFS_WH_DR_BRHINO, -+ sizeof(AUFS_WH_DR_BRHINO) - 1); -+ -+ AuDebugOn(bindex < 0 && !br); -+ AuDebugOn(bindex >= 0 && br); -+ -+ err = -EINVAL; -+ suspend = !br; -+ if (suspend) -+ br = au_sbr(sb, bindex); -+ load = !!path; -+ if (!load) { -+ path = &br->br_path; -+ AuDebugOn(!au_br_writable(br->br_perm)); -+ if (unlikely(!au_br_writable(br->br_perm))) -+ goto out; -+ } -+ -+ hdir = NULL; -+ if (suspend) { -+ dir = d_inode(sb->s_root); -+ hdir = au_hinode(au_ii(dir), bindex); -+ dir = hdir->hi_inode; -+ au_hn_inode_lock_nested(hdir, AuLsc_I_CHILD); -+ } else { -+ dir = d_inode(path->dentry); -+ inode_lock_nested(dir, AuLsc_I_CHILD); -+ } -+ hinopath.dentry = vfsub_lkup_one(&hinoname, path->dentry); -+ err = PTR_ERR(hinopath.dentry); -+ if (IS_ERR(hinopath.dentry)) -+ goto out_unlock; -+ -+ err = 0; -+ flags = O_RDONLY; -+ if (load) { -+ if (d_is_negative(hinopath.dentry)) -+ goto out_dput; /* success */ -+ } else { -+ if (au_dr_hino_test_empty(&br->br_dirren)) { -+ if (d_is_positive(hinopath.dentry)) { -+ delegated = NULL; -+ err = vfsub_unlink(dir, &hinopath, &delegated, -+ /*force*/0); -+ AuTraceErr(err); -+ if (unlikely(err)) -+ pr_err("ignored err %d, %pd2\n", -+ err, hinopath.dentry); -+ if (unlikely(err == -EWOULDBLOCK)) -+ iput(delegated); -+ err = 0; -+ } -+ goto out_dput; -+ } else if (!d_is_positive(hinopath.dentry)) { -+ err = vfsub_create(dir, &hinopath, 0600, -+ /*want_excl*/false); -+ AuTraceErr(err); -+ if (unlikely(err)) -+ goto out_dput; -+ } -+ flags = O_WRONLY; -+ } -+ hinopath.mnt = path->mnt; -+ hinofile = vfsub_dentry_open(&hinopath, flags); -+ if (suspend) -+ au_hn_inode_unlock(hdir); -+ else -+ inode_unlock(dir); -+ dput(hinopath.dentry); -+ AuTraceErrPtr(hinofile); -+ if (IS_ERR(hinofile)) { -+ err = PTR_ERR(hinofile); -+ goto out; -+ } -+ -+ if (load) -+ err = au_dr_hino_load(&br->br_dirren, hinofile); -+ else -+ err = au_dr_hino_store(sb, br, hinofile); -+ fput(hinofile); -+ goto out; -+ -+out_dput: -+ dput(hinopath.dentry); -+out_unlock: -+ if (suspend) -+ au_hn_inode_unlock(hdir); -+ else -+ inode_unlock(dir); -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int au_dr_brid_init(struct au_dr_brid *brid, const struct path *path) -+{ -+ int err; -+ struct kstatfs kstfs; -+ dev_t dev; -+ struct dentry *dentry; -+ struct super_block *sb; -+ -+ err = vfs_statfs((void *)path, &kstfs); -+ AuTraceErr(err); -+ if (unlikely(err)) -+ goto out; -+ -+ /* todo: support for UUID */ -+ -+ if (kstfs.f_fsid.val[0] || kstfs.f_fsid.val[1]) { -+ brid->type = AuBrid_FSID; -+ brid->fsid = kstfs.f_fsid; -+ } else { -+ dentry = path->dentry; -+ sb = dentry->d_sb; -+ dev = sb->s_dev; -+ if (dev) { -+ brid->type = AuBrid_DEV; -+ brid->dev = dev; -+ } -+ } -+ -+out: -+ return err; -+} -+ -+int au_dr_br_init(struct super_block *sb, struct au_branch *br, -+ const struct path *path) -+{ -+ int err, i; -+ struct au_dr_br *dr; -+ struct hlist_bl_head *hbl; -+ -+ dr = &br->br_dirren; -+ hbl = dr->dr_h_ino; -+ for (i = 0; i < AuDirren_NHASH; i++, hbl++) -+ INIT_HLIST_BL_HEAD(hbl); -+ -+ err = au_dr_brid_init(&dr->dr_brid, path); -+ if (unlikely(err)) -+ goto out; -+ -+ if (au_opt_test(au_mntflags(sb), DIRREN)) -+ err = au_dr_hino(sb, /*bindex*/-1, br, path); -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+int au_dr_br_fin(struct super_block *sb, struct au_branch *br) -+{ -+ int err; -+ -+ err = 0; -+ if (au_br_writable(br->br_perm)) -+ err = au_dr_hino(sb, /*bindex*/-1, br, /*path*/NULL); -+ if (!err) -+ au_dr_hino_free(&br->br_dirren); -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int au_brid_str(struct au_dr_brid *brid, struct inode *h_inode, -+ char *buf, size_t sz) -+{ -+ int err; -+ unsigned int major, minor; -+ char *p; -+ -+ p = buf; -+ err = snprintf(p, sz, "%d_", brid->type); -+ AuDebugOn(err > sz); -+ p += err; -+ sz -= err; -+ switch (brid->type) { -+ case AuBrid_Unset: -+ return -EINVAL; -+ case AuBrid_UUID: -+ err = snprintf(p, sz, "%pU", brid->uuid.b); -+ break; -+ case AuBrid_FSID: -+ err = snprintf(p, sz, "%08x-%08x", -+ brid->fsid.val[0], brid->fsid.val[1]); -+ break; -+ case AuBrid_DEV: -+ major = MAJOR(brid->dev); -+ minor = MINOR(brid->dev); -+ if (major <= 0xff && minor <= 0xff) -+ err = snprintf(p, sz, "%02x%02x", major, minor); -+ else -+ err = snprintf(p, sz, "%03x:%05x", major, minor); -+ break; -+ } -+ AuDebugOn(err > sz); -+ p += err; -+ sz -= err; -+ err = snprintf(p, sz, "_%llu", (unsigned long long)h_inode->i_ino); -+ AuDebugOn(err > sz); -+ p += err; -+ sz -= err; -+ -+ return p - buf; -+} -+ -+static int au_drinfo_name(struct au_branch *br, char *name, int len) -+{ -+ int rlen; -+ struct dentry *br_dentry; -+ struct inode *br_inode; -+ -+ br_dentry = au_br_dentry(br); -+ br_inode = d_inode(br_dentry); -+ rlen = au_brid_str(&br->br_dirren.dr_brid, br_inode, name, len); -+ AuDebugOn(rlen >= AUFS_DIRREN_ENV_VAL_SZ); -+ AuDebugOn(rlen > len); -+ -+ return rlen; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * from the given @h_dentry, construct drinfo at @*fdata. -+ * when the size of @*fdata is not enough, reallocate and return new @fdata and -+ * @allocated. -+ */ -+static int au_drinfo_construct(struct au_drinfo_fdata **fdata, -+ struct dentry *h_dentry, -+ unsigned char *allocated) -+{ -+ int err, v; -+ struct au_drinfo_fdata *f, *p; -+ struct au_drinfo *drinfo; -+ struct inode *h_inode; -+ struct qstr *qname; -+ -+ err = 0; -+ f = *fdata; -+ h_inode = d_inode(h_dentry); -+ qname = &h_dentry->d_name; -+ drinfo = &f->drinfo; -+ drinfo->ino = (__force uint64_t)cpu_to_be64(h_inode->i_ino); -+ drinfo->oldnamelen = qname->len; -+ if (*allocated < sizeof(*f) + qname->len) { -+ v = roundup_pow_of_two(*allocated + qname->len); -+ p = au_krealloc(f, v, GFP_NOFS, /*may_shrink*/0); -+ if (unlikely(!p)) { -+ err = -ENOMEM; -+ AuTraceErr(err); -+ goto out; -+ } -+ f = p; -+ *fdata = f; -+ *allocated = v; -+ drinfo = &f->drinfo; -+ } -+ memcpy(drinfo->oldname, qname->name, qname->len); -+ AuDbg("i%llu, %.*s\n", -+ be64_to_cpu((__force __be64)drinfo->ino), drinfo->oldnamelen, -+ drinfo->oldname); -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+/* callers have to free the return value */ -+static struct au_drinfo *au_drinfo_read_k(struct file *file, ino_t h_ino) -+{ -+ struct au_drinfo *ret, *drinfo; -+ struct au_drinfo_fdata fdata; -+ int len; -+ loff_t pos; -+ ssize_t ssz; -+ -+ ret = ERR_PTR(-EIO); -+ pos = 0; -+ ssz = vfsub_read_k(file, &fdata, sizeof(fdata), &pos); -+ if (unlikely(ssz != sizeof(fdata))) { -+ AuIOErr("ssz %zd, %u, %pD2\n", -+ ssz, (unsigned int)sizeof(fdata), file); -+ goto out; -+ } -+ -+ fdata.magic = ntohl((__force __be32)fdata.magic); -+ switch (fdata.magic) { -+ case AUFS_DRINFO_MAGIC_V1: -+ break; -+ default: -+ AuIOErr("magic-num 0x%x, 0x%x, %pD2\n", -+ fdata.magic, AUFS_DRINFO_MAGIC_V1, file); -+ goto out; -+ } -+ -+ drinfo = &fdata.drinfo; -+ len = drinfo->oldnamelen; -+ if (!len) { -+ AuIOErr("broken drinfo %pD2\n", file); -+ goto out; -+ } -+ -+ ret = NULL; -+ drinfo->ino = be64_to_cpu((__force __be64)drinfo->ino); -+ if (unlikely(h_ino && drinfo->ino != h_ino)) { -+ AuDbg("ignored i%llu, i%llu, %pD2\n", -+ (unsigned long long)drinfo->ino, -+ (unsigned long long)h_ino, file); -+ goto out; /* success */ -+ } -+ -+ ret = kmalloc(sizeof(*ret) + len, GFP_NOFS); -+ if (unlikely(!ret)) { -+ ret = ERR_PTR(-ENOMEM); -+ AuTraceErrPtr(ret); -+ goto out; -+ } -+ -+ *ret = *drinfo; -+ ssz = vfsub_read_k(file, (void *)ret->oldname, len, &pos); -+ if (unlikely(ssz != len)) { -+ au_kfree_rcu(ret); -+ ret = ERR_PTR(-EIO); -+ AuIOErr("ssz %zd, %u, %pD2\n", ssz, len, file); -+ goto out; -+ } -+ -+ AuDbg("oldname %.*s\n", ret->oldnamelen, ret->oldname); -+ -+out: -+ return ret; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* in order to be revertible */ -+struct au_drinfo_rev_elm { -+ int created; -+ struct dentry *info_dentry; -+ struct au_drinfo *info_last; -+}; -+ -+struct au_drinfo_rev { -+ unsigned char already; -+ aufs_bindex_t nelm; -+ struct au_drinfo_rev_elm elm[0]; -+}; -+ -+/* todo: isn't it too large? */ -+struct au_drinfo_store { -+ struct path h_ppath; -+ struct dentry *h_dentry; -+ struct au_drinfo_fdata *fdata; -+ char *infoname; /* inside of whname, just after PFX */ -+ char whname[sizeof(AUFS_WH_DR_INFO_PFX) + AUFS_DIRREN_ENV_VAL_SZ]; -+ aufs_bindex_t btgt, btail; -+ unsigned char no_sio, -+ allocated, /* current size of *fdata */ -+ infonamelen, /* room size for p */ -+ whnamelen, /* length of the generated name */ -+ renameback; /* renamed back */ -+}; -+ -+/* on rename(2) error, the caller should revert it using @elm */ -+static int au_drinfo_do_store(struct au_drinfo_store *w, -+ struct au_drinfo_rev_elm *elm) -+{ -+ int err, len; -+ ssize_t ssz; -+ loff_t pos; -+ struct path infopath = { -+ .mnt = w->h_ppath.mnt -+ }; -+ struct inode *h_dir, *h_inode, *delegated; -+ struct file *infofile; -+ struct qstr *qname; -+ -+ AuDebugOn(elm -+ && memcmp(elm, page_address(ZERO_PAGE(0)), sizeof(*elm))); -+ -+ infopath.dentry = vfsub_lookup_one_len(w->whname, w->h_ppath.dentry, -+ w->whnamelen); -+ AuTraceErrPtr(infopath.dentry); -+ if (IS_ERR(infopath.dentry)) { -+ err = PTR_ERR(infopath.dentry); -+ goto out; -+ } -+ -+ err = 0; -+ h_dir = d_inode(w->h_ppath.dentry); -+ if (elm && d_is_negative(infopath.dentry)) { -+ err = vfsub_create(h_dir, &infopath, 0600, /*want_excl*/true); -+ AuTraceErr(err); -+ if (unlikely(err)) -+ goto out_dput; -+ elm->created = 1; -+ elm->info_dentry = dget(infopath.dentry); -+ } -+ -+ infofile = vfsub_dentry_open(&infopath, O_RDWR); -+ AuTraceErrPtr(infofile); -+ if (IS_ERR(infofile)) { -+ err = PTR_ERR(infofile); -+ goto out_dput; -+ } -+ -+ h_inode = d_inode(infopath.dentry); -+ if (elm && i_size_read(h_inode)) { -+ h_inode = d_inode(w->h_dentry); -+ elm->info_last = au_drinfo_read_k(infofile, h_inode->i_ino); -+ AuTraceErrPtr(elm->info_last); -+ if (IS_ERR(elm->info_last)) { -+ err = PTR_ERR(elm->info_last); -+ elm->info_last = NULL; -+ AuDebugOn(elm->info_dentry); -+ goto out_fput; -+ } -+ } -+ -+ if (elm && w->renameback) { -+ delegated = NULL; -+ err = vfsub_unlink(h_dir, &infopath, &delegated, /*force*/0); -+ AuTraceErr(err); -+ if (unlikely(err == -EWOULDBLOCK)) -+ iput(delegated); -+ goto out_fput; -+ } -+ -+ pos = 0; -+ qname = &w->h_dentry->d_name; -+ len = sizeof(*w->fdata) + qname->len; -+ if (!elm) -+ len = sizeof(*w->fdata) + w->fdata->drinfo.oldnamelen; -+ ssz = vfsub_write_k(infofile, w->fdata, len, &pos); -+ if (ssz == len) { -+ AuDbg("hi%llu, %.*s\n", w->fdata->drinfo.ino, -+ w->fdata->drinfo.oldnamelen, w->fdata->drinfo.oldname); -+ goto out_fput; /* success */ -+ } else { -+ err = -EIO; -+ if (ssz < 0) -+ err = ssz; -+ /* the caller should revert it using @elm */ -+ } -+ -+out_fput: -+ fput(infofile); -+out_dput: -+ dput(infopath.dentry); -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+struct au_call_drinfo_do_store_args { -+ int *errp; -+ struct au_drinfo_store *w; -+ struct au_drinfo_rev_elm *elm; -+}; -+ -+static void au_call_drinfo_do_store(void *args) -+{ -+ struct au_call_drinfo_do_store_args *a = args; -+ -+ *a->errp = au_drinfo_do_store(a->w, a->elm); -+} -+ -+static int au_drinfo_store_sio(struct au_drinfo_store *w, -+ struct au_drinfo_rev_elm *elm) -+{ -+ int err, wkq_err; -+ -+ if (w->no_sio) -+ err = au_drinfo_do_store(w, elm); -+ else { -+ struct au_call_drinfo_do_store_args a = { -+ .errp = &err, -+ .w = w, -+ .elm = elm -+ }; -+ wkq_err = au_wkq_wait(au_call_drinfo_do_store, &a); -+ if (unlikely(wkq_err)) -+ err = wkq_err; -+ } -+ AuTraceErr(err); -+ -+ return err; -+} -+ -+static int au_drinfo_store_work_init(struct au_drinfo_store *w, -+ aufs_bindex_t btgt) -+{ -+ int err; -+ -+ memset(w, 0, sizeof(*w)); -+ w->allocated = roundup_pow_of_two(sizeof(*w->fdata) + 40); -+ strcpy(w->whname, AUFS_WH_DR_INFO_PFX); -+ w->infoname = w->whname + sizeof(AUFS_WH_DR_INFO_PFX) - 1; -+ w->infonamelen = sizeof(w->whname) - sizeof(AUFS_WH_DR_INFO_PFX); -+ w->btgt = btgt; -+ w->no_sio = !!uid_eq(current_fsuid(), GLOBAL_ROOT_UID); -+ -+ err = -ENOMEM; -+ w->fdata = kcalloc(1, w->allocated, GFP_NOFS); -+ if (unlikely(!w->fdata)) { -+ AuTraceErr(err); -+ goto out; -+ } -+ w->fdata->magic = (__force uint32_t)htonl(AUFS_DRINFO_MAGIC_V1); -+ err = 0; -+ -+out: -+ return err; -+} -+ -+static void au_drinfo_store_work_fin(struct au_drinfo_store *w) -+{ -+ au_kfree_rcu(w->fdata); -+} -+ -+static void au_drinfo_store_rev(struct au_drinfo_rev *rev, -+ struct au_drinfo_store *w) -+{ -+ struct au_drinfo_rev_elm *elm; -+ struct inode *h_dir, *delegated; -+ int err, nelm; -+ struct path infopath = { -+ .mnt = w->h_ppath.mnt -+ }; -+ -+ h_dir = d_inode(w->h_ppath.dentry); -+ IMustLock(h_dir); -+ -+ err = 0; -+ elm = rev->elm; -+ for (nelm = rev->nelm; nelm > 0; nelm--, elm++) { -+ AuDebugOn(elm->created && elm->info_last); -+ if (elm->created) { -+ AuDbg("here\n"); -+ delegated = NULL; -+ infopath.dentry = elm->info_dentry; -+ err = vfsub_unlink(h_dir, &infopath, &delegated, -+ !w->no_sio); -+ AuTraceErr(err); -+ if (unlikely(err == -EWOULDBLOCK)) -+ iput(delegated); -+ dput(elm->info_dentry); -+ } else if (elm->info_last) { -+ AuDbg("here\n"); -+ w->fdata->drinfo = *elm->info_last; -+ memcpy(w->fdata->drinfo.oldname, -+ elm->info_last->oldname, -+ elm->info_last->oldnamelen); -+ err = au_drinfo_store_sio(w, /*elm*/NULL); -+ au_kfree_rcu(elm->info_last); -+ } -+ if (unlikely(err)) -+ AuIOErr("%d, %s\n", err, w->whname); -+ /* go on even if err */ -+ } -+} -+ -+/* caller has to call au_dr_rename_fin() later */ -+static int au_drinfo_store(struct dentry *dentry, aufs_bindex_t btgt, -+ struct qstr *dst_name, void *_rev) -+{ -+ int err, sz, nelm; -+ aufs_bindex_t bindex, btail; -+ struct au_drinfo_store work; -+ struct au_drinfo_rev *rev, **p; -+ struct au_drinfo_rev_elm *elm; -+ struct super_block *sb; -+ struct au_branch *br; -+ struct au_hinode *hdir; -+ -+ err = au_drinfo_store_work_init(&work, btgt); -+ AuTraceErr(err); -+ if (unlikely(err)) -+ goto out; -+ -+ err = -ENOMEM; -+ btail = au_dbtaildir(dentry); -+ nelm = btail - btgt; -+ sz = sizeof(*rev) + sizeof(*elm) * nelm; -+ rev = kcalloc(1, sz, GFP_NOFS); -+ if (unlikely(!rev)) { -+ AuTraceErr(err); -+ goto out_args; -+ } -+ rev->nelm = nelm; -+ elm = rev->elm; -+ p = _rev; -+ *p = rev; -+ -+ err = 0; -+ sb = dentry->d_sb; -+ work.h_ppath.dentry = au_h_dptr(dentry, btgt); -+ work.h_ppath.mnt = au_sbr_mnt(sb, btgt); -+ hdir = au_hi(d_inode(dentry), btgt); -+ au_hn_inode_lock_nested(hdir, AuLsc_I_CHILD); -+ for (bindex = btgt + 1; bindex <= btail; bindex++, elm++) { -+ work.h_dentry = au_h_dptr(dentry, bindex); -+ if (!work.h_dentry) -+ continue; -+ -+ err = au_drinfo_construct(&work.fdata, work.h_dentry, -+ &work.allocated); -+ AuTraceErr(err); -+ if (unlikely(err)) -+ break; -+ -+ work.renameback = au_qstreq(&work.h_dentry->d_name, dst_name); -+ br = au_sbr(sb, bindex); -+ work.whnamelen = sizeof(AUFS_WH_DR_INFO_PFX) - 1; -+ work.whnamelen += au_drinfo_name(br, work.infoname, -+ work.infonamelen); -+ AuDbg("whname %.*s, i%llu, %.*s\n", -+ work.whnamelen, work.whname, -+ be64_to_cpu((__force __be64)work.fdata->drinfo.ino), -+ work.fdata->drinfo.oldnamelen, -+ work.fdata->drinfo.oldname); -+ -+ err = au_drinfo_store_sio(&work, elm); -+ AuTraceErr(err); -+ if (unlikely(err)) -+ break; -+ } -+ if (unlikely(err)) { -+ /* revert all drinfo */ -+ au_drinfo_store_rev(rev, &work); -+ au_kfree_try_rcu(rev); -+ *p = NULL; -+ } -+ au_hn_inode_unlock(hdir); -+ -+out_args: -+ au_drinfo_store_work_fin(&work); -+out: -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+int au_dr_rename(struct dentry *src, aufs_bindex_t bindex, -+ struct qstr *dst_name, void *_rev) -+{ -+ int err, already; -+ ino_t ino; -+ struct super_block *sb; -+ struct au_branch *br; -+ struct au_dr_br *dr; -+ struct dentry *h_dentry; -+ struct inode *h_inode; -+ struct au_dr_hino *ent; -+ struct au_drinfo_rev *rev, **p; -+ -+ AuDbg("bindex %d\n", bindex); -+ -+ err = -ENOMEM; -+ ent = kmalloc(sizeof(*ent), GFP_NOFS); -+ if (unlikely(!ent)) -+ goto out; -+ -+ sb = src->d_sb; -+ br = au_sbr(sb, bindex); -+ dr = &br->br_dirren; -+ h_dentry = au_h_dptr(src, bindex); -+ h_inode = d_inode(h_dentry); -+ ino = h_inode->i_ino; -+ ent->dr_h_ino = ino; -+ already = au_dr_hino_test_add(dr, ino, ent); -+ AuDbg("b%d, hi%llu, already %d\n", -+ bindex, (unsigned long long)ino, already); -+ -+ err = au_drinfo_store(src, bindex, dst_name, _rev); -+ AuTraceErr(err); -+ if (!err) { -+ p = _rev; -+ rev = *p; -+ rev->already = already; -+ goto out; /* success */ -+ } -+ -+ /* revert */ -+ if (!already) -+ au_dr_hino_del(dr, ent); -+ au_kfree_rcu(ent); -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+void au_dr_rename_fin(struct dentry *src, aufs_bindex_t btgt, void *_rev) -+{ -+ struct au_drinfo_rev *rev; -+ struct au_drinfo_rev_elm *elm; -+ int nelm; -+ -+ rev = _rev; -+ elm = rev->elm; -+ for (nelm = rev->nelm; nelm > 0; nelm--, elm++) { -+ dput(elm->info_dentry); -+ au_kfree_rcu(elm->info_last); -+ } -+ au_kfree_try_rcu(rev); -+} -+ -+void au_dr_rename_rev(struct dentry *src, aufs_bindex_t btgt, void *_rev) -+{ -+ int err; -+ struct au_drinfo_store work; -+ struct au_drinfo_rev *rev = _rev; -+ struct super_block *sb; -+ struct au_branch *br; -+ struct inode *h_inode; -+ struct au_dr_br *dr; -+ struct au_dr_hino *ent; -+ -+ err = au_drinfo_store_work_init(&work, btgt); -+ if (unlikely(err)) -+ goto out; -+ -+ sb = src->d_sb; -+ br = au_sbr(sb, btgt); -+ work.h_ppath.dentry = au_h_dptr(src, btgt); -+ work.h_ppath.mnt = au_br_mnt(br); -+ au_drinfo_store_rev(rev, &work); -+ au_drinfo_store_work_fin(&work); -+ if (rev->already) -+ goto out; -+ -+ dr = &br->br_dirren; -+ h_inode = d_inode(work.h_ppath.dentry); -+ ent = au_dr_hino_find(dr, h_inode->i_ino); -+ BUG_ON(!ent); -+ au_dr_hino_del(dr, ent); -+ au_kfree_rcu(ent); -+ -+out: -+ au_kfree_try_rcu(rev); -+ if (unlikely(err)) -+ pr_err("failed to remove dirren info\n"); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static struct au_drinfo *au_drinfo_do_load(struct path *h_ppath, -+ char *whname, int whnamelen, -+ struct dentry **info_dentry) -+{ -+ struct au_drinfo *drinfo; -+ struct file *f; -+ struct inode *h_dir; -+ struct path infopath; -+ int unlocked; -+ -+ AuDbg("%pd/%.*s\n", h_ppath->dentry, whnamelen, whname); -+ -+ *info_dentry = NULL; -+ drinfo = NULL; -+ unlocked = 0; -+ h_dir = d_inode(h_ppath->dentry); -+ inode_lock_shared_nested(h_dir, AuLsc_I_PARENT); -+ infopath.dentry = vfsub_lookup_one_len(whname, h_ppath->dentry, -+ whnamelen); -+ if (IS_ERR(infopath.dentry)) { -+ drinfo = (void *)infopath.dentry; -+ goto out; -+ } -+ -+ if (d_is_negative(infopath.dentry)) -+ goto out_dput; /* success */ -+ -+ infopath.mnt = h_ppath->mnt; -+ f = vfsub_dentry_open(&infopath, O_RDONLY); -+ inode_unlock_shared(h_dir); -+ unlocked = 1; -+ if (IS_ERR(f)) { -+ drinfo = (void *)f; -+ goto out_dput; -+ } -+ -+ drinfo = au_drinfo_read_k(f, /*h_ino*/0); -+ if (IS_ERR_OR_NULL(drinfo)) -+ goto out_fput; -+ -+ AuDbg("oldname %.*s\n", drinfo->oldnamelen, drinfo->oldname); -+ *info_dentry = dget(infopath.dentry); /* keep it alive */ -+ -+out_fput: -+ fput(f); -+out_dput: -+ dput(infopath.dentry); -+out: -+ if (!unlocked) -+ inode_unlock_shared(h_dir); -+ AuTraceErrPtr(drinfo); -+ return drinfo; -+} -+ -+struct au_drinfo_do_load_args { -+ struct au_drinfo **drinfop; -+ struct path *h_ppath; -+ char *whname; -+ int whnamelen; -+ struct dentry **info_dentry; -+}; -+ -+static void au_call_drinfo_do_load(void *args) -+{ -+ struct au_drinfo_do_load_args *a = args; -+ -+ *a->drinfop = au_drinfo_do_load(a->h_ppath, a->whname, a->whnamelen, -+ a->info_dentry); -+} -+ -+struct au_drinfo_load { -+ struct path h_ppath; -+ struct qstr *qname; -+ unsigned char no_sio; -+ -+ aufs_bindex_t ninfo; -+ struct au_drinfo **drinfo; -+}; -+ -+static int au_drinfo_load(struct au_drinfo_load *w, aufs_bindex_t bindex, -+ struct au_branch *br) -+{ -+ int err, wkq_err, whnamelen, e; -+ char whname[sizeof(AUFS_WH_DR_INFO_PFX) + AUFS_DIRREN_ENV_VAL_SZ] -+ = AUFS_WH_DR_INFO_PFX; -+ struct au_drinfo *drinfo; -+ struct qstr oldname; -+ struct inode *h_dir, *delegated; -+ struct dentry *info_dentry; -+ struct path infopath; -+ -+ whnamelen = sizeof(AUFS_WH_DR_INFO_PFX) - 1; -+ whnamelen += au_drinfo_name(br, whname + whnamelen, -+ sizeof(whname) - whnamelen); -+ if (w->no_sio) -+ drinfo = au_drinfo_do_load(&w->h_ppath, whname, whnamelen, -+ &info_dentry); -+ else { -+ struct au_drinfo_do_load_args args = { -+ .drinfop = &drinfo, -+ .h_ppath = &w->h_ppath, -+ .whname = whname, -+ .whnamelen = whnamelen, -+ .info_dentry = &info_dentry -+ }; -+ wkq_err = au_wkq_wait(au_call_drinfo_do_load, &args); -+ if (unlikely(wkq_err)) -+ drinfo = ERR_PTR(wkq_err); -+ } -+ err = PTR_ERR(drinfo); -+ if (IS_ERR_OR_NULL(drinfo)) -+ goto out; -+ -+ err = 0; -+ oldname.len = drinfo->oldnamelen; -+ oldname.name = drinfo->oldname; -+ if (au_qstreq(w->qname, &oldname)) { -+ /* the name is renamed back */ -+ au_kfree_rcu(drinfo); -+ drinfo = NULL; -+ -+ infopath.dentry = info_dentry; -+ infopath.mnt = w->h_ppath.mnt; -+ h_dir = d_inode(w->h_ppath.dentry); -+ delegated = NULL; -+ inode_lock_nested(h_dir, AuLsc_I_PARENT); -+ e = vfsub_unlink(h_dir, &infopath, &delegated, !w->no_sio); -+ inode_unlock(h_dir); -+ if (unlikely(e)) -+ AuIOErr("ignored %d, %pd2\n", e, &infopath.dentry); -+ if (unlikely(e == -EWOULDBLOCK)) -+ iput(delegated); -+ } -+ au_kfree_rcu(w->drinfo[bindex]); -+ w->drinfo[bindex] = drinfo; -+ dput(info_dentry); -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static void au_dr_lkup_free(struct au_drinfo **drinfo, int n) -+{ -+ struct au_drinfo **p = drinfo; -+ -+ while (n-- > 0) -+ au_kfree_rcu(*drinfo++); -+ au_kfree_try_rcu(p); -+} -+ -+int au_dr_lkup(struct au_do_lookup_args *lkup, struct dentry *dentry, -+ aufs_bindex_t btgt) -+{ -+ int err, ninfo; -+ struct au_drinfo_load w; -+ aufs_bindex_t bindex, bbot; -+ struct au_branch *br; -+ struct inode *h_dir; -+ struct au_dr_hino *ent; -+ struct super_block *sb; -+ -+ AuDbg("%.*s, name %.*s, whname %.*s, b%d\n", -+ AuLNPair(&dentry->d_name), AuLNPair(&lkup->dirren.dr_name), -+ AuLNPair(&lkup->whname), btgt); -+ -+ sb = dentry->d_sb; -+ bbot = au_sbbot(sb); -+ w.ninfo = bbot + 1; -+ if (!lkup->dirren.drinfo) { -+ lkup->dirren.drinfo = kcalloc(w.ninfo, -+ sizeof(*lkup->dirren.drinfo), -+ GFP_NOFS); -+ if (unlikely(!lkup->dirren.drinfo)) { -+ err = -ENOMEM; -+ goto out; -+ } -+ lkup->dirren.ninfo = w.ninfo; -+ } -+ w.drinfo = lkup->dirren.drinfo; -+ w.no_sio = !!uid_eq(current_fsuid(), GLOBAL_ROOT_UID); -+ w.h_ppath.dentry = au_h_dptr(dentry, btgt); -+ AuDebugOn(!w.h_ppath.dentry); -+ w.h_ppath.mnt = au_sbr_mnt(sb, btgt); -+ w.qname = &dentry->d_name; -+ -+ ninfo = 0; -+ for (bindex = btgt + 1; bindex <= bbot; bindex++) { -+ br = au_sbr(sb, bindex); -+ err = au_drinfo_load(&w, bindex, br); -+ if (unlikely(err)) -+ goto out_free; -+ if (w.drinfo[bindex]) -+ ninfo++; -+ } -+ if (!ninfo) { -+ br = au_sbr(sb, btgt); -+ h_dir = d_inode(w.h_ppath.dentry); -+ ent = au_dr_hino_find(&br->br_dirren, h_dir->i_ino); -+ AuDebugOn(!ent); -+ au_dr_hino_del(&br->br_dirren, ent); -+ au_kfree_rcu(ent); -+ } -+ goto out; /* success */ -+ -+out_free: -+ au_dr_lkup_free(lkup->dirren.drinfo, lkup->dirren.ninfo); -+ lkup->dirren.ninfo = 0; -+ lkup->dirren.drinfo = NULL; -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+void au_dr_lkup_fin(struct au_do_lookup_args *lkup) -+{ -+ au_dr_lkup_free(lkup->dirren.drinfo, lkup->dirren.ninfo); -+} -+ -+int au_dr_lkup_name(struct au_do_lookup_args *lkup, aufs_bindex_t btgt) -+{ -+ int err; -+ struct au_drinfo *drinfo; -+ -+ err = 0; -+ if (!lkup->dirren.drinfo) -+ goto out; -+ AuDebugOn(lkup->dirren.ninfo <= btgt); -+ drinfo = lkup->dirren.drinfo[btgt]; -+ if (!drinfo) -+ goto out; -+ -+ au_kfree_try_rcu(lkup->whname.name); -+ lkup->whname.name = NULL; -+ lkup->dirren.dr_name.len = drinfo->oldnamelen; -+ lkup->dirren.dr_name.name = drinfo->oldname; -+ lkup->name = &lkup->dirren.dr_name; -+ err = au_wh_name_alloc(&lkup->whname, lkup->name); -+ if (!err) -+ AuDbg("name %.*s, whname %.*s, b%d\n", -+ AuLNPair(lkup->name), AuLNPair(&lkup->whname), -+ btgt); -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+int au_dr_lkup_h_ino(struct au_do_lookup_args *lkup, aufs_bindex_t bindex, -+ ino_t h_ino) -+{ -+ int match; -+ struct au_drinfo *drinfo; -+ -+ match = 1; -+ if (!lkup->dirren.drinfo) -+ goto out; -+ AuDebugOn(lkup->dirren.ninfo <= bindex); -+ drinfo = lkup->dirren.drinfo[bindex]; -+ if (!drinfo) -+ goto out; -+ -+ match = (drinfo->ino == h_ino); -+ AuDbg("match %d\n", match); -+ -+out: -+ return match; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+int au_dr_opt_set(struct super_block *sb) -+{ -+ int err; -+ aufs_bindex_t bindex, bbot; -+ struct au_branch *br; -+ -+ err = 0; -+ bbot = au_sbbot(sb); -+ for (bindex = 0; !err && bindex <= bbot; bindex++) { -+ br = au_sbr(sb, bindex); -+ err = au_dr_hino(sb, bindex, /*br*/NULL, &br->br_path); -+ } -+ -+ return err; -+} -+ -+int au_dr_opt_flush(struct super_block *sb) -+{ -+ int err; -+ aufs_bindex_t bindex, bbot; -+ struct au_branch *br; -+ -+ err = 0; -+ bbot = au_sbbot(sb); -+ for (bindex = 0; !err && bindex <= bbot; bindex++) { -+ br = au_sbr(sb, bindex); -+ if (au_br_writable(br->br_perm)) -+ err = au_dr_hino(sb, bindex, /*br*/NULL, /*path*/NULL); -+ } -+ -+ return err; -+} -+ -+int au_dr_opt_clr(struct super_block *sb, int no_flush) -+{ -+ int err; -+ aufs_bindex_t bindex, bbot; -+ struct au_branch *br; -+ -+ err = 0; -+ if (!no_flush) { -+ err = au_dr_opt_flush(sb); -+ if (unlikely(err)) -+ goto out; -+ } -+ -+ bbot = au_sbbot(sb); -+ for (bindex = 0; bindex <= bbot; bindex++) { -+ br = au_sbr(sb, bindex); -+ au_dr_hino_free(&br->br_dirren); -+ } -+ -+out: -+ return err; -+} -diff -Nurp linux-5.6.3/fs/aufs/dirren.h linux-5.6.3-aufs/fs/aufs/dirren.h ---- linux-5.6.3/fs/aufs/dirren.h 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/dirren.h 2020-04-10 12:40:52.190049409 +0300 -@@ -0,0 +1,127 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2017-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * renamed dir info -+ */ -+ -+#ifndef __AUFS_DIRREN_H__ -+#define __AUFS_DIRREN_H__ -+ -+#ifdef __KERNEL__ -+ -+#include -+#include -+#include -+#include "hbl.h" -+ -+#define AuDirren_NHASH 100 -+ -+#ifdef CONFIG_AUFS_DIRREN -+enum au_brid_type { -+ AuBrid_Unset, -+ AuBrid_UUID, -+ AuBrid_FSID, -+ AuBrid_DEV -+}; -+ -+struct au_dr_brid { -+ enum au_brid_type type; -+ union { -+ uuid_t uuid; /* unimplemented yet */ -+ fsid_t fsid; -+ dev_t dev; -+ }; -+}; -+ -+/* 20 is the max digits length of ulong 64 */ -+/* brid-type "_" uuid "_" inum */ -+#define AUFS_DIRREN_FNAME_SZ (1 + 1 + UUID_STRING_LEN + 20) -+#define AUFS_DIRREN_ENV_VAL_SZ (AUFS_DIRREN_FNAME_SZ + 1 + 20) -+ -+struct au_dr_hino { -+ struct hlist_bl_node dr_hnode; -+ ino_t dr_h_ino; -+}; -+ -+struct au_dr_br { -+ struct hlist_bl_head dr_h_ino[AuDirren_NHASH]; -+ struct au_dr_brid dr_brid; -+}; -+ -+struct au_dr_lookup { -+ /* dr_name is pointed by struct au_do_lookup_args.name */ -+ struct qstr dr_name; /* subset of dr_info */ -+ aufs_bindex_t ninfo; -+ struct au_drinfo **drinfo; -+}; -+#else -+struct au_dr_hino; -+/* empty */ -+struct au_dr_br { }; -+struct au_dr_lookup { }; -+#endif -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct au_branch; -+struct au_do_lookup_args; -+struct au_hinode; -+#ifdef CONFIG_AUFS_DIRREN -+int au_dr_hino_test_add(struct au_dr_br *dr, ino_t h_ino, -+ struct au_dr_hino *add_ent); -+void au_dr_hino_free(struct au_dr_br *dr); -+int au_dr_br_init(struct super_block *sb, struct au_branch *br, -+ const struct path *path); -+int au_dr_br_fin(struct super_block *sb, struct au_branch *br); -+int au_dr_rename(struct dentry *src, aufs_bindex_t bindex, -+ struct qstr *dst_name, void *_rev); -+void au_dr_rename_fin(struct dentry *src, aufs_bindex_t btgt, void *rev); -+void au_dr_rename_rev(struct dentry *src, aufs_bindex_t bindex, void *rev); -+int au_dr_lkup(struct au_do_lookup_args *lkup, struct dentry *dentry, -+ aufs_bindex_t bindex); -+int au_dr_lkup_name(struct au_do_lookup_args *lkup, aufs_bindex_t btgt); -+int au_dr_lkup_h_ino(struct au_do_lookup_args *lkup, aufs_bindex_t bindex, -+ ino_t h_ino); -+void au_dr_lkup_fin(struct au_do_lookup_args *lkup); -+int au_dr_opt_set(struct super_block *sb); -+int au_dr_opt_flush(struct super_block *sb); -+int au_dr_opt_clr(struct super_block *sb, int no_flush); -+#else -+AuStubInt0(au_dr_hino_test_add, struct au_dr_br *dr, ino_t h_ino, -+ struct au_dr_hino *add_ent); -+AuStubVoid(au_dr_hino_free, struct au_dr_br *dr); -+AuStubInt0(au_dr_br_init, struct super_block *sb, struct au_branch *br, -+ const struct path *path); -+AuStubInt0(au_dr_br_fin, struct super_block *sb, struct au_branch *br); -+AuStubInt0(au_dr_rename, struct dentry *src, aufs_bindex_t bindex, -+ struct qstr *dst_name, void *_rev); -+AuStubVoid(au_dr_rename_fin, struct dentry *src, aufs_bindex_t btgt, void *rev); -+AuStubVoid(au_dr_rename_rev, struct dentry *src, aufs_bindex_t bindex, -+ void *rev); -+AuStubInt0(au_dr_lkup, struct au_do_lookup_args *lkup, struct dentry *dentry, -+ aufs_bindex_t bindex); -+AuStubInt0(au_dr_lkup_name, struct au_do_lookup_args *lkup, aufs_bindex_t btgt); -+AuStubInt0(au_dr_lkup_h_ino, struct au_do_lookup_args *lkup, -+ aufs_bindex_t bindex, ino_t h_ino); -+AuStubVoid(au_dr_lkup_fin, struct au_do_lookup_args *lkup); -+AuStubInt0(au_dr_opt_set, struct super_block *sb); -+AuStubInt0(au_dr_opt_flush, struct super_block *sb); -+AuStubInt0(au_dr_opt_clr, struct super_block *sb, int no_flush); -+#endif -+ -+/* ---------------------------------------------------------------------- */ -+ -+#ifdef CONFIG_AUFS_DIRREN -+static inline int au_dr_ihash(ino_t h_ino) -+{ -+ return h_ino % AuDirren_NHASH; -+} -+#else -+AuStubInt0(au_dr_ihash, ino_t h_ino); -+#endif -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_DIRREN_H__ */ -diff -Nurp linux-5.6.3/fs/aufs/dynop.c linux-5.6.3-aufs/fs/aufs/dynop.c ---- linux-5.6.3/fs/aufs/dynop.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/dynop.c 2020-04-10 12:40:52.190049409 +0300 -@@ -0,0 +1,354 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2010-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * dynamically customizable operations for regular files -+ */ -+ -+#include "aufs.h" -+ -+#define DyPrSym(key) AuDbgSym(key->dk_op.dy_hop) -+ -+/* -+ * How large will these lists be? -+ * Usually just a few elements, 20-30 at most for each, I guess. -+ */ -+static struct hlist_bl_head dynop[AuDyLast]; -+ -+static struct au_dykey *dy_gfind_get(struct hlist_bl_head *hbl, -+ const void *h_op) -+{ -+ struct au_dykey *key, *tmp; -+ struct hlist_bl_node *pos; -+ -+ key = NULL; -+ hlist_bl_lock(hbl); -+ hlist_bl_for_each_entry(tmp, pos, hbl, dk_hnode) -+ if (tmp->dk_op.dy_hop == h_op) { -+ if (kref_get_unless_zero(&tmp->dk_kref)) -+ key = tmp; -+ break; -+ } -+ hlist_bl_unlock(hbl); -+ -+ return key; -+} -+ -+static struct au_dykey *dy_bradd(struct au_branch *br, struct au_dykey *key) -+{ -+ struct au_dykey **k, *found; -+ const void *h_op = key->dk_op.dy_hop; -+ int i; -+ -+ found = NULL; -+ k = br->br_dykey; -+ for (i = 0; i < AuBrDynOp; i++) -+ if (k[i]) { -+ if (k[i]->dk_op.dy_hop == h_op) { -+ found = k[i]; -+ break; -+ } -+ } else -+ break; -+ if (!found) { -+ spin_lock(&br->br_dykey_lock); -+ for (; i < AuBrDynOp; i++) -+ if (k[i]) { -+ if (k[i]->dk_op.dy_hop == h_op) { -+ found = k[i]; -+ break; -+ } -+ } else { -+ k[i] = key; -+ break; -+ } -+ spin_unlock(&br->br_dykey_lock); -+ BUG_ON(i == AuBrDynOp); /* expand the array */ -+ } -+ -+ return found; -+} -+ -+/* kref_get() if @key is already added */ -+static struct au_dykey *dy_gadd(struct hlist_bl_head *hbl, struct au_dykey *key) -+{ -+ struct au_dykey *tmp, *found; -+ struct hlist_bl_node *pos; -+ const void *h_op = key->dk_op.dy_hop; -+ -+ found = NULL; -+ hlist_bl_lock(hbl); -+ hlist_bl_for_each_entry(tmp, pos, hbl, dk_hnode) -+ if (tmp->dk_op.dy_hop == h_op) { -+ if (kref_get_unless_zero(&tmp->dk_kref)) -+ found = tmp; -+ break; -+ } -+ if (!found) -+ hlist_bl_add_head(&key->dk_hnode, hbl); -+ hlist_bl_unlock(hbl); -+ -+ if (!found) -+ DyPrSym(key); -+ return found; -+} -+ -+static void dy_free_rcu(struct rcu_head *rcu) -+{ -+ struct au_dykey *key; -+ -+ key = container_of(rcu, struct au_dykey, dk_rcu); -+ DyPrSym(key); -+ kfree(key); -+} -+ -+static void dy_free(struct kref *kref) -+{ -+ struct au_dykey *key; -+ struct hlist_bl_head *hbl; -+ -+ key = container_of(kref, struct au_dykey, dk_kref); -+ hbl = dynop + key->dk_op.dy_type; -+ au_hbl_del(&key->dk_hnode, hbl); -+ call_rcu(&key->dk_rcu, dy_free_rcu); -+} -+ -+void au_dy_put(struct au_dykey *key) -+{ -+ kref_put(&key->dk_kref, dy_free); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+#define DyDbgSize(cnt, op) AuDebugOn(cnt != sizeof(op)/sizeof(void *)) -+ -+#ifdef CONFIG_AUFS_DEBUG -+#define DyDbgDeclare(cnt) unsigned int cnt = 0 -+#define DyDbgInc(cnt) do { cnt++; } while (0) -+#else -+#define DyDbgDeclare(cnt) do {} while (0) -+#define DyDbgInc(cnt) do {} while (0) -+#endif -+ -+#define DySet(func, dst, src, h_op, h_sb) do { \ -+ DyDbgInc(cnt); \ -+ if (h_op->func) { \ -+ if (src.func) \ -+ dst.func = src.func; \ -+ else \ -+ AuDbg("%s %s\n", au_sbtype(h_sb), #func); \ -+ } \ -+} while (0) -+ -+#define DySetForce(func, dst, src) do { \ -+ AuDebugOn(!src.func); \ -+ DyDbgInc(cnt); \ -+ dst.func = src.func; \ -+} while (0) -+ -+#define DySetAop(func) \ -+ DySet(func, dyaop->da_op, aufs_aop, h_aop, h_sb) -+#define DySetAopForce(func) \ -+ DySetForce(func, dyaop->da_op, aufs_aop) -+ -+static void dy_aop(struct au_dykey *key, const void *h_op, -+ struct super_block *h_sb __maybe_unused) -+{ -+ struct au_dyaop *dyaop = (void *)key; -+ const struct address_space_operations *h_aop = h_op; -+ DyDbgDeclare(cnt); -+ -+ AuDbg("%s\n", au_sbtype(h_sb)); -+ -+ DySetAop(writepage); -+ DySetAopForce(readpage); /* force */ -+ DySetAop(writepages); -+ DySetAop(set_page_dirty); -+ DySetAop(readpages); -+ DySetAop(write_begin); -+ DySetAop(write_end); -+ DySetAop(bmap); -+ DySetAop(invalidatepage); -+ DySetAop(releasepage); -+ DySetAop(freepage); -+ /* this one will be changed according to an aufs mount option */ -+ DySetAop(direct_IO); -+ DySetAop(migratepage); -+ DySetAop(isolate_page); -+ DySetAop(putback_page); -+ DySetAop(launder_page); -+ DySetAop(is_partially_uptodate); -+ DySetAop(is_dirty_writeback); -+ DySetAop(error_remove_page); -+ DySetAop(swap_activate); -+ DySetAop(swap_deactivate); -+ -+ DyDbgSize(cnt, *h_aop); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static void dy_bug(struct kref *kref) -+{ -+ BUG(); -+} -+ -+static struct au_dykey *dy_get(struct au_dynop *op, struct au_branch *br) -+{ -+ struct au_dykey *key, *old; -+ struct hlist_bl_head *hbl; -+ struct op { -+ unsigned int sz; -+ void (*set)(struct au_dykey *key, const void *h_op, -+ struct super_block *h_sb __maybe_unused); -+ }; -+ static const struct op a[] = { -+ [AuDy_AOP] = { -+ .sz = sizeof(struct au_dyaop), -+ .set = dy_aop -+ } -+ }; -+ const struct op *p; -+ -+ hbl = dynop + op->dy_type; -+ key = dy_gfind_get(hbl, op->dy_hop); -+ if (key) -+ goto out_add; /* success */ -+ -+ p = a + op->dy_type; -+ key = kzalloc(p->sz, GFP_NOFS); -+ if (unlikely(!key)) { -+ key = ERR_PTR(-ENOMEM); -+ goto out; -+ } -+ -+ key->dk_op.dy_hop = op->dy_hop; -+ kref_init(&key->dk_kref); -+ p->set(key, op->dy_hop, au_br_sb(br)); -+ old = dy_gadd(hbl, key); -+ if (old) { -+ au_kfree_rcu(key); -+ key = old; -+ } -+ -+out_add: -+ old = dy_bradd(br, key); -+ if (old) -+ /* its ref-count should never be zero here */ -+ kref_put(&key->dk_kref, dy_bug); -+out: -+ return key; -+} -+ -+/* ---------------------------------------------------------------------- */ -+/* -+ * Aufs prohibits O_DIRECT by default even if the branch supports it. -+ * This behaviour is necessary to return an error from open(O_DIRECT) instead -+ * of the succeeding I/O. The dio mount option enables O_DIRECT and makes -+ * open(O_DIRECT) always succeed, but the succeeding I/O may return an error. -+ * See the aufs manual in detail. -+ */ -+static void dy_adx(struct au_dyaop *dyaop, int do_dx) -+{ -+ if (!do_dx) -+ dyaop->da_op.direct_IO = NULL; -+ else -+ dyaop->da_op.direct_IO = aufs_aop.direct_IO; -+} -+ -+static struct au_dyaop *dy_aget(struct au_branch *br, -+ const struct address_space_operations *h_aop, -+ int do_dx) -+{ -+ struct au_dyaop *dyaop; -+ struct au_dynop op; -+ -+ op.dy_type = AuDy_AOP; -+ op.dy_haop = h_aop; -+ dyaop = (void *)dy_get(&op, br); -+ if (IS_ERR(dyaop)) -+ goto out; -+ dy_adx(dyaop, do_dx); -+ -+out: -+ return dyaop; -+} -+ -+int au_dy_iaop(struct inode *inode, aufs_bindex_t bindex, -+ struct inode *h_inode) -+{ -+ int err, do_dx; -+ struct super_block *sb; -+ struct au_branch *br; -+ struct au_dyaop *dyaop; -+ -+ AuDebugOn(!S_ISREG(h_inode->i_mode)); -+ IiMustWriteLock(inode); -+ -+ sb = inode->i_sb; -+ br = au_sbr(sb, bindex); -+ do_dx = !!au_opt_test(au_mntflags(sb), DIO); -+ dyaop = dy_aget(br, h_inode->i_mapping->a_ops, do_dx); -+ err = PTR_ERR(dyaop); -+ if (IS_ERR(dyaop)) -+ /* unnecessary to call dy_fput() */ -+ goto out; -+ -+ err = 0; -+ inode->i_mapping->a_ops = &dyaop->da_op; -+ -+out: -+ return err; -+} -+ -+/* -+ * Is it safe to replace a_ops during the inode/file is in operation? -+ * Yes, I hope so. -+ */ -+int au_dy_irefresh(struct inode *inode) -+{ -+ int err; -+ aufs_bindex_t btop; -+ struct inode *h_inode; -+ -+ err = 0; -+ if (S_ISREG(inode->i_mode)) { -+ btop = au_ibtop(inode); -+ h_inode = au_h_iptr(inode, btop); -+ err = au_dy_iaop(inode, btop, h_inode); -+ } -+ return err; -+} -+ -+void au_dy_arefresh(int do_dx) -+{ -+ struct hlist_bl_head *hbl; -+ struct hlist_bl_node *pos; -+ struct au_dykey *key; -+ -+ hbl = dynop + AuDy_AOP; -+ hlist_bl_lock(hbl); -+ hlist_bl_for_each_entry(key, pos, hbl, dk_hnode) -+ dy_adx((void *)key, do_dx); -+ hlist_bl_unlock(hbl); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+void __init au_dy_init(void) -+{ -+ int i; -+ -+ for (i = 0; i < AuDyLast; i++) -+ INIT_HLIST_BL_HEAD(dynop + i); -+} -+ -+void au_dy_fin(void) -+{ -+ int i; -+ -+ for (i = 0; i < AuDyLast; i++) -+ WARN_ON(!hlist_bl_empty(dynop + i)); -+} -diff -Nurp linux-5.6.3/fs/aufs/dynop.h linux-5.6.3-aufs/fs/aufs/dynop.h ---- linux-5.6.3/fs/aufs/dynop.h 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/dynop.h 2020-04-10 12:40:52.190049409 +0300 -@@ -0,0 +1,64 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2010-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * dynamically customizable operations (for regular files only) -+ */ -+ -+#ifndef __AUFS_DYNOP_H__ -+#define __AUFS_DYNOP_H__ -+ -+#ifdef __KERNEL__ -+ -+#include -+#include -+ -+enum {AuDy_AOP, AuDyLast}; -+ -+struct au_dynop { -+ int dy_type; -+ union { -+ const void *dy_hop; -+ const struct address_space_operations *dy_haop; -+ }; -+}; -+ -+struct au_dykey { -+ union { -+ struct hlist_bl_node dk_hnode; -+ struct rcu_head dk_rcu; -+ }; -+ struct au_dynop dk_op; -+ -+ /* -+ * during I am in the branch local array, kref is gotten. when the -+ * branch is removed, kref is put. -+ */ -+ struct kref dk_kref; -+}; -+ -+/* stop unioning since their sizes are very different from each other */ -+struct au_dyaop { -+ struct au_dykey da_key; -+ struct address_space_operations da_op; /* not const */ -+}; -+/* make sure that 'struct au_dykey *' can be any type */ -+static_assert(!offsetof(struct au_dyaop, da_key)); -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* dynop.c */ -+struct au_branch; -+void au_dy_put(struct au_dykey *key); -+int au_dy_iaop(struct inode *inode, aufs_bindex_t bindex, -+ struct inode *h_inode); -+int au_dy_irefresh(struct inode *inode); -+void au_dy_arefresh(int do_dio); -+ -+void __init au_dy_init(void); -+void au_dy_fin(void); -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_DYNOP_H__ */ -diff -Nurp linux-5.6.3/fs/aufs/export.c linux-5.6.3-aufs/fs/aufs/export.c ---- linux-5.6.3/fs/aufs/export.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/export.c 2020-04-10 12:40:52.190049409 +0300 -@@ -0,0 +1,825 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * export via nfs -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include "aufs.h" -+ -+union conv { -+#ifdef CONFIG_AUFS_INO_T_64 -+ __u32 a[2]; -+#else -+ __u32 a[1]; -+#endif -+ ino_t ino; -+}; -+ -+static ino_t decode_ino(__u32 *a) -+{ -+ union conv u; -+ -+ BUILD_BUG_ON(sizeof(u.ino) != sizeof(u.a)); -+ u.a[0] = a[0]; -+#ifdef CONFIG_AUFS_INO_T_64 -+ u.a[1] = a[1]; -+#endif -+ return u.ino; -+} -+ -+static void encode_ino(__u32 *a, ino_t ino) -+{ -+ union conv u; -+ -+ u.ino = ino; -+ a[0] = u.a[0]; -+#ifdef CONFIG_AUFS_INO_T_64 -+ a[1] = u.a[1]; -+#endif -+} -+ -+/* NFS file handle */ -+enum { -+ Fh_br_id, -+ Fh_sigen, -+#ifdef CONFIG_AUFS_INO_T_64 -+ /* support 64bit inode number */ -+ Fh_ino1, -+ Fh_ino2, -+ Fh_dir_ino1, -+ Fh_dir_ino2, -+#else -+ Fh_ino1, -+ Fh_dir_ino1, -+#endif -+ Fh_igen, -+ Fh_h_type, -+ Fh_tail, -+ -+ Fh_ino = Fh_ino1, -+ Fh_dir_ino = Fh_dir_ino1 -+}; -+ -+static int au_test_anon(struct dentry *dentry) -+{ -+ /* note: read d_flags without d_lock */ -+ return !!(dentry->d_flags & DCACHE_DISCONNECTED); -+} -+ -+int au_test_nfsd(void) -+{ -+ int ret; -+ struct task_struct *tsk = current; -+ char comm[sizeof(tsk->comm)]; -+ -+ ret = 0; -+ if (tsk->flags & PF_KTHREAD) { -+ get_task_comm(comm, tsk); -+ ret = !strcmp(comm, "nfsd"); -+ } -+ -+ return ret; -+} -+ -+/* ---------------------------------------------------------------------- */ -+/* inode generation external table */ -+ -+void au_xigen_inc(struct inode *inode) -+{ -+ loff_t pos; -+ ssize_t sz; -+ __u32 igen; -+ struct super_block *sb; -+ struct au_sbinfo *sbinfo; -+ -+ sb = inode->i_sb; -+ AuDebugOn(!au_opt_test(au_mntflags(sb), XINO)); -+ -+ sbinfo = au_sbi(sb); -+ pos = inode->i_ino; -+ pos *= sizeof(igen); -+ igen = inode->i_generation + 1; -+ sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xigen, &igen, -+ sizeof(igen), &pos); -+ if (sz == sizeof(igen)) -+ return; /* success */ -+ -+ if (unlikely(sz >= 0)) -+ AuIOErr("xigen error (%zd)\n", sz); -+} -+ -+int au_xigen_new(struct inode *inode) -+{ -+ int err; -+ loff_t pos; -+ ssize_t sz; -+ struct super_block *sb; -+ struct au_sbinfo *sbinfo; -+ struct file *file; -+ -+ err = 0; -+ /* todo: dirty, at mount time */ -+ if (inode->i_ino == AUFS_ROOT_INO) -+ goto out; -+ sb = inode->i_sb; -+ SiMustAnyLock(sb); -+ if (unlikely(!au_opt_test(au_mntflags(sb), XINO))) -+ goto out; -+ -+ err = -EFBIG; -+ pos = inode->i_ino; -+ if (unlikely(au_loff_max / sizeof(inode->i_generation) - 1 < pos)) { -+ AuIOErr1("too large i%lld\n", pos); -+ goto out; -+ } -+ pos *= sizeof(inode->i_generation); -+ -+ err = 0; -+ sbinfo = au_sbi(sb); -+ file = sbinfo->si_xigen; -+ BUG_ON(!file); -+ -+ if (vfsub_f_size_read(file) -+ < pos + sizeof(inode->i_generation)) { -+ inode->i_generation = atomic_inc_return(&sbinfo->si_xigen_next); -+ sz = xino_fwrite(sbinfo->si_xwrite, file, &inode->i_generation, -+ sizeof(inode->i_generation), &pos); -+ } else -+ sz = xino_fread(sbinfo->si_xread, file, &inode->i_generation, -+ sizeof(inode->i_generation), &pos); -+ if (sz == sizeof(inode->i_generation)) -+ goto out; /* success */ -+ -+ err = sz; -+ if (unlikely(sz >= 0)) { -+ err = -EIO; -+ AuIOErr("xigen error (%zd)\n", sz); -+ } -+ -+out: -+ return err; -+} -+ -+int au_xigen_set(struct super_block *sb, struct path *path) -+{ -+ int err; -+ struct au_sbinfo *sbinfo; -+ struct file *file; -+ -+ SiMustWriteLock(sb); -+ -+ sbinfo = au_sbi(sb); -+ file = au_xino_create2(sb, path, sbinfo->si_xigen); -+ err = PTR_ERR(file); -+ if (IS_ERR(file)) -+ goto out; -+ err = 0; -+ if (sbinfo->si_xigen) -+ fput(sbinfo->si_xigen); -+ sbinfo->si_xigen = file; -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+void au_xigen_clr(struct super_block *sb) -+{ -+ struct au_sbinfo *sbinfo; -+ -+ SiMustWriteLock(sb); -+ -+ sbinfo = au_sbi(sb); -+ if (sbinfo->si_xigen) { -+ fput(sbinfo->si_xigen); -+ sbinfo->si_xigen = NULL; -+ } -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static struct dentry *decode_by_ino(struct super_block *sb, ino_t ino, -+ ino_t dir_ino) -+{ -+ struct dentry *dentry, *d; -+ struct inode *inode; -+ unsigned int sigen; -+ -+ dentry = NULL; -+ inode = ilookup(sb, ino); -+ if (!inode) -+ goto out; -+ -+ dentry = ERR_PTR(-ESTALE); -+ sigen = au_sigen(sb); -+ if (unlikely(au_is_bad_inode(inode) -+ || IS_DEADDIR(inode) -+ || sigen != au_iigen(inode, NULL))) -+ goto out_iput; -+ -+ dentry = NULL; -+ if (!dir_ino || S_ISDIR(inode->i_mode)) -+ dentry = d_find_alias(inode); -+ else { -+ spin_lock(&inode->i_lock); -+ hlist_for_each_entry(d, &inode->i_dentry, d_u.d_alias) { -+ spin_lock(&d->d_lock); -+ if (!au_test_anon(d) -+ && d_inode(d->d_parent)->i_ino == dir_ino) { -+ dentry = dget_dlock(d); -+ spin_unlock(&d->d_lock); -+ break; -+ } -+ spin_unlock(&d->d_lock); -+ } -+ spin_unlock(&inode->i_lock); -+ } -+ if (unlikely(dentry && au_digen_test(dentry, sigen))) { -+ /* need to refresh */ -+ dput(dentry); -+ dentry = NULL; -+ } -+ -+out_iput: -+ iput(inode); -+out: -+ AuTraceErrPtr(dentry); -+ return dentry; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* todo: dirty? */ -+/* if exportfs_decode_fh() passed vfsmount*, we could be happy */ -+ -+struct au_compare_mnt_args { -+ /* input */ -+ struct super_block *sb; -+ -+ /* output */ -+ struct vfsmount *mnt; -+}; -+ -+static int au_compare_mnt(struct vfsmount *mnt, void *arg) -+{ -+ struct au_compare_mnt_args *a = arg; -+ -+ if (mnt->mnt_sb != a->sb) -+ return 0; -+ a->mnt = mntget(mnt); -+ return 1; -+} -+ -+static struct vfsmount *au_mnt_get(struct super_block *sb) -+{ -+ int err; -+ struct path root; -+ struct au_compare_mnt_args args = { -+ .sb = sb -+ }; -+ -+ get_fs_root(current->fs, &root); -+ rcu_read_lock(); -+ err = iterate_mounts(au_compare_mnt, &args, root.mnt); -+ rcu_read_unlock(); -+ path_put(&root); -+ AuDebugOn(!err); -+ AuDebugOn(!args.mnt); -+ return args.mnt; -+} -+ -+struct au_nfsd_si_lock { -+ unsigned int sigen; -+ aufs_bindex_t bindex, br_id; -+ unsigned char force_lock; -+}; -+ -+static int si_nfsd_read_lock(struct super_block *sb, -+ struct au_nfsd_si_lock *nsi_lock) -+{ -+ int err; -+ aufs_bindex_t bindex; -+ -+ si_read_lock(sb, AuLock_FLUSH); -+ -+ /* branch id may be wrapped around */ -+ err = 0; -+ bindex = au_br_index(sb, nsi_lock->br_id); -+ if (bindex >= 0 && nsi_lock->sigen + AUFS_BRANCH_MAX > au_sigen(sb)) -+ goto out; /* success */ -+ -+ err = -ESTALE; -+ bindex = -1; -+ if (!nsi_lock->force_lock) -+ si_read_unlock(sb); -+ -+out: -+ nsi_lock->bindex = bindex; -+ return err; -+} -+ -+struct find_name_by_ino { -+ struct dir_context ctx; -+ int called, found; -+ ino_t ino; -+ char *name; -+ int namelen; -+}; -+ -+static int -+find_name_by_ino(struct dir_context *ctx, const char *name, int namelen, -+ loff_t offset, u64 ino, unsigned int d_type) -+{ -+ struct find_name_by_ino *a = container_of(ctx, struct find_name_by_ino, -+ ctx); -+ -+ a->called++; -+ if (a->ino != ino) -+ return 0; -+ -+ memcpy(a->name, name, namelen); -+ a->namelen = namelen; -+ a->found = 1; -+ return 1; -+} -+ -+static struct dentry *au_lkup_by_ino(struct path *path, ino_t ino, -+ struct au_nfsd_si_lock *nsi_lock) -+{ -+ struct dentry *dentry, *parent; -+ struct file *file; -+ struct inode *dir; -+ struct find_name_by_ino arg = { -+ .ctx = { -+ .actor = find_name_by_ino -+ } -+ }; -+ int err; -+ -+ parent = path->dentry; -+ if (nsi_lock) -+ si_read_unlock(parent->d_sb); -+ file = vfsub_dentry_open(path, au_dir_roflags); -+ dentry = (void *)file; -+ if (IS_ERR(file)) -+ goto out; -+ -+ dentry = ERR_PTR(-ENOMEM); -+ arg.name = (void *)__get_free_page(GFP_NOFS); -+ if (unlikely(!arg.name)) -+ goto out_file; -+ arg.ino = ino; -+ arg.found = 0; -+ do { -+ arg.called = 0; -+ /* smp_mb(); */ -+ err = vfsub_iterate_dir(file, &arg.ctx); -+ } while (!err && !arg.found && arg.called); -+ dentry = ERR_PTR(err); -+ if (unlikely(err)) -+ goto out_name; -+ /* instead of ENOENT */ -+ dentry = ERR_PTR(-ESTALE); -+ if (!arg.found) -+ goto out_name; -+ -+ /* do not call vfsub_lkup_one() */ -+ dir = d_inode(parent); -+ dentry = vfsub_lookup_one_len_unlocked(arg.name, parent, arg.namelen); -+ AuTraceErrPtr(dentry); -+ if (IS_ERR(dentry)) -+ goto out_name; -+ AuDebugOn(au_test_anon(dentry)); -+ if (unlikely(d_really_is_negative(dentry))) { -+ dput(dentry); -+ dentry = ERR_PTR(-ENOENT); -+ } -+ -+out_name: -+ free_page((unsigned long)arg.name); -+out_file: -+ fput(file); -+out: -+ if (unlikely(nsi_lock -+ && si_nfsd_read_lock(parent->d_sb, nsi_lock) < 0)) -+ if (!IS_ERR(dentry)) { -+ dput(dentry); -+ dentry = ERR_PTR(-ESTALE); -+ } -+ AuTraceErrPtr(dentry); -+ return dentry; -+} -+ -+static struct dentry *decode_by_dir_ino(struct super_block *sb, ino_t ino, -+ ino_t dir_ino, -+ struct au_nfsd_si_lock *nsi_lock) -+{ -+ struct dentry *dentry; -+ struct path path; -+ -+ if (dir_ino != AUFS_ROOT_INO) { -+ path.dentry = decode_by_ino(sb, dir_ino, 0); -+ dentry = path.dentry; -+ if (!path.dentry || IS_ERR(path.dentry)) -+ goto out; -+ AuDebugOn(au_test_anon(path.dentry)); -+ } else -+ path.dentry = dget(sb->s_root); -+ -+ path.mnt = au_mnt_get(sb); -+ dentry = au_lkup_by_ino(&path, ino, nsi_lock); -+ path_put(&path); -+ -+out: -+ AuTraceErrPtr(dentry); -+ return dentry; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int h_acceptable(void *expv, struct dentry *dentry) -+{ -+ return 1; -+} -+ -+static char *au_build_path(struct dentry *h_parent, struct path *h_rootpath, -+ char *buf, int len, struct super_block *sb) -+{ -+ char *p; -+ int n; -+ struct path path; -+ -+ p = d_path(h_rootpath, buf, len); -+ if (IS_ERR(p)) -+ goto out; -+ n = strlen(p); -+ -+ path.mnt = h_rootpath->mnt; -+ path.dentry = h_parent; -+ p = d_path(&path, buf, len); -+ if (IS_ERR(p)) -+ goto out; -+ if (n != 1) -+ p += n; -+ -+ path.mnt = au_mnt_get(sb); -+ path.dentry = sb->s_root; -+ p = d_path(&path, buf, len - strlen(p)); -+ mntput(path.mnt); -+ if (IS_ERR(p)) -+ goto out; -+ if (n != 1) -+ p[strlen(p)] = '/'; -+ -+out: -+ AuTraceErrPtr(p); -+ return p; -+} -+ -+static -+struct dentry *decode_by_path(struct super_block *sb, ino_t ino, __u32 *fh, -+ int fh_len, struct au_nfsd_si_lock *nsi_lock) -+{ -+ struct dentry *dentry, *h_parent, *root; -+ struct super_block *h_sb; -+ char *pathname, *p; -+ struct vfsmount *h_mnt; -+ struct au_branch *br; -+ int err; -+ struct path path; -+ -+ br = au_sbr(sb, nsi_lock->bindex); -+ h_mnt = au_br_mnt(br); -+ h_sb = h_mnt->mnt_sb; -+ /* todo: call lower fh_to_dentry()? fh_to_parent()? */ -+ lockdep_off(); -+ h_parent = exportfs_decode_fh(h_mnt, (void *)(fh + Fh_tail), -+ fh_len - Fh_tail, fh[Fh_h_type], -+ h_acceptable, /*context*/NULL); -+ lockdep_on(); -+ dentry = h_parent; -+ if (unlikely(!h_parent || IS_ERR(h_parent))) { -+ AuWarn1("%s decode_fh failed, %ld\n", -+ au_sbtype(h_sb), PTR_ERR(h_parent)); -+ goto out; -+ } -+ dentry = NULL; -+ if (unlikely(au_test_anon(h_parent))) { -+ AuWarn1("%s decode_fh returned a disconnected dentry\n", -+ au_sbtype(h_sb)); -+ goto out_h_parent; -+ } -+ -+ dentry = ERR_PTR(-ENOMEM); -+ pathname = (void *)__get_free_page(GFP_NOFS); -+ if (unlikely(!pathname)) -+ goto out_h_parent; -+ -+ root = sb->s_root; -+ path.mnt = h_mnt; -+ di_read_lock_parent(root, !AuLock_IR); -+ path.dentry = au_h_dptr(root, nsi_lock->bindex); -+ di_read_unlock(root, !AuLock_IR); -+ p = au_build_path(h_parent, &path, pathname, PAGE_SIZE, sb); -+ dentry = (void *)p; -+ if (IS_ERR(p)) -+ goto out_pathname; -+ -+ si_read_unlock(sb); -+ err = vfsub_kern_path(p, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path); -+ dentry = ERR_PTR(err); -+ if (unlikely(err)) -+ goto out_relock; -+ -+ dentry = ERR_PTR(-ENOENT); -+ AuDebugOn(au_test_anon(path.dentry)); -+ if (unlikely(d_really_is_negative(path.dentry))) -+ goto out_path; -+ -+ if (ino != d_inode(path.dentry)->i_ino) -+ dentry = au_lkup_by_ino(&path, ino, /*nsi_lock*/NULL); -+ else -+ dentry = dget(path.dentry); -+ -+out_path: -+ path_put(&path); -+out_relock: -+ if (unlikely(si_nfsd_read_lock(sb, nsi_lock) < 0)) -+ if (!IS_ERR(dentry)) { -+ dput(dentry); -+ dentry = ERR_PTR(-ESTALE); -+ } -+out_pathname: -+ free_page((unsigned long)pathname); -+out_h_parent: -+ dput(h_parent); -+out: -+ AuTraceErrPtr(dentry); -+ return dentry; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static struct dentry * -+aufs_fh_to_dentry(struct super_block *sb, struct fid *fid, int fh_len, -+ int fh_type) -+{ -+ struct dentry *dentry; -+ __u32 *fh = fid->raw; -+ struct au_branch *br; -+ ino_t ino, dir_ino; -+ struct au_nfsd_si_lock nsi_lock = { -+ .force_lock = 0 -+ }; -+ -+ dentry = ERR_PTR(-ESTALE); -+ /* it should never happen, but the file handle is unreliable */ -+ if (unlikely(fh_len < Fh_tail)) -+ goto out; -+ nsi_lock.sigen = fh[Fh_sigen]; -+ nsi_lock.br_id = fh[Fh_br_id]; -+ -+ /* branch id may be wrapped around */ -+ br = NULL; -+ if (unlikely(si_nfsd_read_lock(sb, &nsi_lock))) -+ goto out; -+ nsi_lock.force_lock = 1; -+ -+ /* is this inode still cached? */ -+ ino = decode_ino(fh + Fh_ino); -+ /* it should never happen */ -+ if (unlikely(ino == AUFS_ROOT_INO)) -+ goto out_unlock; -+ -+ dir_ino = decode_ino(fh + Fh_dir_ino); -+ dentry = decode_by_ino(sb, ino, dir_ino); -+ if (IS_ERR(dentry)) -+ goto out_unlock; -+ if (dentry) -+ goto accept; -+ -+ /* is the parent dir cached? */ -+ br = au_sbr(sb, nsi_lock.bindex); -+ au_lcnt_inc(&br->br_nfiles); -+ dentry = decode_by_dir_ino(sb, ino, dir_ino, &nsi_lock); -+ if (IS_ERR(dentry)) -+ goto out_unlock; -+ if (dentry) -+ goto accept; -+ -+ /* lookup path */ -+ dentry = decode_by_path(sb, ino, fh, fh_len, &nsi_lock); -+ if (IS_ERR(dentry)) -+ goto out_unlock; -+ if (unlikely(!dentry)) -+ /* todo?: make it ESTALE */ -+ goto out_unlock; -+ -+accept: -+ if (!au_digen_test(dentry, au_sigen(sb)) -+ && d_inode(dentry)->i_generation == fh[Fh_igen]) -+ goto out_unlock; /* success */ -+ -+ dput(dentry); -+ dentry = ERR_PTR(-ESTALE); -+out_unlock: -+ if (br) -+ au_lcnt_dec(&br->br_nfiles); -+ si_read_unlock(sb); -+out: -+ AuTraceErrPtr(dentry); -+ return dentry; -+} -+ -+#if 0 /* reserved for future use */ -+/* support subtreecheck option */ -+static struct dentry *aufs_fh_to_parent(struct super_block *sb, struct fid *fid, -+ int fh_len, int fh_type) -+{ -+ struct dentry *parent; -+ __u32 *fh = fid->raw; -+ ino_t dir_ino; -+ -+ dir_ino = decode_ino(fh + Fh_dir_ino); -+ parent = decode_by_ino(sb, dir_ino, 0); -+ if (IS_ERR(parent)) -+ goto out; -+ if (!parent) -+ parent = decode_by_path(sb, au_br_index(sb, fh[Fh_br_id]), -+ dir_ino, fh, fh_len); -+ -+out: -+ AuTraceErrPtr(parent); -+ return parent; -+} -+#endif -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int aufs_encode_fh(struct inode *inode, __u32 *fh, int *max_len, -+ struct inode *dir) -+{ -+ int err; -+ aufs_bindex_t bindex; -+ struct super_block *sb, *h_sb; -+ struct dentry *dentry, *parent, *h_parent; -+ struct inode *h_dir; -+ struct au_branch *br; -+ -+ err = -ENOSPC; -+ if (unlikely(*max_len <= Fh_tail)) { -+ AuWarn1("NFSv2 client (max_len %d)?\n", *max_len); -+ goto out; -+ } -+ -+ err = FILEID_ROOT; -+ if (inode->i_ino == AUFS_ROOT_INO) { -+ AuDebugOn(inode->i_ino != AUFS_ROOT_INO); -+ goto out; -+ } -+ -+ h_parent = NULL; -+ sb = inode->i_sb; -+ err = si_read_lock(sb, AuLock_FLUSH); -+ if (unlikely(err)) -+ goto out; -+ -+#ifdef CONFIG_AUFS_DEBUG -+ if (unlikely(!au_opt_test(au_mntflags(sb), XINO))) -+ AuWarn1("NFS-exporting requires xino\n"); -+#endif -+ err = -EIO; -+ parent = NULL; -+ ii_read_lock_child(inode); -+ bindex = au_ibtop(inode); -+ if (!dir) { -+ dentry = d_find_any_alias(inode); -+ if (unlikely(!dentry)) -+ goto out_unlock; -+ AuDebugOn(au_test_anon(dentry)); -+ parent = dget_parent(dentry); -+ dput(dentry); -+ if (unlikely(!parent)) -+ goto out_unlock; -+ if (d_really_is_positive(parent)) -+ dir = d_inode(parent); -+ } -+ -+ ii_read_lock_parent(dir); -+ h_dir = au_h_iptr(dir, bindex); -+ ii_read_unlock(dir); -+ if (unlikely(!h_dir)) -+ goto out_parent; -+ h_parent = d_find_any_alias(h_dir); -+ if (unlikely(!h_parent)) -+ goto out_hparent; -+ -+ err = -EPERM; -+ br = au_sbr(sb, bindex); -+ h_sb = au_br_sb(br); -+ if (unlikely(!h_sb->s_export_op)) { -+ AuErr1("%s branch is not exportable\n", au_sbtype(h_sb)); -+ goto out_hparent; -+ } -+ -+ fh[Fh_br_id] = br->br_id; -+ fh[Fh_sigen] = au_sigen(sb); -+ encode_ino(fh + Fh_ino, inode->i_ino); -+ encode_ino(fh + Fh_dir_ino, dir->i_ino); -+ fh[Fh_igen] = inode->i_generation; -+ -+ *max_len -= Fh_tail; -+ fh[Fh_h_type] = exportfs_encode_fh(h_parent, (void *)(fh + Fh_tail), -+ max_len, -+ /*connectable or subtreecheck*/0); -+ err = fh[Fh_h_type]; -+ *max_len += Fh_tail; -+ /* todo: macros? */ -+ if (err != FILEID_INVALID) -+ err = 99; -+ else -+ AuWarn1("%s encode_fh failed\n", au_sbtype(h_sb)); -+ -+out_hparent: -+ dput(h_parent); -+out_parent: -+ dput(parent); -+out_unlock: -+ ii_read_unlock(inode); -+ si_read_unlock(sb); -+out: -+ if (unlikely(err < 0)) -+ err = FILEID_INVALID; -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int aufs_commit_metadata(struct inode *inode) -+{ -+ int err; -+ aufs_bindex_t bindex; -+ struct super_block *sb; -+ struct inode *h_inode; -+ int (*f)(struct inode *inode); -+ -+ sb = inode->i_sb; -+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW); -+ ii_write_lock_child(inode); -+ bindex = au_ibtop(inode); -+ AuDebugOn(bindex < 0); -+ h_inode = au_h_iptr(inode, bindex); -+ -+ f = h_inode->i_sb->s_export_op->commit_metadata; -+ if (f) -+ err = f(h_inode); -+ else { -+ struct writeback_control wbc = { -+ .sync_mode = WB_SYNC_ALL, -+ .nr_to_write = 0 /* metadata only */ -+ }; -+ -+ err = sync_inode(h_inode, &wbc); -+ } -+ -+ au_cpup_attr_timesizes(inode); -+ ii_write_unlock(inode); -+ si_read_unlock(sb); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static struct export_operations aufs_export_op = { -+ .fh_to_dentry = aufs_fh_to_dentry, -+ /* .fh_to_parent = aufs_fh_to_parent, */ -+ .encode_fh = aufs_encode_fh, -+ .commit_metadata = aufs_commit_metadata -+}; -+ -+void au_export_init(struct super_block *sb) -+{ -+ struct au_sbinfo *sbinfo; -+ __u32 u; -+ -+ BUILD_BUG_ON_MSG(IS_BUILTIN(CONFIG_AUFS_FS) -+ && IS_MODULE(CONFIG_EXPORTFS), -+ AUFS_NAME ": unsupported configuration " -+ "CONFIG_EXPORTFS=m and CONFIG_AUFS_FS=y"); -+ -+ sb->s_export_op = &aufs_export_op; -+ sbinfo = au_sbi(sb); -+ sbinfo->si_xigen = NULL; -+ get_random_bytes(&u, sizeof(u)); -+ BUILD_BUG_ON(sizeof(u) != sizeof(int)); -+ atomic_set(&sbinfo->si_xigen_next, u); -+} -diff -Nurp linux-5.6.3/fs/aufs/fhsm.c linux-5.6.3-aufs/fs/aufs/fhsm.c ---- linux-5.6.3/fs/aufs/fhsm.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/fhsm.c 2020-04-10 12:40:52.190049409 +0300 -@@ -0,0 +1,413 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2011-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * File-based Hierarchy Storage Management -+ */ -+ -+#include -+#include -+#include -+#include -+#include "aufs.h" -+ -+static aufs_bindex_t au_fhsm_bottom(struct super_block *sb) -+{ -+ struct au_sbinfo *sbinfo; -+ struct au_fhsm *fhsm; -+ -+ SiMustAnyLock(sb); -+ -+ sbinfo = au_sbi(sb); -+ fhsm = &sbinfo->si_fhsm; -+ AuDebugOn(!fhsm); -+ return fhsm->fhsm_bottom; -+} -+ -+void au_fhsm_set_bottom(struct super_block *sb, aufs_bindex_t bindex) -+{ -+ struct au_sbinfo *sbinfo; -+ struct au_fhsm *fhsm; -+ -+ SiMustWriteLock(sb); -+ -+ sbinfo = au_sbi(sb); -+ fhsm = &sbinfo->si_fhsm; -+ AuDebugOn(!fhsm); -+ fhsm->fhsm_bottom = bindex; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int au_fhsm_test_jiffy(struct au_sbinfo *sbinfo, struct au_branch *br) -+{ -+ struct au_br_fhsm *bf; -+ -+ bf = br->br_fhsm; -+ MtxMustLock(&bf->bf_lock); -+ -+ return !bf->bf_readable -+ || time_after(jiffies, -+ bf->bf_jiffy + sbinfo->si_fhsm.fhsm_expire); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static void au_fhsm_notify(struct super_block *sb, int val) -+{ -+ struct au_sbinfo *sbinfo; -+ struct au_fhsm *fhsm; -+ -+ SiMustAnyLock(sb); -+ -+ sbinfo = au_sbi(sb); -+ fhsm = &sbinfo->si_fhsm; -+ if (au_fhsm_pid(fhsm) -+ && atomic_read(&fhsm->fhsm_readable) != -1) { -+ atomic_set(&fhsm->fhsm_readable, val); -+ if (val) -+ wake_up(&fhsm->fhsm_wqh); -+ } -+} -+ -+static int au_fhsm_stfs(struct super_block *sb, aufs_bindex_t bindex, -+ struct aufs_stfs *rstfs, int do_lock, int do_notify) -+{ -+ int err; -+ struct au_branch *br; -+ struct au_br_fhsm *bf; -+ -+ br = au_sbr(sb, bindex); -+ AuDebugOn(au_br_rdonly(br)); -+ bf = br->br_fhsm; -+ AuDebugOn(!bf); -+ -+ if (do_lock) -+ mutex_lock(&bf->bf_lock); -+ else -+ MtxMustLock(&bf->bf_lock); -+ -+ /* sb->s_root for NFS is unreliable */ -+ err = au_br_stfs(br, &bf->bf_stfs); -+ if (unlikely(err)) { -+ AuErr1("FHSM failed (%d), b%d, ignored.\n", bindex, err); -+ goto out; -+ } -+ -+ bf->bf_jiffy = jiffies; -+ bf->bf_readable = 1; -+ if (do_notify) -+ au_fhsm_notify(sb, /*val*/1); -+ if (rstfs) -+ *rstfs = bf->bf_stfs; -+ -+out: -+ if (do_lock) -+ mutex_unlock(&bf->bf_lock); -+ au_fhsm_notify(sb, /*val*/1); -+ -+ return err; -+} -+ -+void au_fhsm_wrote(struct super_block *sb, aufs_bindex_t bindex, int force) -+{ -+ int err; -+ struct au_sbinfo *sbinfo; -+ struct au_fhsm *fhsm; -+ struct au_branch *br; -+ struct au_br_fhsm *bf; -+ -+ AuDbg("b%d, force %d\n", bindex, force); -+ SiMustAnyLock(sb); -+ -+ sbinfo = au_sbi(sb); -+ fhsm = &sbinfo->si_fhsm; -+ if (!au_ftest_si(sbinfo, FHSM) -+ || fhsm->fhsm_bottom == bindex) -+ return; -+ -+ br = au_sbr(sb, bindex); -+ bf = br->br_fhsm; -+ AuDebugOn(!bf); -+ mutex_lock(&bf->bf_lock); -+ if (force -+ || au_fhsm_pid(fhsm) -+ || au_fhsm_test_jiffy(sbinfo, br)) -+ err = au_fhsm_stfs(sb, bindex, /*rstfs*/NULL, /*do_lock*/0, -+ /*do_notify*/1); -+ mutex_unlock(&bf->bf_lock); -+} -+ -+void au_fhsm_wrote_all(struct super_block *sb, int force) -+{ -+ aufs_bindex_t bindex, bbot; -+ struct au_branch *br; -+ -+ /* exclude the bottom */ -+ bbot = au_fhsm_bottom(sb); -+ for (bindex = 0; bindex < bbot; bindex++) { -+ br = au_sbr(sb, bindex); -+ if (au_br_fhsm(br->br_perm)) -+ au_fhsm_wrote(sb, bindex, force); -+ } -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static __poll_t au_fhsm_poll(struct file *file, struct poll_table_struct *wait) -+{ -+ __poll_t mask; -+ struct au_sbinfo *sbinfo; -+ struct au_fhsm *fhsm; -+ -+ mask = 0; -+ sbinfo = file->private_data; -+ fhsm = &sbinfo->si_fhsm; -+ poll_wait(file, &fhsm->fhsm_wqh, wait); -+ if (atomic_read(&fhsm->fhsm_readable)) -+ mask = EPOLLIN /* | EPOLLRDNORM */; -+ -+ if (!mask) -+ AuDbg("mask 0x%x\n", mask); -+ return mask; -+} -+ -+static int au_fhsm_do_read_one(struct aufs_stbr __user *stbr, -+ struct aufs_stfs *stfs, __s16 brid) -+{ -+ int err; -+ -+ err = copy_to_user(&stbr->stfs, stfs, sizeof(*stfs)); -+ if (!err) -+ err = __put_user(brid, &stbr->brid); -+ if (unlikely(err)) -+ err = -EFAULT; -+ -+ return err; -+} -+ -+static ssize_t au_fhsm_do_read(struct super_block *sb, -+ struct aufs_stbr __user *stbr, size_t count) -+{ -+ ssize_t err; -+ int nstbr; -+ aufs_bindex_t bindex, bbot; -+ struct au_branch *br; -+ struct au_br_fhsm *bf; -+ -+ /* except the bottom branch */ -+ err = 0; -+ nstbr = 0; -+ bbot = au_fhsm_bottom(sb); -+ for (bindex = 0; !err && bindex < bbot; bindex++) { -+ br = au_sbr(sb, bindex); -+ if (!au_br_fhsm(br->br_perm)) -+ continue; -+ -+ bf = br->br_fhsm; -+ mutex_lock(&bf->bf_lock); -+ if (bf->bf_readable) { -+ err = -EFAULT; -+ if (count >= sizeof(*stbr)) -+ err = au_fhsm_do_read_one(stbr++, &bf->bf_stfs, -+ br->br_id); -+ if (!err) { -+ bf->bf_readable = 0; -+ count -= sizeof(*stbr); -+ nstbr++; -+ } -+ } -+ mutex_unlock(&bf->bf_lock); -+ } -+ if (!err) -+ err = sizeof(*stbr) * nstbr; -+ -+ return err; -+} -+ -+static ssize_t au_fhsm_read(struct file *file, char __user *buf, size_t count, -+ loff_t *pos) -+{ -+ ssize_t err; -+ int readable; -+ aufs_bindex_t nfhsm, bindex, bbot; -+ struct au_sbinfo *sbinfo; -+ struct au_fhsm *fhsm; -+ struct au_branch *br; -+ struct super_block *sb; -+ -+ err = 0; -+ sbinfo = file->private_data; -+ fhsm = &sbinfo->si_fhsm; -+need_data: -+ spin_lock_irq(&fhsm->fhsm_wqh.lock); -+ if (!atomic_read(&fhsm->fhsm_readable)) { -+ if (vfsub_file_flags(file) & O_NONBLOCK) -+ err = -EAGAIN; -+ else -+ err = wait_event_interruptible_locked_irq -+ (fhsm->fhsm_wqh, -+ atomic_read(&fhsm->fhsm_readable)); -+ } -+ spin_unlock_irq(&fhsm->fhsm_wqh.lock); -+ if (unlikely(err)) -+ goto out; -+ -+ /* sb may already be dead */ -+ au_rw_read_lock(&sbinfo->si_rwsem); -+ readable = atomic_read(&fhsm->fhsm_readable); -+ if (readable > 0) { -+ sb = sbinfo->si_sb; -+ AuDebugOn(!sb); -+ /* exclude the bottom branch */ -+ nfhsm = 0; -+ bbot = au_fhsm_bottom(sb); -+ for (bindex = 0; bindex < bbot; bindex++) { -+ br = au_sbr(sb, bindex); -+ if (au_br_fhsm(br->br_perm)) -+ nfhsm++; -+ } -+ err = -EMSGSIZE; -+ if (nfhsm * sizeof(struct aufs_stbr) <= count) { -+ atomic_set(&fhsm->fhsm_readable, 0); -+ err = au_fhsm_do_read(sbinfo->si_sb, (void __user *)buf, -+ count); -+ } -+ } -+ au_rw_read_unlock(&sbinfo->si_rwsem); -+ if (!readable) -+ goto need_data; -+ -+out: -+ return err; -+} -+ -+static int au_fhsm_release(struct inode *inode, struct file *file) -+{ -+ struct au_sbinfo *sbinfo; -+ struct au_fhsm *fhsm; -+ -+ /* sb may already be dead */ -+ sbinfo = file->private_data; -+ fhsm = &sbinfo->si_fhsm; -+ spin_lock(&fhsm->fhsm_spin); -+ fhsm->fhsm_pid = 0; -+ spin_unlock(&fhsm->fhsm_spin); -+ kobject_put(&sbinfo->si_kobj); -+ -+ return 0; -+} -+ -+static const struct file_operations au_fhsm_fops = { -+ .owner = THIS_MODULE, -+ .llseek = noop_llseek, -+ .read = au_fhsm_read, -+ .poll = au_fhsm_poll, -+ .release = au_fhsm_release -+}; -+ -+int au_fhsm_fd(struct super_block *sb, int oflags) -+{ -+ int err, fd; -+ struct au_sbinfo *sbinfo; -+ struct au_fhsm *fhsm; -+ -+ err = -EPERM; -+ if (unlikely(!capable(CAP_SYS_ADMIN))) -+ goto out; -+ -+ err = -EINVAL; -+ if (unlikely(oflags & ~(O_CLOEXEC | O_NONBLOCK))) -+ goto out; -+ -+ err = 0; -+ sbinfo = au_sbi(sb); -+ fhsm = &sbinfo->si_fhsm; -+ spin_lock(&fhsm->fhsm_spin); -+ if (!fhsm->fhsm_pid) -+ fhsm->fhsm_pid = current->pid; -+ else -+ err = -EBUSY; -+ spin_unlock(&fhsm->fhsm_spin); -+ if (unlikely(err)) -+ goto out; -+ -+ oflags |= O_RDONLY; -+ /* oflags |= FMODE_NONOTIFY; */ -+ fd = anon_inode_getfd("[aufs_fhsm]", &au_fhsm_fops, sbinfo, oflags); -+ err = fd; -+ if (unlikely(fd < 0)) -+ goto out_pid; -+ -+ /* succeed regardless 'fhsm' status */ -+ kobject_get(&sbinfo->si_kobj); -+ si_noflush_read_lock(sb); -+ if (au_ftest_si(sbinfo, FHSM)) -+ au_fhsm_wrote_all(sb, /*force*/0); -+ si_read_unlock(sb); -+ goto out; /* success */ -+ -+out_pid: -+ spin_lock(&fhsm->fhsm_spin); -+ fhsm->fhsm_pid = 0; -+ spin_unlock(&fhsm->fhsm_spin); -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+int au_fhsm_br_alloc(struct au_branch *br) -+{ -+ int err; -+ -+ err = 0; -+ br->br_fhsm = kmalloc(sizeof(*br->br_fhsm), GFP_NOFS); -+ if (br->br_fhsm) -+ au_br_fhsm_init(br->br_fhsm); -+ else -+ err = -ENOMEM; -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+void au_fhsm_fin(struct super_block *sb) -+{ -+ au_fhsm_notify(sb, /*val*/-1); -+} -+ -+void au_fhsm_init(struct au_sbinfo *sbinfo) -+{ -+ struct au_fhsm *fhsm; -+ -+ fhsm = &sbinfo->si_fhsm; -+ spin_lock_init(&fhsm->fhsm_spin); -+ init_waitqueue_head(&fhsm->fhsm_wqh); -+ atomic_set(&fhsm->fhsm_readable, 0); -+ fhsm->fhsm_expire -+ = msecs_to_jiffies(AUFS_FHSM_CACHE_DEF_SEC * MSEC_PER_SEC); -+ fhsm->fhsm_bottom = -1; -+} -+ -+void au_fhsm_set(struct au_sbinfo *sbinfo, unsigned int sec) -+{ -+ sbinfo->si_fhsm.fhsm_expire -+ = msecs_to_jiffies(sec * MSEC_PER_SEC); -+} -+ -+void au_fhsm_show(struct seq_file *seq, struct au_sbinfo *sbinfo) -+{ -+ unsigned int u; -+ -+ if (!au_ftest_si(sbinfo, FHSM)) -+ return; -+ -+ u = jiffies_to_msecs(sbinfo->si_fhsm.fhsm_expire) / MSEC_PER_SEC; -+ if (u != AUFS_FHSM_CACHE_DEF_SEC) -+ seq_printf(seq, ",fhsm_sec=%u", u); -+} -diff -Nurp linux-5.6.3/fs/aufs/file.c linux-5.6.3-aufs/fs/aufs/file.c ---- linux-5.6.3/fs/aufs/file.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/file.c 2020-04-10 12:40:52.190049409 +0300 -@@ -0,0 +1,850 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * handling file/dir, and address_space operation -+ */ -+ -+#ifdef CONFIG_AUFS_DEBUG -+#include -+#endif -+#include -+#include "aufs.h" -+ -+/* drop flags for writing */ -+unsigned int au_file_roflags(unsigned int flags) -+{ -+ flags &= ~(O_WRONLY | O_RDWR | O_APPEND | O_CREAT | O_TRUNC); -+ flags |= O_RDONLY | O_NOATIME; -+ return flags; -+} -+ -+/* common functions to regular file and dir */ -+struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags, -+ struct file *file, int force_wr) -+{ -+ struct file *h_file; -+ struct dentry *h_dentry; -+ struct inode *h_inode; -+ struct super_block *sb; -+ struct au_branch *br; -+ struct path h_path; -+ int err; -+ -+ /* a race condition can happen between open and unlink/rmdir */ -+ h_file = ERR_PTR(-ENOENT); -+ h_dentry = au_h_dptr(dentry, bindex); -+ if (au_test_nfsd() && (!h_dentry || d_is_negative(h_dentry))) -+ goto out; -+ h_inode = d_inode(h_dentry); -+ spin_lock(&h_dentry->d_lock); -+ err = (!d_unhashed(dentry) && d_unlinked(h_dentry)) -+ /* || !d_inode(dentry)->i_nlink */ -+ ; -+ spin_unlock(&h_dentry->d_lock); -+ if (unlikely(err)) -+ goto out; -+ -+ sb = dentry->d_sb; -+ br = au_sbr(sb, bindex); -+ err = au_br_test_oflag(flags, br); -+ h_file = ERR_PTR(err); -+ if (unlikely(err)) -+ goto out; -+ -+ /* drop flags for writing */ -+ if (au_test_ro(sb, bindex, d_inode(dentry))) { -+ if (force_wr && !(flags & O_WRONLY)) -+ force_wr = 0; -+ flags = au_file_roflags(flags); -+ if (force_wr) { -+ h_file = ERR_PTR(-EROFS); -+ flags = au_file_roflags(flags); -+ if (unlikely(vfsub_native_ro(h_inode) -+ || IS_APPEND(h_inode))) -+ goto out; -+ flags &= ~O_ACCMODE; -+ flags |= O_WRONLY; -+ } -+ } -+ flags &= ~O_CREAT; -+ au_lcnt_inc(&br->br_nfiles); -+ h_path.dentry = h_dentry; -+ h_path.mnt = au_br_mnt(br); -+ h_file = vfsub_dentry_open(&h_path, flags); -+ if (IS_ERR(h_file)) -+ goto out_br; -+ -+ if (flags & __FMODE_EXEC) { -+ err = deny_write_access(h_file); -+ if (unlikely(err)) { -+ fput(h_file); -+ h_file = ERR_PTR(err); -+ goto out_br; -+ } -+ } -+ fsnotify_open(h_file); -+ goto out; /* success */ -+ -+out_br: -+ au_lcnt_dec(&br->br_nfiles); -+out: -+ return h_file; -+} -+ -+static int au_cmoo(struct dentry *dentry) -+{ -+ int err, cmoo, matched; -+ unsigned int udba; -+ struct path h_path; -+ struct au_pin pin; -+ struct au_cp_generic cpg = { -+ .dentry = dentry, -+ .bdst = -1, -+ .bsrc = -1, -+ .len = -1, -+ .pin = &pin, -+ .flags = AuCpup_DTIME | AuCpup_HOPEN -+ }; -+ struct inode *delegated; -+ struct super_block *sb; -+ struct au_sbinfo *sbinfo; -+ struct au_fhsm *fhsm; -+ pid_t pid; -+ struct au_branch *br; -+ struct dentry *parent; -+ struct au_hinode *hdir; -+ -+ DiMustWriteLock(dentry); -+ IiMustWriteLock(d_inode(dentry)); -+ -+ err = 0; -+ if (IS_ROOT(dentry)) -+ goto out; -+ cpg.bsrc = au_dbtop(dentry); -+ if (!cpg.bsrc) -+ goto out; -+ -+ sb = dentry->d_sb; -+ sbinfo = au_sbi(sb); -+ fhsm = &sbinfo->si_fhsm; -+ pid = au_fhsm_pid(fhsm); -+ rcu_read_lock(); -+ matched = (pid -+ && (current->pid == pid -+ || rcu_dereference(current->real_parent)->pid == pid)); -+ rcu_read_unlock(); -+ if (matched) -+ goto out; -+ -+ br = au_sbr(sb, cpg.bsrc); -+ cmoo = au_br_cmoo(br->br_perm); -+ if (!cmoo) -+ goto out; -+ if (!d_is_reg(dentry)) -+ cmoo &= AuBrAttr_COO_ALL; -+ if (!cmoo) -+ goto out; -+ -+ parent = dget_parent(dentry); -+ di_write_lock_parent(parent); -+ err = au_wbr_do_copyup_bu(dentry, cpg.bsrc - 1); -+ cpg.bdst = err; -+ if (unlikely(err < 0)) { -+ err = 0; /* there is no upper writable branch */ -+ goto out_dgrade; -+ } -+ AuDbg("bsrc %d, bdst %d\n", cpg.bsrc, cpg.bdst); -+ -+ /* do not respect the coo attrib for the target branch */ -+ err = au_cpup_dirs(dentry, cpg.bdst); -+ if (unlikely(err)) -+ goto out_dgrade; -+ -+ di_downgrade_lock(parent, AuLock_IR); -+ udba = au_opt_udba(sb); -+ err = au_pin(&pin, dentry, cpg.bdst, udba, -+ AuPin_DI_LOCKED | AuPin_MNT_WRITE); -+ if (unlikely(err)) -+ goto out_parent; -+ -+ err = au_sio_cpup_simple(&cpg); -+ au_unpin(&pin); -+ if (unlikely(err)) -+ goto out_parent; -+ if (!(cmoo & AuBrWAttr_MOO)) -+ goto out_parent; /* success */ -+ -+ err = au_pin(&pin, dentry, cpg.bsrc, udba, -+ AuPin_DI_LOCKED | AuPin_MNT_WRITE); -+ if (unlikely(err)) -+ goto out_parent; -+ -+ h_path.mnt = au_br_mnt(br); -+ h_path.dentry = au_h_dptr(dentry, cpg.bsrc); -+ hdir = au_hi(d_inode(parent), cpg.bsrc); -+ delegated = NULL; -+ err = vfsub_unlink(hdir->hi_inode, &h_path, &delegated, /*force*/1); -+ au_unpin(&pin); -+ /* todo: keep h_dentry or not? */ -+ if (unlikely(err == -EWOULDBLOCK)) { -+ pr_warn("cannot retry for NFSv4 delegation" -+ " for an internal unlink\n"); -+ iput(delegated); -+ } -+ if (unlikely(err)) { -+ pr_err("unlink %pd after coo failed (%d), ignored\n", -+ dentry, err); -+ err = 0; -+ } -+ goto out_parent; /* success */ -+ -+out_dgrade: -+ di_downgrade_lock(parent, AuLock_IR); -+out_parent: -+ di_read_unlock(parent, AuLock_IR); -+ dput(parent); -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+int au_do_open(struct file *file, struct au_do_open_args *args) -+{ -+ int err, aopen = args->aopen; -+ struct dentry *dentry; -+ struct au_finfo *finfo; -+ -+ if (!aopen) -+ err = au_finfo_init(file, args->fidir); -+ else { -+ lockdep_off(); -+ err = au_finfo_init(file, args->fidir); -+ lockdep_on(); -+ } -+ if (unlikely(err)) -+ goto out; -+ -+ dentry = file->f_path.dentry; -+ AuDebugOn(IS_ERR_OR_NULL(dentry)); -+ di_write_lock_child(dentry); -+ err = au_cmoo(dentry); -+ di_downgrade_lock(dentry, AuLock_IR); -+ if (!err) { -+ if (!aopen) -+ err = args->open(file, vfsub_file_flags(file), NULL); -+ else { -+ lockdep_off(); -+ err = args->open(file, vfsub_file_flags(file), -+ args->h_file); -+ lockdep_on(); -+ } -+ } -+ di_read_unlock(dentry, AuLock_IR); -+ -+ finfo = au_fi(file); -+ if (!err) { -+ finfo->fi_file = file; -+ au_hbl_add(&finfo->fi_hlist, -+ &au_sbi(file->f_path.dentry->d_sb)->si_files); -+ } -+ if (!aopen) -+ fi_write_unlock(file); -+ else { -+ lockdep_off(); -+ fi_write_unlock(file); -+ lockdep_on(); -+ } -+ if (unlikely(err)) { -+ finfo->fi_hdir = NULL; -+ au_finfo_fin(file); -+ } -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+int au_reopen_nondir(struct file *file) -+{ -+ int err; -+ aufs_bindex_t btop; -+ struct dentry *dentry; -+ struct au_branch *br; -+ struct file *h_file, *h_file_tmp; -+ -+ dentry = file->f_path.dentry; -+ btop = au_dbtop(dentry); -+ br = au_sbr(dentry->d_sb, btop); -+ h_file_tmp = NULL; -+ if (au_fbtop(file) == btop) { -+ h_file = au_hf_top(file); -+ if (file->f_mode == h_file->f_mode) -+ return 0; /* success */ -+ h_file_tmp = h_file; -+ get_file(h_file_tmp); -+ au_lcnt_inc(&br->br_nfiles); -+ au_set_h_fptr(file, btop, NULL); -+ } -+ AuDebugOn(au_fi(file)->fi_hdir); -+ /* -+ * it can happen -+ * file exists on both of rw and ro -+ * open --> dbtop and fbtop are both 0 -+ * prepend a branch as rw, "rw" become ro -+ * remove rw/file -+ * delete the top branch, "rw" becomes rw again -+ * --> dbtop is 1, fbtop is still 0 -+ * write --> fbtop is 0 but dbtop is 1 -+ */ -+ /* AuDebugOn(au_fbtop(file) < btop); */ -+ -+ h_file = au_h_open(dentry, btop, vfsub_file_flags(file) & ~O_TRUNC, -+ file, /*force_wr*/0); -+ err = PTR_ERR(h_file); -+ if (IS_ERR(h_file)) { -+ if (h_file_tmp) { -+ /* revert */ -+ au_set_h_fptr(file, btop, h_file_tmp); -+ h_file_tmp = NULL; -+ } -+ goto out; /* todo: close all? */ -+ } -+ -+ err = 0; -+ au_set_fbtop(file, btop); -+ au_set_h_fptr(file, btop, h_file); -+ au_update_figen(file); -+ /* todo: necessary? */ -+ /* file->f_ra = h_file->f_ra; */ -+ -+out: -+ if (h_file_tmp) { -+ fput(h_file_tmp); -+ au_lcnt_dec(&br->br_nfiles); -+ } -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int au_reopen_wh(struct file *file, aufs_bindex_t btgt, -+ struct dentry *hi_wh) -+{ -+ int err; -+ aufs_bindex_t btop; -+ struct au_dinfo *dinfo; -+ struct dentry *h_dentry; -+ struct au_hdentry *hdp; -+ -+ dinfo = au_di(file->f_path.dentry); -+ AuRwMustWriteLock(&dinfo->di_rwsem); -+ -+ btop = dinfo->di_btop; -+ dinfo->di_btop = btgt; -+ hdp = au_hdentry(dinfo, btgt); -+ h_dentry = hdp->hd_dentry; -+ hdp->hd_dentry = hi_wh; -+ err = au_reopen_nondir(file); -+ hdp->hd_dentry = h_dentry; -+ dinfo->di_btop = btop; -+ -+ return err; -+} -+ -+static int au_ready_to_write_wh(struct file *file, loff_t len, -+ aufs_bindex_t bcpup, struct au_pin *pin) -+{ -+ int err; -+ struct inode *inode, *h_inode; -+ struct dentry *h_dentry, *hi_wh; -+ struct au_cp_generic cpg = { -+ .dentry = file->f_path.dentry, -+ .bdst = bcpup, -+ .bsrc = -1, -+ .len = len, -+ .pin = pin -+ }; -+ -+ au_update_dbtop(cpg.dentry); -+ inode = d_inode(cpg.dentry); -+ h_inode = NULL; -+ if (au_dbtop(cpg.dentry) <= bcpup -+ && au_dbbot(cpg.dentry) >= bcpup) { -+ h_dentry = au_h_dptr(cpg.dentry, bcpup); -+ if (h_dentry && d_is_positive(h_dentry)) -+ h_inode = d_inode(h_dentry); -+ } -+ hi_wh = au_hi_wh(inode, bcpup); -+ if (!hi_wh && !h_inode) -+ err = au_sio_cpup_wh(&cpg, file); -+ else -+ /* already copied-up after unlink */ -+ err = au_reopen_wh(file, bcpup, hi_wh); -+ -+ if (!err -+ && (inode->i_nlink > 1 -+ || (inode->i_state & I_LINKABLE)) -+ && au_opt_test(au_mntflags(cpg.dentry->d_sb), PLINK)) -+ au_plink_append(inode, bcpup, au_h_dptr(cpg.dentry, bcpup)); -+ -+ return err; -+} -+ -+/* -+ * prepare the @file for writing. -+ */ -+int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin) -+{ -+ int err; -+ aufs_bindex_t dbtop; -+ struct dentry *parent; -+ struct inode *inode; -+ struct super_block *sb; -+ struct file *h_file; -+ struct au_cp_generic cpg = { -+ .dentry = file->f_path.dentry, -+ .bdst = -1, -+ .bsrc = -1, -+ .len = len, -+ .pin = pin, -+ .flags = AuCpup_DTIME -+ }; -+ -+ sb = cpg.dentry->d_sb; -+ inode = d_inode(cpg.dentry); -+ cpg.bsrc = au_fbtop(file); -+ err = au_test_ro(sb, cpg.bsrc, inode); -+ if (!err && (au_hf_top(file)->f_mode & FMODE_WRITE)) { -+ err = au_pin(pin, cpg.dentry, cpg.bsrc, AuOpt_UDBA_NONE, -+ /*flags*/0); -+ goto out; -+ } -+ -+ /* need to cpup or reopen */ -+ parent = dget_parent(cpg.dentry); -+ di_write_lock_parent(parent); -+ err = AuWbrCopyup(au_sbi(sb), cpg.dentry); -+ cpg.bdst = err; -+ if (unlikely(err < 0)) -+ goto out_dgrade; -+ err = 0; -+ -+ if (!d_unhashed(cpg.dentry) && !au_h_dptr(parent, cpg.bdst)) { -+ err = au_cpup_dirs(cpg.dentry, cpg.bdst); -+ if (unlikely(err)) -+ goto out_dgrade; -+ } -+ -+ err = au_pin(pin, cpg.dentry, cpg.bdst, AuOpt_UDBA_NONE, -+ AuPin_DI_LOCKED | AuPin_MNT_WRITE); -+ if (unlikely(err)) -+ goto out_dgrade; -+ -+ dbtop = au_dbtop(cpg.dentry); -+ if (dbtop <= cpg.bdst) -+ cpg.bsrc = cpg.bdst; -+ -+ if (dbtop <= cpg.bdst /* just reopen */ -+ || !d_unhashed(cpg.dentry) /* copyup and reopen */ -+ ) { -+ h_file = au_h_open_pre(cpg.dentry, cpg.bsrc, /*force_wr*/0); -+ if (IS_ERR(h_file)) -+ err = PTR_ERR(h_file); -+ else { -+ di_downgrade_lock(parent, AuLock_IR); -+ if (dbtop > cpg.bdst) -+ err = au_sio_cpup_simple(&cpg); -+ if (!err) -+ err = au_reopen_nondir(file); -+ au_h_open_post(cpg.dentry, cpg.bsrc, h_file); -+ } -+ } else { /* copyup as wh and reopen */ -+ /* -+ * since writable hfsplus branch is not supported, -+ * h_open_pre/post() are unnecessary. -+ */ -+ err = au_ready_to_write_wh(file, len, cpg.bdst, pin); -+ di_downgrade_lock(parent, AuLock_IR); -+ } -+ -+ if (!err) { -+ au_pin_set_parent_lflag(pin, /*lflag*/0); -+ goto out_dput; /* success */ -+ } -+ au_unpin(pin); -+ goto out_unlock; -+ -+out_dgrade: -+ di_downgrade_lock(parent, AuLock_IR); -+out_unlock: -+ di_read_unlock(parent, AuLock_IR); -+out_dput: -+ dput(parent); -+out: -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+int au_do_flush(struct file *file, fl_owner_t id, -+ int (*flush)(struct file *file, fl_owner_t id)) -+{ -+ int err; -+ struct super_block *sb; -+ struct inode *inode; -+ -+ inode = file_inode(file); -+ sb = inode->i_sb; -+ si_noflush_read_lock(sb); -+ fi_read_lock(file); -+ ii_read_lock_child(inode); -+ -+ err = flush(file, id); -+ au_cpup_attr_timesizes(inode); -+ -+ ii_read_unlock(inode); -+ fi_read_unlock(file); -+ si_read_unlock(sb); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int au_file_refresh_by_inode(struct file *file, int *need_reopen) -+{ -+ int err; -+ struct au_pin pin; -+ struct au_finfo *finfo; -+ struct dentry *parent, *hi_wh; -+ struct inode *inode; -+ struct super_block *sb; -+ struct au_cp_generic cpg = { -+ .dentry = file->f_path.dentry, -+ .bdst = -1, -+ .bsrc = -1, -+ .len = -1, -+ .pin = &pin, -+ .flags = AuCpup_DTIME -+ }; -+ -+ FiMustWriteLock(file); -+ -+ err = 0; -+ finfo = au_fi(file); -+ sb = cpg.dentry->d_sb; -+ inode = d_inode(cpg.dentry); -+ cpg.bdst = au_ibtop(inode); -+ if (cpg.bdst == finfo->fi_btop || IS_ROOT(cpg.dentry)) -+ goto out; -+ -+ parent = dget_parent(cpg.dentry); -+ if (au_test_ro(sb, cpg.bdst, inode)) { -+ di_read_lock_parent(parent, !AuLock_IR); -+ err = AuWbrCopyup(au_sbi(sb), cpg.dentry); -+ cpg.bdst = err; -+ di_read_unlock(parent, !AuLock_IR); -+ if (unlikely(err < 0)) -+ goto out_parent; -+ err = 0; -+ } -+ -+ di_read_lock_parent(parent, AuLock_IR); -+ hi_wh = au_hi_wh(inode, cpg.bdst); -+ if (!S_ISDIR(inode->i_mode) -+ && au_opt_test(au_mntflags(sb), PLINK) -+ && au_plink_test(inode) -+ && !d_unhashed(cpg.dentry) -+ && cpg.bdst < au_dbtop(cpg.dentry)) { -+ err = au_test_and_cpup_dirs(cpg.dentry, cpg.bdst); -+ if (unlikely(err)) -+ goto out_unlock; -+ -+ /* always superio. */ -+ err = au_pin(&pin, cpg.dentry, cpg.bdst, AuOpt_UDBA_NONE, -+ AuPin_DI_LOCKED | AuPin_MNT_WRITE); -+ if (!err) { -+ err = au_sio_cpup_simple(&cpg); -+ au_unpin(&pin); -+ } -+ } else if (hi_wh) { -+ /* already copied-up after unlink */ -+ err = au_reopen_wh(file, cpg.bdst, hi_wh); -+ *need_reopen = 0; -+ } -+ -+out_unlock: -+ di_read_unlock(parent, AuLock_IR); -+out_parent: -+ dput(parent); -+out: -+ return err; -+} -+ -+static void au_do_refresh_dir(struct file *file) -+{ -+ aufs_bindex_t bindex, bbot, new_bindex, brid; -+ struct au_hfile *p, tmp, *q; -+ struct au_finfo *finfo; -+ struct super_block *sb; -+ struct au_fidir *fidir; -+ -+ FiMustWriteLock(file); -+ -+ sb = file->f_path.dentry->d_sb; -+ finfo = au_fi(file); -+ fidir = finfo->fi_hdir; -+ AuDebugOn(!fidir); -+ p = fidir->fd_hfile + finfo->fi_btop; -+ brid = p->hf_br->br_id; -+ bbot = fidir->fd_bbot; -+ for (bindex = finfo->fi_btop; bindex <= bbot; bindex++, p++) { -+ if (!p->hf_file) -+ continue; -+ -+ new_bindex = au_br_index(sb, p->hf_br->br_id); -+ if (new_bindex == bindex) -+ continue; -+ if (new_bindex < 0) { -+ au_set_h_fptr(file, bindex, NULL); -+ continue; -+ } -+ -+ /* swap two lower inode, and loop again */ -+ q = fidir->fd_hfile + new_bindex; -+ tmp = *q; -+ *q = *p; -+ *p = tmp; -+ if (tmp.hf_file) { -+ bindex--; -+ p--; -+ } -+ } -+ -+ p = fidir->fd_hfile; -+ if (!au_test_mmapped(file) && !d_unlinked(file->f_path.dentry)) { -+ bbot = au_sbbot(sb); -+ for (finfo->fi_btop = 0; finfo->fi_btop <= bbot; -+ finfo->fi_btop++, p++) -+ if (p->hf_file) { -+ if (file_inode(p->hf_file)) -+ break; -+ au_hfput(p, /*execed*/0); -+ } -+ } else { -+ bbot = au_br_index(sb, brid); -+ for (finfo->fi_btop = 0; finfo->fi_btop < bbot; -+ finfo->fi_btop++, p++) -+ if (p->hf_file) -+ au_hfput(p, /*execed*/0); -+ bbot = au_sbbot(sb); -+ } -+ -+ p = fidir->fd_hfile + bbot; -+ for (fidir->fd_bbot = bbot; fidir->fd_bbot >= finfo->fi_btop; -+ fidir->fd_bbot--, p--) -+ if (p->hf_file) { -+ if (file_inode(p->hf_file)) -+ break; -+ au_hfput(p, /*execed*/0); -+ } -+ AuDebugOn(fidir->fd_bbot < finfo->fi_btop); -+} -+ -+/* -+ * after branch manipulating, refresh the file. -+ */ -+static int refresh_file(struct file *file, int (*reopen)(struct file *file)) -+{ -+ int err, need_reopen, nbr; -+ aufs_bindex_t bbot, bindex; -+ struct dentry *dentry; -+ struct super_block *sb; -+ struct au_finfo *finfo; -+ struct au_hfile *hfile; -+ -+ dentry = file->f_path.dentry; -+ sb = dentry->d_sb; -+ nbr = au_sbbot(sb) + 1; -+ finfo = au_fi(file); -+ if (!finfo->fi_hdir) { -+ hfile = &finfo->fi_htop; -+ AuDebugOn(!hfile->hf_file); -+ bindex = au_br_index(sb, hfile->hf_br->br_id); -+ AuDebugOn(bindex < 0); -+ if (bindex != finfo->fi_btop) -+ au_set_fbtop(file, bindex); -+ } else { -+ err = au_fidir_realloc(finfo, nbr, /*may_shrink*/0); -+ if (unlikely(err)) -+ goto out; -+ au_do_refresh_dir(file); -+ } -+ -+ err = 0; -+ need_reopen = 1; -+ if (!au_test_mmapped(file)) -+ err = au_file_refresh_by_inode(file, &need_reopen); -+ if (finfo->fi_hdir) -+ /* harmless if err */ -+ au_fidir_realloc(finfo, nbr, /*may_shrink*/1); -+ if (!err && need_reopen && !d_unlinked(dentry)) -+ err = reopen(file); -+ if (!err) { -+ au_update_figen(file); -+ goto out; /* success */ -+ } -+ -+ /* error, close all lower files */ -+ if (finfo->fi_hdir) { -+ bbot = au_fbbot_dir(file); -+ for (bindex = au_fbtop(file); bindex <= bbot; bindex++) -+ au_set_h_fptr(file, bindex, NULL); -+ } -+ -+out: -+ return err; -+} -+ -+/* common function to regular file and dir */ -+int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file), -+ int wlock, unsigned int fi_lsc) -+{ -+ int err; -+ unsigned int sigen, figen; -+ aufs_bindex_t btop; -+ unsigned char pseudo_link; -+ struct dentry *dentry; -+ struct inode *inode; -+ -+ err = 0; -+ dentry = file->f_path.dentry; -+ inode = d_inode(dentry); -+ sigen = au_sigen(dentry->d_sb); -+ fi_write_lock_nested(file, fi_lsc); -+ figen = au_figen(file); -+ if (!fi_lsc) -+ di_write_lock_child(dentry); -+ else -+ di_write_lock_child2(dentry); -+ btop = au_dbtop(dentry); -+ pseudo_link = (btop != au_ibtop(inode)); -+ if (sigen == figen && !pseudo_link && au_fbtop(file) == btop) { -+ if (!wlock) { -+ di_downgrade_lock(dentry, AuLock_IR); -+ fi_downgrade_lock(file); -+ } -+ goto out; /* success */ -+ } -+ -+ AuDbg("sigen %d, figen %d\n", sigen, figen); -+ if (au_digen_test(dentry, sigen)) { -+ err = au_reval_dpath(dentry, sigen); -+ AuDebugOn(!err && au_digen_test(dentry, sigen)); -+ } -+ -+ if (!err) -+ err = refresh_file(file, reopen); -+ if (!err) { -+ if (!wlock) { -+ di_downgrade_lock(dentry, AuLock_IR); -+ fi_downgrade_lock(file); -+ } -+ } else { -+ di_write_unlock(dentry); -+ fi_write_unlock(file); -+ } -+ -+out: -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* cf. aufs_nopage() */ -+/* for madvise(2) */ -+static int aufs_readpage(struct file *file __maybe_unused, struct page *page) -+{ -+ unlock_page(page); -+ return 0; -+} -+ -+/* it will never be called, but necessary to support O_DIRECT */ -+static ssize_t aufs_direct_IO(struct kiocb *iocb, struct iov_iter *iter) -+{ BUG(); return 0; } -+ -+/* they will never be called. */ -+#ifdef CONFIG_AUFS_DEBUG -+static int aufs_write_begin(struct file *file, struct address_space *mapping, -+ loff_t pos, unsigned len, unsigned flags, -+ struct page **pagep, void **fsdata) -+{ AuUnsupport(); return 0; } -+static int aufs_write_end(struct file *file, struct address_space *mapping, -+ loff_t pos, unsigned len, unsigned copied, -+ struct page *page, void *fsdata) -+{ AuUnsupport(); return 0; } -+static int aufs_writepage(struct page *page, struct writeback_control *wbc) -+{ AuUnsupport(); return 0; } -+ -+static int aufs_set_page_dirty(struct page *page) -+{ AuUnsupport(); return 0; } -+static void aufs_invalidatepage(struct page *page, unsigned int offset, -+ unsigned int length) -+{ AuUnsupport(); } -+static int aufs_releasepage(struct page *page, gfp_t gfp) -+{ AuUnsupport(); return 0; } -+#if 0 /* called by memory compaction regardless file */ -+static int aufs_migratepage(struct address_space *mapping, struct page *newpage, -+ struct page *page, enum migrate_mode mode) -+{ AuUnsupport(); return 0; } -+#endif -+static bool aufs_isolate_page(struct page *page, isolate_mode_t mode) -+{ AuUnsupport(); return true; } -+static void aufs_putback_page(struct page *page) -+{ AuUnsupport(); } -+static int aufs_launder_page(struct page *page) -+{ AuUnsupport(); return 0; } -+static int aufs_is_partially_uptodate(struct page *page, -+ unsigned long from, -+ unsigned long count) -+{ AuUnsupport(); return 0; } -+static void aufs_is_dirty_writeback(struct page *page, bool *dirty, -+ bool *writeback) -+{ AuUnsupport(); } -+static int aufs_error_remove_page(struct address_space *mapping, -+ struct page *page) -+{ AuUnsupport(); return 0; } -+static int aufs_swap_activate(struct swap_info_struct *sis, struct file *file, -+ sector_t *span) -+{ AuUnsupport(); return 0; } -+static void aufs_swap_deactivate(struct file *file) -+{ AuUnsupport(); } -+#endif /* CONFIG_AUFS_DEBUG */ -+ -+const struct address_space_operations aufs_aop = { -+ .readpage = aufs_readpage, -+ .direct_IO = aufs_direct_IO, -+#ifdef CONFIG_AUFS_DEBUG -+ .writepage = aufs_writepage, -+ /* no writepages, because of writepage */ -+ .set_page_dirty = aufs_set_page_dirty, -+ /* no readpages, because of readpage */ -+ .write_begin = aufs_write_begin, -+ .write_end = aufs_write_end, -+ /* no bmap, no block device */ -+ .invalidatepage = aufs_invalidatepage, -+ .releasepage = aufs_releasepage, -+ /* is fallback_migrate_page ok? */ -+ /* .migratepage = aufs_migratepage, */ -+ .isolate_page = aufs_isolate_page, -+ .putback_page = aufs_putback_page, -+ .launder_page = aufs_launder_page, -+ .is_partially_uptodate = aufs_is_partially_uptodate, -+ .is_dirty_writeback = aufs_is_dirty_writeback, -+ .error_remove_page = aufs_error_remove_page, -+ .swap_activate = aufs_swap_activate, -+ .swap_deactivate = aufs_swap_deactivate -+#endif /* CONFIG_AUFS_DEBUG */ -+}; -diff -Nurp linux-5.6.3/fs/aufs/file.h linux-5.6.3-aufs/fs/aufs/file.h ---- linux-5.6.3/fs/aufs/file.h 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/file.h 2020-04-10 12:40:52.190049409 +0300 -@@ -0,0 +1,329 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * file operations -+ */ -+ -+#ifndef __AUFS_FILE_H__ -+#define __AUFS_FILE_H__ -+ -+#ifdef __KERNEL__ -+ -+#include -+#include -+#include -+#include -+#include "rwsem.h" -+ -+struct au_branch; -+struct au_hfile { -+ struct file *hf_file; -+ struct au_branch *hf_br; -+}; -+ -+struct au_vdir; -+struct au_fidir { -+ aufs_bindex_t fd_bbot; -+ aufs_bindex_t fd_nent; -+ struct au_vdir *fd_vdir_cache; -+ struct au_hfile fd_hfile[]; -+}; -+ -+static inline int au_fidir_sz(int nent) -+{ -+ AuDebugOn(nent < 0); -+ return sizeof(struct au_fidir) + sizeof(struct au_hfile) * nent; -+} -+ -+struct au_finfo { -+ atomic_t fi_generation; -+ -+ struct au_rwsem fi_rwsem; -+ aufs_bindex_t fi_btop; -+ -+ /* do not union them */ -+ struct { /* for non-dir */ -+ struct au_hfile fi_htop; -+ atomic_t fi_mmapped; -+ }; -+ struct au_fidir *fi_hdir; /* for dir only */ -+ -+ struct hlist_bl_node fi_hlist; -+ struct file *fi_file; /* very ugly */ -+ struct rcu_head rcu; -+} ____cacheline_aligned_in_smp; -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* file.c */ -+extern const struct address_space_operations aufs_aop; -+unsigned int au_file_roflags(unsigned int flags); -+struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags, -+ struct file *file, int force_wr); -+struct au_do_open_args { -+ int aopen; -+ int (*open)(struct file *file, int flags, -+ struct file *h_file); -+ struct au_fidir *fidir; -+ struct file *h_file; -+}; -+int au_do_open(struct file *file, struct au_do_open_args *args); -+int au_reopen_nondir(struct file *file); -+struct au_pin; -+int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin); -+int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file), -+ int wlock, unsigned int fi_lsc); -+int au_do_flush(struct file *file, fl_owner_t id, -+ int (*flush)(struct file *file, fl_owner_t id)); -+ -+/* poll.c */ -+#ifdef CONFIG_AUFS_POLL -+__poll_t aufs_poll(struct file *file, struct poll_table_struct *pt); -+#endif -+ -+#ifdef CONFIG_AUFS_BR_HFSPLUS -+/* hfsplus.c */ -+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex, -+ int force_wr); -+void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex, -+ struct file *h_file); -+#else -+AuStub(struct file *, au_h_open_pre, return NULL, struct dentry *dentry, -+ aufs_bindex_t bindex, int force_wr) -+AuStubVoid(au_h_open_post, struct dentry *dentry, aufs_bindex_t bindex, -+ struct file *h_file); -+#endif -+ -+/* f_op.c */ -+extern const struct file_operations aufs_file_fop; -+int au_do_open_nondir(struct file *file, int flags, struct file *h_file); -+int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file); -+struct file *au_read_pre(struct file *file, int keep_fi, unsigned int lsc); -+ -+/* finfo.c */ -+void au_hfput(struct au_hfile *hf, int execed); -+void au_set_h_fptr(struct file *file, aufs_bindex_t bindex, -+ struct file *h_file); -+ -+void au_update_figen(struct file *file); -+struct au_fidir *au_fidir_alloc(struct super_block *sb); -+int au_fidir_realloc(struct au_finfo *finfo, int nbr, int may_shrink); -+ -+void au_fi_init_once(void *_fi); -+void au_finfo_fin(struct file *file); -+int au_finfo_init(struct file *file, struct au_fidir *fidir); -+ -+/* ioctl.c */ -+long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg); -+#ifdef CONFIG_COMPAT -+long aufs_compat_ioctl_dir(struct file *file, unsigned int cmd, -+ unsigned long arg); -+long aufs_compat_ioctl_nondir(struct file *file, unsigned int cmd, -+ unsigned long arg); -+#endif -+ -+/* ---------------------------------------------------------------------- */ -+ -+static inline struct au_finfo *au_fi(struct file *file) -+{ -+ return file->private_data; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+#define fi_read_lock(f) au_rw_read_lock(&au_fi(f)->fi_rwsem) -+#define fi_write_lock(f) au_rw_write_lock(&au_fi(f)->fi_rwsem) -+#define fi_read_trylock(f) au_rw_read_trylock(&au_fi(f)->fi_rwsem) -+#define fi_write_trylock(f) au_rw_write_trylock(&au_fi(f)->fi_rwsem) -+/* -+#define fi_read_trylock_nested(f) \ -+ au_rw_read_trylock_nested(&au_fi(f)->fi_rwsem) -+#define fi_write_trylock_nested(f) \ -+ au_rw_write_trylock_nested(&au_fi(f)->fi_rwsem) -+*/ -+ -+#define fi_read_unlock(f) au_rw_read_unlock(&au_fi(f)->fi_rwsem) -+#define fi_write_unlock(f) au_rw_write_unlock(&au_fi(f)->fi_rwsem) -+#define fi_downgrade_lock(f) au_rw_dgrade_lock(&au_fi(f)->fi_rwsem) -+ -+/* lock subclass for finfo */ -+enum { -+ AuLsc_FI_1, -+ AuLsc_FI_2 -+}; -+ -+static inline void fi_read_lock_nested(struct file *f, unsigned int lsc) -+{ -+ au_rw_read_lock_nested(&au_fi(f)->fi_rwsem, lsc); -+} -+ -+static inline void fi_write_lock_nested(struct file *f, unsigned int lsc) -+{ -+ au_rw_write_lock_nested(&au_fi(f)->fi_rwsem, lsc); -+} -+ -+/* -+ * fi_read_lock_1, fi_write_lock_1, -+ * fi_read_lock_2, fi_write_lock_2 -+ */ -+#define AuReadLockFunc(name) \ -+static inline void fi_read_lock_##name(struct file *f) \ -+{ fi_read_lock_nested(f, AuLsc_FI_##name); } -+ -+#define AuWriteLockFunc(name) \ -+static inline void fi_write_lock_##name(struct file *f) \ -+{ fi_write_lock_nested(f, AuLsc_FI_##name); } -+ -+#define AuRWLockFuncs(name) \ -+ AuReadLockFunc(name) \ -+ AuWriteLockFunc(name) -+ -+AuRWLockFuncs(1); -+AuRWLockFuncs(2); -+ -+#undef AuReadLockFunc -+#undef AuWriteLockFunc -+#undef AuRWLockFuncs -+ -+#define FiMustNoWaiters(f) AuRwMustNoWaiters(&au_fi(f)->fi_rwsem) -+#define FiMustAnyLock(f) AuRwMustAnyLock(&au_fi(f)->fi_rwsem) -+#define FiMustWriteLock(f) AuRwMustWriteLock(&au_fi(f)->fi_rwsem) -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* todo: hard/soft set? */ -+static inline aufs_bindex_t au_fbtop(struct file *file) -+{ -+ FiMustAnyLock(file); -+ return au_fi(file)->fi_btop; -+} -+ -+static inline aufs_bindex_t au_fbbot_dir(struct file *file) -+{ -+ FiMustAnyLock(file); -+ AuDebugOn(!au_fi(file)->fi_hdir); -+ return au_fi(file)->fi_hdir->fd_bbot; -+} -+ -+static inline struct au_vdir *au_fvdir_cache(struct file *file) -+{ -+ FiMustAnyLock(file); -+ AuDebugOn(!au_fi(file)->fi_hdir); -+ return au_fi(file)->fi_hdir->fd_vdir_cache; -+} -+ -+static inline void au_set_fbtop(struct file *file, aufs_bindex_t bindex) -+{ -+ FiMustWriteLock(file); -+ au_fi(file)->fi_btop = bindex; -+} -+ -+static inline void au_set_fbbot_dir(struct file *file, aufs_bindex_t bindex) -+{ -+ FiMustWriteLock(file); -+ AuDebugOn(!au_fi(file)->fi_hdir); -+ au_fi(file)->fi_hdir->fd_bbot = bindex; -+} -+ -+static inline void au_set_fvdir_cache(struct file *file, -+ struct au_vdir *vdir_cache) -+{ -+ FiMustWriteLock(file); -+ AuDebugOn(!au_fi(file)->fi_hdir); -+ au_fi(file)->fi_hdir->fd_vdir_cache = vdir_cache; -+} -+ -+static inline struct file *au_hf_top(struct file *file) -+{ -+ FiMustAnyLock(file); -+ AuDebugOn(au_fi(file)->fi_hdir); -+ return au_fi(file)->fi_htop.hf_file; -+} -+ -+static inline struct file *au_hf_dir(struct file *file, aufs_bindex_t bindex) -+{ -+ FiMustAnyLock(file); -+ AuDebugOn(!au_fi(file)->fi_hdir); -+ return au_fi(file)->fi_hdir->fd_hfile[0 + bindex].hf_file; -+} -+ -+/* todo: memory barrier? */ -+static inline unsigned int au_figen(struct file *f) -+{ -+ return atomic_read(&au_fi(f)->fi_generation); -+} -+ -+static inline void au_set_mmapped(struct file *f) -+{ -+ if (atomic_inc_return(&au_fi(f)->fi_mmapped)) -+ return; -+ pr_warn("fi_mmapped wrapped around\n"); -+ while (!atomic_inc_return(&au_fi(f)->fi_mmapped)) -+ ; -+} -+ -+static inline void au_unset_mmapped(struct file *f) -+{ -+ atomic_dec(&au_fi(f)->fi_mmapped); -+} -+ -+static inline int au_test_mmapped(struct file *f) -+{ -+ return atomic_read(&au_fi(f)->fi_mmapped); -+} -+ -+/* customize vma->vm_file */ -+ -+static inline void au_do_vm_file_reset(struct vm_area_struct *vma, -+ struct file *file) -+{ -+ struct file *f; -+ -+ f = vma->vm_file; -+ get_file(file); -+ vma->vm_file = file; -+ fput(f); -+} -+ -+#ifdef CONFIG_MMU -+#define AuDbgVmRegion(file, vma) do {} while (0) -+ -+static inline void au_vm_file_reset(struct vm_area_struct *vma, -+ struct file *file) -+{ -+ au_do_vm_file_reset(vma, file); -+} -+#else -+#define AuDbgVmRegion(file, vma) \ -+ AuDebugOn((vma)->vm_region && (vma)->vm_region->vm_file != (file)) -+ -+static inline void au_vm_file_reset(struct vm_area_struct *vma, -+ struct file *file) -+{ -+ struct file *f; -+ -+ au_do_vm_file_reset(vma, file); -+ f = vma->vm_region->vm_file; -+ get_file(file); -+ vma->vm_region->vm_file = file; -+ fput(f); -+} -+#endif /* CONFIG_MMU */ -+ -+/* handle vma->vm_prfile */ -+static inline void au_vm_prfile_set(struct vm_area_struct *vma, -+ struct file *file) -+{ -+ get_file(file); -+ vma->vm_prfile = file; -+#ifndef CONFIG_MMU -+ get_file(file); -+ vma->vm_region->vm_prfile = file; -+#endif -+} -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_FILE_H__ */ -diff -Nurp linux-5.6.3/fs/aufs/finfo.c linux-5.6.3-aufs/fs/aufs/finfo.c ---- linux-5.6.3/fs/aufs/finfo.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/finfo.c 2020-04-10 12:40:52.190049409 +0300 -@@ -0,0 +1,136 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * file private data -+ */ -+ -+#include "aufs.h" -+ -+void au_hfput(struct au_hfile *hf, int execed) -+{ -+ if (execed) -+ allow_write_access(hf->hf_file); -+ fput(hf->hf_file); -+ hf->hf_file = NULL; -+ au_lcnt_dec(&hf->hf_br->br_nfiles); -+ hf->hf_br = NULL; -+} -+ -+void au_set_h_fptr(struct file *file, aufs_bindex_t bindex, struct file *val) -+{ -+ struct au_finfo *finfo = au_fi(file); -+ struct au_hfile *hf; -+ struct au_fidir *fidir; -+ -+ fidir = finfo->fi_hdir; -+ if (!fidir) { -+ AuDebugOn(finfo->fi_btop != bindex); -+ hf = &finfo->fi_htop; -+ } else -+ hf = fidir->fd_hfile + bindex; -+ -+ if (hf && hf->hf_file) -+ au_hfput(hf, vfsub_file_execed(file)); -+ if (val) { -+ FiMustWriteLock(file); -+ AuDebugOn(IS_ERR_OR_NULL(file->f_path.dentry)); -+ hf->hf_file = val; -+ hf->hf_br = au_sbr(file->f_path.dentry->d_sb, bindex); -+ } -+} -+ -+void au_update_figen(struct file *file) -+{ -+ atomic_set(&au_fi(file)->fi_generation, au_digen(file->f_path.dentry)); -+ /* smp_mb(); */ /* atomic_set */ -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct au_fidir *au_fidir_alloc(struct super_block *sb) -+{ -+ struct au_fidir *fidir; -+ int nbr; -+ -+ nbr = au_sbbot(sb) + 1; -+ if (nbr < 2) -+ nbr = 2; /* initial allocate for 2 branches */ -+ fidir = kzalloc(au_fidir_sz(nbr), GFP_NOFS); -+ if (fidir) { -+ fidir->fd_bbot = -1; -+ fidir->fd_nent = nbr; -+ } -+ -+ return fidir; -+} -+ -+int au_fidir_realloc(struct au_finfo *finfo, int nbr, int may_shrink) -+{ -+ int err; -+ struct au_fidir *fidir, *p; -+ -+ AuRwMustWriteLock(&finfo->fi_rwsem); -+ fidir = finfo->fi_hdir; -+ AuDebugOn(!fidir); -+ -+ err = -ENOMEM; -+ p = au_kzrealloc(fidir, au_fidir_sz(fidir->fd_nent), au_fidir_sz(nbr), -+ GFP_NOFS, may_shrink); -+ if (p) { -+ p->fd_nent = nbr; -+ finfo->fi_hdir = p; -+ err = 0; -+ } -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+void au_finfo_fin(struct file *file) -+{ -+ struct au_finfo *finfo; -+ -+ au_lcnt_dec(&au_sbi(file->f_path.dentry->d_sb)->si_nfiles); -+ -+ finfo = au_fi(file); -+ AuDebugOn(finfo->fi_hdir); -+ AuRwDestroy(&finfo->fi_rwsem); -+ au_cache_free_finfo(finfo); -+} -+ -+void au_fi_init_once(void *_finfo) -+{ -+ struct au_finfo *finfo = _finfo; -+ -+ au_rw_init(&finfo->fi_rwsem); -+} -+ -+int au_finfo_init(struct file *file, struct au_fidir *fidir) -+{ -+ int err; -+ struct au_finfo *finfo; -+ struct dentry *dentry; -+ -+ err = -ENOMEM; -+ dentry = file->f_path.dentry; -+ finfo = au_cache_alloc_finfo(); -+ if (unlikely(!finfo)) -+ goto out; -+ -+ err = 0; -+ au_lcnt_inc(&au_sbi(dentry->d_sb)->si_nfiles); -+ au_rw_write_lock(&finfo->fi_rwsem); -+ finfo->fi_btop = -1; -+ finfo->fi_hdir = fidir; -+ atomic_set(&finfo->fi_generation, au_digen(dentry)); -+ /* smp_mb(); */ /* atomic_set */ -+ -+ file->private_data = finfo; -+ -+out: -+ return err; -+} -diff -Nurp linux-5.6.3/fs/aufs/f_op.c linux-5.6.3-aufs/fs/aufs/f_op.c ---- linux-5.6.3/fs/aufs/f_op.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/f_op.c 2020-04-10 12:40:52.190049409 +0300 -@@ -0,0 +1,806 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * file and vm operations -+ */ -+ -+#include -+#include -+#include -+#include -+#include "aufs.h" -+ -+int au_do_open_nondir(struct file *file, int flags, struct file *h_file) -+{ -+ int err; -+ aufs_bindex_t bindex; -+ struct dentry *dentry, *h_dentry; -+ struct au_finfo *finfo; -+ struct inode *h_inode; -+ -+ FiMustWriteLock(file); -+ -+ err = 0; -+ dentry = file->f_path.dentry; -+ AuDebugOn(IS_ERR_OR_NULL(dentry)); -+ finfo = au_fi(file); -+ memset(&finfo->fi_htop, 0, sizeof(finfo->fi_htop)); -+ atomic_set(&finfo->fi_mmapped, 0); -+ bindex = au_dbtop(dentry); -+ if (!h_file) { -+ h_dentry = au_h_dptr(dentry, bindex); -+ err = vfsub_test_mntns(file->f_path.mnt, h_dentry->d_sb); -+ if (unlikely(err)) -+ goto out; -+ h_file = au_h_open(dentry, bindex, flags, file, /*force_wr*/0); -+ if (IS_ERR(h_file)) { -+ err = PTR_ERR(h_file); -+ goto out; -+ } -+ } else { -+ h_dentry = h_file->f_path.dentry; -+ err = vfsub_test_mntns(file->f_path.mnt, h_dentry->d_sb); -+ if (unlikely(err)) -+ goto out; -+ /* br ref is already inc-ed */ -+ } -+ -+ if ((flags & __O_TMPFILE) -+ && !(flags & O_EXCL)) { -+ h_inode = file_inode(h_file); -+ spin_lock(&h_inode->i_lock); -+ h_inode->i_state |= I_LINKABLE; -+ spin_unlock(&h_inode->i_lock); -+ } -+ au_set_fbtop(file, bindex); -+ au_set_h_fptr(file, bindex, h_file); -+ au_update_figen(file); -+ /* todo: necessary? */ -+ /* file->f_ra = h_file->f_ra; */ -+ -+out: -+ return err; -+} -+ -+static int aufs_open_nondir(struct inode *inode __maybe_unused, -+ struct file *file) -+{ -+ int err; -+ struct super_block *sb; -+ struct au_do_open_args args = { -+ .open = au_do_open_nondir -+ }; -+ -+ AuDbg("%pD, f_flags 0x%x, f_mode 0x%x\n", -+ file, vfsub_file_flags(file), file->f_mode); -+ -+ sb = file->f_path.dentry->d_sb; -+ si_read_lock(sb, AuLock_FLUSH); -+ err = au_do_open(file, &args); -+ si_read_unlock(sb); -+ return err; -+} -+ -+int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file) -+{ -+ struct au_finfo *finfo; -+ aufs_bindex_t bindex; -+ -+ finfo = au_fi(file); -+ au_hbl_del(&finfo->fi_hlist, -+ &au_sbi(file->f_path.dentry->d_sb)->si_files); -+ bindex = finfo->fi_btop; -+ if (bindex >= 0) -+ au_set_h_fptr(file, bindex, NULL); -+ -+ au_finfo_fin(file); -+ return 0; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int au_do_flush_nondir(struct file *file, fl_owner_t id) -+{ -+ int err; -+ struct file *h_file; -+ -+ err = 0; -+ h_file = au_hf_top(file); -+ if (h_file) -+ err = vfsub_flush(h_file, id); -+ return err; -+} -+ -+static int aufs_flush_nondir(struct file *file, fl_owner_t id) -+{ -+ return au_do_flush(file, id, au_do_flush_nondir); -+} -+ -+/* ---------------------------------------------------------------------- */ -+/* -+ * read and write functions acquire [fdi]_rwsem once, but release before -+ * mmap_sem. This is because to stop a race condition between mmap(2). -+ * Releasing these aufs-rwsem should be safe, no branch-management (by keeping -+ * si_rwsem), no harmful copy-up should happen. Actually copy-up may happen in -+ * read functions after [fdi]_rwsem are released, but it should be harmless. -+ */ -+ -+/* Callers should call au_read_post() or fput() in the end */ -+struct file *au_read_pre(struct file *file, int keep_fi, unsigned int lsc) -+{ -+ struct file *h_file; -+ int err; -+ -+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0, lsc); -+ if (!err) { -+ di_read_unlock(file->f_path.dentry, AuLock_IR); -+ h_file = au_hf_top(file); -+ get_file(h_file); -+ if (!keep_fi) -+ fi_read_unlock(file); -+ } else -+ h_file = ERR_PTR(err); -+ -+ return h_file; -+} -+ -+static void au_read_post(struct inode *inode, struct file *h_file) -+{ -+ /* update without lock, I don't think it a problem */ -+ fsstack_copy_attr_atime(inode, file_inode(h_file)); -+ fput(h_file); -+} -+ -+struct au_write_pre { -+ /* input */ -+ unsigned int lsc; -+ -+ /* output */ -+ blkcnt_t blks; -+ aufs_bindex_t btop; -+}; -+ -+/* -+ * return with iinfo is write-locked -+ * callers should call au_write_post() or iinfo_write_unlock() + fput() in the -+ * end -+ */ -+static struct file *au_write_pre(struct file *file, int do_ready, -+ struct au_write_pre *wpre) -+{ -+ struct file *h_file; -+ struct dentry *dentry; -+ int err; -+ unsigned int lsc; -+ struct au_pin pin; -+ -+ lsc = 0; -+ if (wpre) -+ lsc = wpre->lsc; -+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1, lsc); -+ h_file = ERR_PTR(err); -+ if (unlikely(err)) -+ goto out; -+ -+ dentry = file->f_path.dentry; -+ if (do_ready) { -+ err = au_ready_to_write(file, -1, &pin); -+ if (unlikely(err)) { -+ h_file = ERR_PTR(err); -+ di_write_unlock(dentry); -+ goto out_fi; -+ } -+ } -+ -+ di_downgrade_lock(dentry, /*flags*/0); -+ if (wpre) -+ wpre->btop = au_fbtop(file); -+ h_file = au_hf_top(file); -+ get_file(h_file); -+ if (wpre) -+ wpre->blks = file_inode(h_file)->i_blocks; -+ if (do_ready) -+ au_unpin(&pin); -+ di_read_unlock(dentry, /*flags*/0); -+ -+out_fi: -+ fi_write_unlock(file); -+out: -+ return h_file; -+} -+ -+static void au_write_post(struct inode *inode, struct file *h_file, -+ struct au_write_pre *wpre, ssize_t written) -+{ -+ struct inode *h_inode; -+ -+ au_cpup_attr_timesizes(inode); -+ AuDebugOn(au_ibtop(inode) != wpre->btop); -+ h_inode = file_inode(h_file); -+ inode->i_mode = h_inode->i_mode; -+ ii_write_unlock(inode); -+ /* AuDbg("blks %llu, %llu\n", (u64)blks, (u64)h_inode->i_blocks); */ -+ if (written > 0) -+ au_fhsm_wrote(inode->i_sb, wpre->btop, -+ /*force*/h_inode->i_blocks > wpre->blks); -+ fput(h_file); -+} -+ -+static ssize_t aufs_read(struct file *file, char __user *buf, size_t count, -+ loff_t *ppos) -+{ -+ ssize_t err; -+ struct inode *inode; -+ struct file *h_file; -+ struct super_block *sb; -+ -+ inode = file_inode(file); -+ sb = inode->i_sb; -+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW); -+ -+ h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0); -+ err = PTR_ERR(h_file); -+ if (IS_ERR(h_file)) -+ goto out; -+ -+ /* filedata may be obsoleted by concurrent copyup, but no problem */ -+ err = vfsub_read_u(h_file, buf, count, ppos); -+ /* todo: necessary? */ -+ /* file->f_ra = h_file->f_ra; */ -+ au_read_post(inode, h_file); -+ -+out: -+ si_read_unlock(sb); -+ return err; -+} -+ -+/* -+ * todo: very ugly -+ * it locks both of i_mutex and si_rwsem for read in safe. -+ * if the plink maintenance mode continues forever (that is the problem), -+ * may loop forever. -+ */ -+static void au_mtx_and_read_lock(struct inode *inode) -+{ -+ int err; -+ struct super_block *sb = inode->i_sb; -+ -+ while (1) { -+ inode_lock(inode); -+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM); -+ if (!err) -+ break; -+ inode_unlock(inode); -+ si_read_lock(sb, AuLock_NOPLMW); -+ si_read_unlock(sb); -+ } -+} -+ -+static ssize_t aufs_write(struct file *file, const char __user *ubuf, -+ size_t count, loff_t *ppos) -+{ -+ ssize_t err; -+ struct au_write_pre wpre; -+ struct inode *inode; -+ struct file *h_file; -+ char __user *buf = (char __user *)ubuf; -+ -+ inode = file_inode(file); -+ au_mtx_and_read_lock(inode); -+ -+ wpre.lsc = 0; -+ h_file = au_write_pre(file, /*do_ready*/1, &wpre); -+ err = PTR_ERR(h_file); -+ if (IS_ERR(h_file)) -+ goto out; -+ -+ err = vfsub_write_u(h_file, buf, count, ppos); -+ au_write_post(inode, h_file, &wpre, err); -+ -+out: -+ si_read_unlock(inode->i_sb); -+ inode_unlock(inode); -+ return err; -+} -+ -+static ssize_t au_do_iter(struct file *h_file, int rw, struct kiocb *kio, -+ struct iov_iter *iov_iter) -+{ -+ ssize_t err; -+ struct file *file; -+ ssize_t (*iter)(struct kiocb *, struct iov_iter *); -+ -+ err = security_file_permission(h_file, rw); -+ if (unlikely(err)) -+ goto out; -+ -+ err = -ENOSYS; /* the branch doesn't have its ->(read|write)_iter() */ -+ iter = NULL; -+ if (rw == MAY_READ) -+ iter = h_file->f_op->read_iter; -+ else if (rw == MAY_WRITE) -+ iter = h_file->f_op->write_iter; -+ -+ file = kio->ki_filp; -+ kio->ki_filp = h_file; -+ if (iter) { -+ lockdep_off(); -+ err = iter(kio, iov_iter); -+ lockdep_on(); -+ } else -+ /* currently there is no such fs */ -+ WARN_ON_ONCE(1); -+ kio->ki_filp = file; -+ -+out: -+ return err; -+} -+ -+static ssize_t aufs_read_iter(struct kiocb *kio, struct iov_iter *iov_iter) -+{ -+ ssize_t err; -+ struct file *file, *h_file; -+ struct inode *inode; -+ struct super_block *sb; -+ -+ file = kio->ki_filp; -+ inode = file_inode(file); -+ sb = inode->i_sb; -+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW); -+ -+ h_file = au_read_pre(file, /*keep_fi*/1, /*lsc*/0); -+ err = PTR_ERR(h_file); -+ if (IS_ERR(h_file)) -+ goto out; -+ -+ if (au_test_loopback_kthread()) { -+ au_warn_loopback(h_file->f_path.dentry->d_sb); -+ if (file->f_mapping != h_file->f_mapping) { -+ file->f_mapping = h_file->f_mapping; -+ smp_mb(); /* unnecessary? */ -+ } -+ } -+ fi_read_unlock(file); -+ -+ err = au_do_iter(h_file, MAY_READ, kio, iov_iter); -+ /* todo: necessary? */ -+ /* file->f_ra = h_file->f_ra; */ -+ au_read_post(inode, h_file); -+ -+out: -+ si_read_unlock(sb); -+ return err; -+} -+ -+static ssize_t aufs_write_iter(struct kiocb *kio, struct iov_iter *iov_iter) -+{ -+ ssize_t err; -+ struct au_write_pre wpre; -+ struct inode *inode; -+ struct file *file, *h_file; -+ -+ file = kio->ki_filp; -+ inode = file_inode(file); -+ au_mtx_and_read_lock(inode); -+ -+ wpre.lsc = 0; -+ h_file = au_write_pre(file, /*do_ready*/1, &wpre); -+ err = PTR_ERR(h_file); -+ if (IS_ERR(h_file)) -+ goto out; -+ -+ err = au_do_iter(h_file, MAY_WRITE, kio, iov_iter); -+ au_write_post(inode, h_file, &wpre, err); -+ -+out: -+ si_read_unlock(inode->i_sb); -+ inode_unlock(inode); -+ return err; -+} -+ -+static ssize_t aufs_splice_read(struct file *file, loff_t *ppos, -+ struct pipe_inode_info *pipe, size_t len, -+ unsigned int flags) -+{ -+ ssize_t err; -+ struct file *h_file; -+ struct inode *inode; -+ struct super_block *sb; -+ -+ inode = file_inode(file); -+ sb = inode->i_sb; -+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW); -+ -+ h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0); -+ err = PTR_ERR(h_file); -+ if (IS_ERR(h_file)) -+ goto out; -+ -+ err = vfsub_splice_to(h_file, ppos, pipe, len, flags); -+ /* todo: necessary? */ -+ /* file->f_ra = h_file->f_ra; */ -+ au_read_post(inode, h_file); -+ -+out: -+ si_read_unlock(sb); -+ return err; -+} -+ -+static ssize_t -+aufs_splice_write(struct pipe_inode_info *pipe, struct file *file, loff_t *ppos, -+ size_t len, unsigned int flags) -+{ -+ ssize_t err; -+ struct au_write_pre wpre; -+ struct inode *inode; -+ struct file *h_file; -+ -+ inode = file_inode(file); -+ au_mtx_and_read_lock(inode); -+ -+ wpre.lsc = 0; -+ h_file = au_write_pre(file, /*do_ready*/1, &wpre); -+ err = PTR_ERR(h_file); -+ if (IS_ERR(h_file)) -+ goto out; -+ -+ err = vfsub_splice_from(pipe, h_file, ppos, len, flags); -+ au_write_post(inode, h_file, &wpre, err); -+ -+out: -+ si_read_unlock(inode->i_sb); -+ inode_unlock(inode); -+ return err; -+} -+ -+static long aufs_fallocate(struct file *file, int mode, loff_t offset, -+ loff_t len) -+{ -+ long err; -+ struct au_write_pre wpre; -+ struct inode *inode; -+ struct file *h_file; -+ -+ inode = file_inode(file); -+ au_mtx_and_read_lock(inode); -+ -+ wpre.lsc = 0; -+ h_file = au_write_pre(file, /*do_ready*/1, &wpre); -+ err = PTR_ERR(h_file); -+ if (IS_ERR(h_file)) -+ goto out; -+ -+ lockdep_off(); -+ err = vfs_fallocate(h_file, mode, offset, len); -+ lockdep_on(); -+ au_write_post(inode, h_file, &wpre, /*written*/1); -+ -+out: -+ si_read_unlock(inode->i_sb); -+ inode_unlock(inode); -+ return err; -+} -+ -+static ssize_t aufs_copy_file_range(struct file *src, loff_t src_pos, -+ struct file *dst, loff_t dst_pos, -+ size_t len, unsigned int flags) -+{ -+ ssize_t err; -+ struct au_write_pre wpre; -+ enum { SRC, DST }; -+ struct { -+ struct inode *inode; -+ struct file *h_file; -+ struct super_block *h_sb; -+ } a[2]; -+#define a_src a[SRC] -+#define a_dst a[DST] -+ -+ err = -EINVAL; -+ a_src.inode = file_inode(src); -+ if (unlikely(!S_ISREG(a_src.inode->i_mode))) -+ goto out; -+ a_dst.inode = file_inode(dst); -+ if (unlikely(!S_ISREG(a_dst.inode->i_mode))) -+ goto out; -+ -+ au_mtx_and_read_lock(a_dst.inode); -+ /* -+ * in order to match the order in di_write_lock2_{child,parent}(), -+ * use f_path.dentry for this comparison. -+ */ -+ if (src->f_path.dentry < dst->f_path.dentry) { -+ a_src.h_file = au_read_pre(src, /*keep_fi*/1, AuLsc_FI_1); -+ err = PTR_ERR(a_src.h_file); -+ if (IS_ERR(a_src.h_file)) -+ goto out_si; -+ -+ wpre.lsc = AuLsc_FI_2; -+ a_dst.h_file = au_write_pre(dst, /*do_ready*/1, &wpre); -+ err = PTR_ERR(a_dst.h_file); -+ if (IS_ERR(a_dst.h_file)) { -+ au_read_post(a_src.inode, a_src.h_file); -+ goto out_si; -+ } -+ } else { -+ wpre.lsc = AuLsc_FI_1; -+ a_dst.h_file = au_write_pre(dst, /*do_ready*/1, &wpre); -+ err = PTR_ERR(a_dst.h_file); -+ if (IS_ERR(a_dst.h_file)) -+ goto out_si; -+ -+ a_src.h_file = au_read_pre(src, /*keep_fi*/1, AuLsc_FI_2); -+ err = PTR_ERR(a_src.h_file); -+ if (IS_ERR(a_src.h_file)) { -+ au_write_post(a_dst.inode, a_dst.h_file, &wpre, -+ /*written*/0); -+ goto out_si; -+ } -+ } -+ -+ err = -EXDEV; -+ a_src.h_sb = file_inode(a_src.h_file)->i_sb; -+ a_dst.h_sb = file_inode(a_dst.h_file)->i_sb; -+ if (unlikely(a_src.h_sb != a_dst.h_sb)) { -+ AuDbgFile(src); -+ AuDbgFile(dst); -+ goto out_file; -+ } -+ -+ err = vfsub_copy_file_range(a_src.h_file, src_pos, a_dst.h_file, -+ dst_pos, len, flags); -+ -+out_file: -+ au_write_post(a_dst.inode, a_dst.h_file, &wpre, err); -+ fi_read_unlock(src); -+ au_read_post(a_src.inode, a_src.h_file); -+out_si: -+ si_read_unlock(a_dst.inode->i_sb); -+ inode_unlock(a_dst.inode); -+out: -+ return err; -+#undef a_src -+#undef a_dst -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * The locking order around current->mmap_sem. -+ * - in most and regular cases -+ * file I/O syscall -- aufs_read() or something -+ * -- si_rwsem for read -- mmap_sem -+ * (Note that [fdi]i_rwsem are released before mmap_sem). -+ * - in mmap case -+ * mmap(2) -- mmap_sem -- aufs_mmap() -- si_rwsem for read -- [fdi]i_rwsem -+ * This AB-BA order is definitely bad, but is not a problem since "si_rwsem for -+ * read" allows multiple processes to acquire it and [fdi]i_rwsem are not held -+ * in file I/O. Aufs needs to stop lockdep in aufs_mmap() though. -+ * It means that when aufs acquires si_rwsem for write, the process should never -+ * acquire mmap_sem. -+ * -+ * Actually aufs_iterate() holds [fdi]i_rwsem before mmap_sem, but this is not a -+ * problem either since any directory is not able to be mmap-ed. -+ * The similar scenario is applied to aufs_readlink() too. -+ */ -+ -+#if 0 /* stop calling security_file_mmap() */ -+/* cf. linux/include/linux/mman.h: calc_vm_prot_bits() */ -+#define AuConv_VM_PROT(f, b) _calc_vm_trans(f, VM_##b, PROT_##b) -+ -+static unsigned long au_arch_prot_conv(unsigned long flags) -+{ -+ /* currently ppc64 only */ -+#ifdef CONFIG_PPC64 -+ /* cf. linux/arch/powerpc/include/asm/mman.h */ -+ AuDebugOn(arch_calc_vm_prot_bits(-1) != VM_SAO); -+ return AuConv_VM_PROT(flags, SAO); -+#else -+ AuDebugOn(arch_calc_vm_prot_bits(-1)); -+ return 0; -+#endif -+} -+ -+static unsigned long au_prot_conv(unsigned long flags) -+{ -+ return AuConv_VM_PROT(flags, READ) -+ | AuConv_VM_PROT(flags, WRITE) -+ | AuConv_VM_PROT(flags, EXEC) -+ | au_arch_prot_conv(flags); -+} -+ -+/* cf. linux/include/linux/mman.h: calc_vm_flag_bits() */ -+#define AuConv_VM_MAP(f, b) _calc_vm_trans(f, VM_##b, MAP_##b) -+ -+static unsigned long au_flag_conv(unsigned long flags) -+{ -+ return AuConv_VM_MAP(flags, GROWSDOWN) -+ | AuConv_VM_MAP(flags, DENYWRITE) -+ | AuConv_VM_MAP(flags, LOCKED); -+} -+#endif -+ -+static int aufs_mmap(struct file *file, struct vm_area_struct *vma) -+{ -+ int err; -+ const unsigned char wlock -+ = (file->f_mode & FMODE_WRITE) && (vma->vm_flags & VM_SHARED); -+ struct super_block *sb; -+ struct file *h_file; -+ struct inode *inode; -+ -+ AuDbgVmRegion(file, vma); -+ -+ inode = file_inode(file); -+ sb = inode->i_sb; -+ lockdep_off(); -+ si_read_lock(sb, AuLock_NOPLMW); -+ -+ h_file = au_write_pre(file, wlock, /*wpre*/NULL); -+ lockdep_on(); -+ err = PTR_ERR(h_file); -+ if (IS_ERR(h_file)) -+ goto out; -+ -+ err = 0; -+ au_set_mmapped(file); -+ au_vm_file_reset(vma, h_file); -+ /* -+ * we cannot call security_mmap_file() here since it may acquire -+ * mmap_sem or i_mutex. -+ * -+ * err = security_mmap_file(h_file, au_prot_conv(vma->vm_flags), -+ * au_flag_conv(vma->vm_flags)); -+ */ -+ if (!err) -+ err = call_mmap(h_file, vma); -+ if (!err) { -+ au_vm_prfile_set(vma, file); -+ fsstack_copy_attr_atime(inode, file_inode(h_file)); -+ goto out_fput; /* success */ -+ } -+ au_unset_mmapped(file); -+ au_vm_file_reset(vma, file); -+ -+out_fput: -+ lockdep_off(); -+ ii_write_unlock(inode); -+ lockdep_on(); -+ fput(h_file); -+out: -+ lockdep_off(); -+ si_read_unlock(sb); -+ lockdep_on(); -+ AuTraceErr(err); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int aufs_fsync_nondir(struct file *file, loff_t start, loff_t end, -+ int datasync) -+{ -+ int err; -+ struct au_write_pre wpre; -+ struct inode *inode; -+ struct file *h_file; -+ -+ err = 0; /* -EBADF; */ /* posix? */ -+ if (unlikely(!(file->f_mode & FMODE_WRITE))) -+ goto out; -+ -+ inode = file_inode(file); -+ au_mtx_and_read_lock(inode); -+ -+ wpre.lsc = 0; -+ h_file = au_write_pre(file, /*do_ready*/1, &wpre); -+ err = PTR_ERR(h_file); -+ if (IS_ERR(h_file)) -+ goto out_unlock; -+ -+ err = vfsub_fsync(h_file, &h_file->f_path, datasync); -+ au_write_post(inode, h_file, &wpre, /*written*/0); -+ -+out_unlock: -+ si_read_unlock(inode->i_sb); -+ inode_unlock(inode); -+out: -+ return err; -+} -+ -+static int aufs_fasync(int fd, struct file *file, int flag) -+{ -+ int err; -+ struct file *h_file; -+ struct super_block *sb; -+ -+ sb = file->f_path.dentry->d_sb; -+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW); -+ -+ h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0); -+ err = PTR_ERR(h_file); -+ if (IS_ERR(h_file)) -+ goto out; -+ -+ if (h_file->f_op->fasync) -+ err = h_file->f_op->fasync(fd, h_file, flag); -+ fput(h_file); /* instead of au_read_post() */ -+ -+out: -+ si_read_unlock(sb); -+ return err; -+} -+ -+static int aufs_setfl(struct file *file, unsigned long arg) -+{ -+ int err; -+ struct file *h_file; -+ struct super_block *sb; -+ -+ sb = file->f_path.dentry->d_sb; -+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW); -+ -+ h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0); -+ err = PTR_ERR(h_file); -+ if (IS_ERR(h_file)) -+ goto out; -+ -+ /* stop calling h_file->fasync */ -+ arg |= vfsub_file_flags(file) & FASYNC; -+ err = setfl(/*unused fd*/-1, h_file, arg); -+ fput(h_file); /* instead of au_read_post() */ -+ -+out: -+ si_read_unlock(sb); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* no one supports this operation, currently */ -+#if 0 /* reserved for future use */ -+static ssize_t aufs_sendpage(struct file *file, struct page *page, int offset, -+ size_t len, loff_t *pos, int more) -+{ -+} -+#endif -+ -+/* ---------------------------------------------------------------------- */ -+ -+const struct file_operations aufs_file_fop = { -+ .owner = THIS_MODULE, -+ -+ .llseek = default_llseek, -+ -+ .read = aufs_read, -+ .write = aufs_write, -+ .read_iter = aufs_read_iter, -+ .write_iter = aufs_write_iter, -+ -+#ifdef CONFIG_AUFS_POLL -+ .poll = aufs_poll, -+#endif -+ .unlocked_ioctl = aufs_ioctl_nondir, -+#ifdef CONFIG_COMPAT -+ .compat_ioctl = aufs_compat_ioctl_nondir, -+#endif -+ .mmap = aufs_mmap, -+ .open = aufs_open_nondir, -+ .flush = aufs_flush_nondir, -+ .release = aufs_release_nondir, -+ .fsync = aufs_fsync_nondir, -+ .fasync = aufs_fasync, -+ /* .sendpage = aufs_sendpage, */ -+ .setfl = aufs_setfl, -+ .splice_write = aufs_splice_write, -+ .splice_read = aufs_splice_read, -+#if 0 /* reserved for future use */ -+ .aio_splice_write = aufs_aio_splice_write, -+ .aio_splice_read = aufs_aio_splice_read, -+#endif -+ .fallocate = aufs_fallocate, -+ .copy_file_range = aufs_copy_file_range -+}; -diff -Nurp linux-5.6.3/fs/aufs/fstype.h linux-5.6.3-aufs/fs/aufs/fstype.h ---- linux-5.6.3/fs/aufs/fstype.h 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/fstype.h 2020-04-10 12:40:52.190049409 +0300 -@@ -0,0 +1,388 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * judging filesystem type -+ */ -+ -+#ifndef __AUFS_FSTYPE_H__ -+#define __AUFS_FSTYPE_H__ -+ -+#ifdef __KERNEL__ -+ -+#include -+#include -+#include -+#include -+ -+static inline int au_test_aufs(struct super_block *sb) -+{ -+ return sb->s_magic == AUFS_SUPER_MAGIC; -+} -+ -+static inline const char *au_sbtype(struct super_block *sb) -+{ -+ return sb->s_type->name; -+} -+ -+static inline int au_test_iso9660(struct super_block *sb __maybe_unused) -+{ -+#if IS_ENABLED(CONFIG_ISO9660_FS) -+ return sb->s_magic == ISOFS_SUPER_MAGIC; -+#else -+ return 0; -+#endif -+} -+ -+static inline int au_test_romfs(struct super_block *sb __maybe_unused) -+{ -+#if IS_ENABLED(CONFIG_ROMFS_FS) -+ return sb->s_magic == ROMFS_MAGIC; -+#else -+ return 0; -+#endif -+} -+ -+static inline int au_test_cramfs(struct super_block *sb __maybe_unused) -+{ -+#if IS_ENABLED(CONFIG_CRAMFS) -+ return sb->s_magic == CRAMFS_MAGIC; -+#endif -+ return 0; -+} -+ -+static inline int au_test_nfs(struct super_block *sb __maybe_unused) -+{ -+#if IS_ENABLED(CONFIG_NFS_FS) -+ return sb->s_magic == NFS_SUPER_MAGIC; -+#else -+ return 0; -+#endif -+} -+ -+static inline int au_test_fuse(struct super_block *sb __maybe_unused) -+{ -+#if IS_ENABLED(CONFIG_FUSE_FS) -+ return sb->s_magic == FUSE_SUPER_MAGIC; -+#else -+ return 0; -+#endif -+} -+ -+static inline int au_test_xfs(struct super_block *sb __maybe_unused) -+{ -+#if IS_ENABLED(CONFIG_XFS_FS) -+ return sb->s_magic == XFS_SB_MAGIC; -+#else -+ return 0; -+#endif -+} -+ -+static inline int au_test_tmpfs(struct super_block *sb __maybe_unused) -+{ -+#ifdef CONFIG_TMPFS -+ return sb->s_magic == TMPFS_MAGIC; -+#else -+ return 0; -+#endif -+} -+ -+static inline int au_test_ecryptfs(struct super_block *sb __maybe_unused) -+{ -+#if IS_ENABLED(CONFIG_ECRYPT_FS) -+ return !strcmp(au_sbtype(sb), "ecryptfs"); -+#else -+ return 0; -+#endif -+} -+ -+static inline int au_test_ramfs(struct super_block *sb) -+{ -+ return sb->s_magic == RAMFS_MAGIC; -+} -+ -+static inline int au_test_ubifs(struct super_block *sb __maybe_unused) -+{ -+#if IS_ENABLED(CONFIG_UBIFS_FS) -+ return sb->s_magic == UBIFS_SUPER_MAGIC; -+#else -+ return 0; -+#endif -+} -+ -+static inline int au_test_procfs(struct super_block *sb __maybe_unused) -+{ -+#ifdef CONFIG_PROC_FS -+ return sb->s_magic == PROC_SUPER_MAGIC; -+#else -+ return 0; -+#endif -+} -+ -+static inline int au_test_sysfs(struct super_block *sb __maybe_unused) -+{ -+#ifdef CONFIG_SYSFS -+ return sb->s_magic == SYSFS_MAGIC; -+#else -+ return 0; -+#endif -+} -+ -+static inline int au_test_configfs(struct super_block *sb __maybe_unused) -+{ -+#if IS_ENABLED(CONFIG_CONFIGFS_FS) -+ return sb->s_magic == CONFIGFS_MAGIC; -+#else -+ return 0; -+#endif -+} -+ -+static inline int au_test_minix(struct super_block *sb __maybe_unused) -+{ -+#if IS_ENABLED(CONFIG_MINIX_FS) -+ return sb->s_magic == MINIX3_SUPER_MAGIC -+ || sb->s_magic == MINIX2_SUPER_MAGIC -+ || sb->s_magic == MINIX2_SUPER_MAGIC2 -+ || sb->s_magic == MINIX_SUPER_MAGIC -+ || sb->s_magic == MINIX_SUPER_MAGIC2; -+#else -+ return 0; -+#endif -+} -+ -+static inline int au_test_fat(struct super_block *sb __maybe_unused) -+{ -+#if IS_ENABLED(CONFIG_FAT_FS) -+ return sb->s_magic == MSDOS_SUPER_MAGIC; -+#else -+ return 0; -+#endif -+} -+ -+static inline int au_test_msdos(struct super_block *sb) -+{ -+ return au_test_fat(sb); -+} -+ -+static inline int au_test_vfat(struct super_block *sb) -+{ -+ return au_test_fat(sb); -+} -+ -+static inline int au_test_securityfs(struct super_block *sb __maybe_unused) -+{ -+#ifdef CONFIG_SECURITYFS -+ return sb->s_magic == SECURITYFS_MAGIC; -+#else -+ return 0; -+#endif -+} -+ -+static inline int au_test_squashfs(struct super_block *sb __maybe_unused) -+{ -+#if IS_ENABLED(CONFIG_SQUASHFS) -+ return sb->s_magic == SQUASHFS_MAGIC; -+#else -+ return 0; -+#endif -+} -+ -+static inline int au_test_btrfs(struct super_block *sb __maybe_unused) -+{ -+#if IS_ENABLED(CONFIG_BTRFS_FS) -+ return sb->s_magic == BTRFS_SUPER_MAGIC; -+#else -+ return 0; -+#endif -+} -+ -+static inline int au_test_xenfs(struct super_block *sb __maybe_unused) -+{ -+#if IS_ENABLED(CONFIG_XENFS) -+ return sb->s_magic == XENFS_SUPER_MAGIC; -+#else -+ return 0; -+#endif -+} -+ -+static inline int au_test_debugfs(struct super_block *sb __maybe_unused) -+{ -+#ifdef CONFIG_DEBUG_FS -+ return sb->s_magic == DEBUGFS_MAGIC; -+#else -+ return 0; -+#endif -+} -+ -+static inline int au_test_nilfs(struct super_block *sb __maybe_unused) -+{ -+#if IS_ENABLED(CONFIG_NILFS) -+ return sb->s_magic == NILFS_SUPER_MAGIC; -+#else -+ return 0; -+#endif -+} -+ -+static inline int au_test_hfsplus(struct super_block *sb __maybe_unused) -+{ -+#if IS_ENABLED(CONFIG_HFSPLUS_FS) -+ return sb->s_magic == HFSPLUS_SUPER_MAGIC; -+#else -+ return 0; -+#endif -+} -+ -+/* ---------------------------------------------------------------------- */ -+/* -+ * they can't be an aufs branch. -+ */ -+static inline int au_test_fs_unsuppoted(struct super_block *sb) -+{ -+ return -+#ifndef CONFIG_AUFS_BR_RAMFS -+ au_test_ramfs(sb) || -+#endif -+ au_test_procfs(sb) -+ || au_test_sysfs(sb) -+ || au_test_configfs(sb) -+ || au_test_debugfs(sb) -+ || au_test_securityfs(sb) -+ || au_test_xenfs(sb) -+ || au_test_ecryptfs(sb) -+ /* || !strcmp(au_sbtype(sb), "unionfs") */ -+ || au_test_aufs(sb); /* will be supported in next version */ -+} -+ -+static inline int au_test_fs_remote(struct super_block *sb) -+{ -+ return !au_test_tmpfs(sb) -+#ifdef CONFIG_AUFS_BR_RAMFS -+ && !au_test_ramfs(sb) -+#endif -+ && !(sb->s_type->fs_flags & FS_REQUIRES_DEV); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * Note: these functions (below) are created after reading ->getattr() in all -+ * filesystems under linux/fs. it means we have to do so in every update... -+ */ -+ -+/* -+ * some filesystems require getattr to refresh the inode attributes before -+ * referencing. -+ * in most cases, we can rely on the inode attribute in NFS (or every remote fs) -+ * and leave the work for d_revalidate() -+ */ -+static inline int au_test_fs_refresh_iattr(struct super_block *sb) -+{ -+ return au_test_nfs(sb) -+ || au_test_fuse(sb) -+ /* || au_test_btrfs(sb) */ /* untested */ -+ ; -+} -+ -+/* -+ * filesystems which don't maintain i_size or i_blocks. -+ */ -+static inline int au_test_fs_bad_iattr_size(struct super_block *sb) -+{ -+ return au_test_xfs(sb) -+ || au_test_btrfs(sb) -+ || au_test_ubifs(sb) -+ || au_test_hfsplus(sb) /* maintained, but incorrect */ -+ /* || au_test_minix(sb) */ /* untested */ -+ ; -+} -+ -+/* -+ * filesystems which don't store the correct value in some of their inode -+ * attributes. -+ */ -+static inline int au_test_fs_bad_iattr(struct super_block *sb) -+{ -+ return au_test_fs_bad_iattr_size(sb) -+ || au_test_fat(sb) -+ || au_test_msdos(sb) -+ || au_test_vfat(sb); -+} -+ -+/* they don't check i_nlink in link(2) */ -+static inline int au_test_fs_no_limit_nlink(struct super_block *sb) -+{ -+ return au_test_tmpfs(sb) -+#ifdef CONFIG_AUFS_BR_RAMFS -+ || au_test_ramfs(sb) -+#endif -+ || au_test_ubifs(sb) -+ || au_test_hfsplus(sb); -+} -+ -+/* -+ * filesystems which sets S_NOATIME and S_NOCMTIME. -+ */ -+static inline int au_test_fs_notime(struct super_block *sb) -+{ -+ return au_test_nfs(sb) -+ || au_test_fuse(sb) -+ || au_test_ubifs(sb) -+ ; -+} -+ -+/* temporary support for i#1 in cramfs */ -+static inline int au_test_fs_unique_ino(struct inode *inode) -+{ -+ if (au_test_cramfs(inode->i_sb)) -+ return inode->i_ino != 1; -+ return 1; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * the filesystem where the xino files placed must support i/o after unlink and -+ * maintain i_size and i_blocks. -+ */ -+static inline int au_test_fs_bad_xino(struct super_block *sb) -+{ -+ return au_test_fs_remote(sb) -+ || au_test_fs_bad_iattr_size(sb) -+ /* don't want unnecessary work for xino */ -+ || au_test_aufs(sb) -+ || au_test_ecryptfs(sb) -+ || au_test_nilfs(sb); -+} -+ -+static inline int au_test_fs_trunc_xino(struct super_block *sb) -+{ -+ return au_test_tmpfs(sb) -+ || au_test_ramfs(sb); -+} -+ -+/* -+ * test if the @sb is real-readonly. -+ */ -+static inline int au_test_fs_rr(struct super_block *sb) -+{ -+ return au_test_squashfs(sb) -+ || au_test_iso9660(sb) -+ || au_test_cramfs(sb) -+ || au_test_romfs(sb); -+} -+ -+/* -+ * test if the @inode is nfs with 'noacl' option -+ * NFS always sets SB_POSIXACL regardless its mount option 'noacl.' -+ */ -+static inline int au_test_nfs_noacl(struct inode *inode) -+{ -+ return au_test_nfs(inode->i_sb) -+ /* && IS_POSIXACL(inode) */ -+ && !nfs_server_capable(inode, NFS_CAP_ACLS); -+} -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_FSTYPE_H__ */ -diff -Nurp linux-5.6.3/fs/aufs/hbl.h linux-5.6.3-aufs/fs/aufs/hbl.h ---- linux-5.6.3/fs/aufs/hbl.h 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/hbl.h 2020-04-10 12:40:52.190049409 +0300 -@@ -0,0 +1,52 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2017-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * helpers for hlist_bl.h -+ */ -+ -+#ifndef __AUFS_HBL_H__ -+#define __AUFS_HBL_H__ -+ -+#ifdef __KERNEL__ -+ -+#include -+ -+static inline void au_hbl_add(struct hlist_bl_node *node, -+ struct hlist_bl_head *hbl) -+{ -+ hlist_bl_lock(hbl); -+ hlist_bl_add_head(node, hbl); -+ hlist_bl_unlock(hbl); -+} -+ -+static inline void au_hbl_del(struct hlist_bl_node *node, -+ struct hlist_bl_head *hbl) -+{ -+ hlist_bl_lock(hbl); -+ hlist_bl_del(node); -+ hlist_bl_unlock(hbl); -+} -+ -+#define au_hbl_for_each(pos, head) \ -+ for (pos = hlist_bl_first(head); \ -+ pos; \ -+ pos = pos->next) -+ -+static inline unsigned long au_hbl_count(struct hlist_bl_head *hbl) -+{ -+ unsigned long cnt; -+ struct hlist_bl_node *pos; -+ -+ cnt = 0; -+ hlist_bl_lock(hbl); -+ au_hbl_for_each(pos, hbl) -+ cnt++; -+ hlist_bl_unlock(hbl); -+ return cnt; -+} -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_HBL_H__ */ -diff -Nurp linux-5.6.3/fs/aufs/hfsnotify.c linux-5.6.3-aufs/fs/aufs/hfsnotify.c ---- linux-5.6.3/fs/aufs/hfsnotify.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/hfsnotify.c 2020-04-10 12:40:52.190049409 +0300 -@@ -0,0 +1,275 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * fsnotify for the lower directories -+ */ -+ -+#include "aufs.h" -+ -+/* FS_IN_IGNORED is unnecessary */ -+static const __u32 AuHfsnMask = (FS_MOVED_TO | FS_MOVED_FROM | FS_DELETE -+ | FS_CREATE | FS_EVENT_ON_CHILD); -+static DECLARE_WAIT_QUEUE_HEAD(au_hfsn_wq); -+static __cacheline_aligned_in_smp atomic64_t au_hfsn_ifree = ATOMIC64_INIT(0); -+ -+static void au_hfsn_free_mark(struct fsnotify_mark *mark) -+{ -+ struct au_hnotify *hn = container_of(mark, struct au_hnotify, -+ hn_mark); -+ /* AuDbg("here\n"); */ -+ au_cache_free_hnotify(hn); -+ smp_mb__before_atomic(); /* for atomic64_dec */ -+ if (atomic64_dec_and_test(&au_hfsn_ifree)) -+ wake_up(&au_hfsn_wq); -+} -+ -+static int au_hfsn_alloc(struct au_hinode *hinode) -+{ -+ int err; -+ struct au_hnotify *hn; -+ struct super_block *sb; -+ struct au_branch *br; -+ struct fsnotify_mark *mark; -+ aufs_bindex_t bindex; -+ -+ hn = hinode->hi_notify; -+ sb = hn->hn_aufs_inode->i_sb; -+ bindex = au_br_index(sb, hinode->hi_id); -+ br = au_sbr(sb, bindex); -+ AuDebugOn(!br->br_hfsn); -+ -+ mark = &hn->hn_mark; -+ fsnotify_init_mark(mark, br->br_hfsn->hfsn_group); -+ mark->mask = AuHfsnMask; -+ /* -+ * by udba rename or rmdir, aufs assign a new inode to the known -+ * h_inode, so specify 1 to allow dups. -+ */ -+ lockdep_off(); -+ err = fsnotify_add_inode_mark(mark, hinode->hi_inode, /*allow_dups*/1); -+ lockdep_on(); -+ -+ return err; -+} -+ -+static int au_hfsn_free(struct au_hinode *hinode, struct au_hnotify *hn) -+{ -+ struct fsnotify_mark *mark; -+ unsigned long long ull; -+ struct fsnotify_group *group; -+ -+ ull = atomic64_inc_return(&au_hfsn_ifree); -+ BUG_ON(!ull); -+ -+ mark = &hn->hn_mark; -+ spin_lock(&mark->lock); -+ group = mark->group; -+ fsnotify_get_group(group); -+ spin_unlock(&mark->lock); -+ lockdep_off(); -+ fsnotify_destroy_mark(mark, group); -+ fsnotify_put_mark(mark); -+ fsnotify_put_group(group); -+ lockdep_on(); -+ -+ /* free hn by myself */ -+ return 0; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static void au_hfsn_ctl(struct au_hinode *hinode, int do_set) -+{ -+ struct fsnotify_mark *mark; -+ -+ mark = &hinode->hi_notify->hn_mark; -+ spin_lock(&mark->lock); -+ if (do_set) { -+ AuDebugOn(mark->mask & AuHfsnMask); -+ mark->mask |= AuHfsnMask; -+ } else { -+ AuDebugOn(!(mark->mask & AuHfsnMask)); -+ mark->mask &= ~AuHfsnMask; -+ } -+ spin_unlock(&mark->lock); -+ /* fsnotify_recalc_inode_mask(hinode->hi_inode); */ -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* #define AuDbgHnotify */ -+#ifdef AuDbgHnotify -+static char *au_hfsn_name(u32 mask) -+{ -+#ifdef CONFIG_AUFS_DEBUG -+#define test_ret(flag) \ -+ do { \ -+ if (mask & flag) \ -+ return #flag; \ -+ } while (0) -+ test_ret(FS_ACCESS); -+ test_ret(FS_MODIFY); -+ test_ret(FS_ATTRIB); -+ test_ret(FS_CLOSE_WRITE); -+ test_ret(FS_CLOSE_NOWRITE); -+ test_ret(FS_OPEN); -+ test_ret(FS_MOVED_FROM); -+ test_ret(FS_MOVED_TO); -+ test_ret(FS_CREATE); -+ test_ret(FS_DELETE); -+ test_ret(FS_DELETE_SELF); -+ test_ret(FS_MOVE_SELF); -+ test_ret(FS_UNMOUNT); -+ test_ret(FS_Q_OVERFLOW); -+ test_ret(FS_IN_IGNORED); -+ test_ret(FS_ISDIR); -+ test_ret(FS_IN_ONESHOT); -+ test_ret(FS_EVENT_ON_CHILD); -+ return ""; -+#undef test_ret -+#else -+ return "??"; -+#endif -+} -+#endif -+ -+/* ---------------------------------------------------------------------- */ -+ -+static void au_hfsn_free_group(struct fsnotify_group *group) -+{ -+ struct au_br_hfsnotify *hfsn = group->private; -+ -+ /* AuDbg("here\n"); */ -+ au_kfree_try_rcu(hfsn); -+} -+ -+static int au_hfsn_handle_event(struct fsnotify_group *group, -+ struct inode *inode, -+ u32 mask, const void *data, int data_type, -+ const struct qstr *file_name, u32 cookie, -+ struct fsnotify_iter_info *iter_info) -+{ -+ int err; -+ struct au_hnotify *hnotify; -+ struct inode *h_dir, *h_inode; -+ struct fsnotify_mark *inode_mark; -+ -+ AuDebugOn(data_type != FSNOTIFY_EVENT_INODE); -+ -+ err = 0; -+ /* if FS_UNMOUNT happens, there must be another bug */ -+ AuDebugOn(mask & FS_UNMOUNT); -+ if (mask & (FS_IN_IGNORED | FS_UNMOUNT)) -+ goto out; -+ -+ h_dir = inode; -+ h_inode = NULL; -+#ifdef AuDbgHnotify -+ au_debug_on(); -+ if (1 || h_child_qstr.len != sizeof(AUFS_XINO_FNAME) - 1 -+ || strncmp(h_child_qstr.name, AUFS_XINO_FNAME, h_child_qstr.len)) { -+ AuDbg("i%lu, mask 0x%x %s, hcname %.*s, hi%lu\n", -+ h_dir->i_ino, mask, au_hfsn_name(mask), -+ AuLNPair(&h_child_qstr), h_inode ? h_inode->i_ino : 0); -+ /* WARN_ON(1); */ -+ } -+ au_debug_off(); -+#endif -+ -+ inode_mark = fsnotify_iter_inode_mark(iter_info); -+ AuDebugOn(!inode_mark); -+ hnotify = container_of(inode_mark, struct au_hnotify, hn_mark); -+ err = au_hnotify(h_dir, hnotify, mask, file_name, h_inode); -+ -+out: -+ return err; -+} -+ -+static struct fsnotify_ops au_hfsn_ops = { -+ .handle_event = au_hfsn_handle_event, -+ .free_group_priv = au_hfsn_free_group, -+ .free_mark = au_hfsn_free_mark -+}; -+ -+/* ---------------------------------------------------------------------- */ -+ -+static void au_hfsn_fin_br(struct au_branch *br) -+{ -+ struct au_br_hfsnotify *hfsn; -+ -+ hfsn = br->br_hfsn; -+ if (hfsn) { -+ lockdep_off(); -+ fsnotify_put_group(hfsn->hfsn_group); -+ lockdep_on(); -+ } -+} -+ -+static int au_hfsn_init_br(struct au_branch *br, int perm) -+{ -+ int err; -+ struct fsnotify_group *group; -+ struct au_br_hfsnotify *hfsn; -+ -+ err = 0; -+ br->br_hfsn = NULL; -+ if (!au_br_hnotifyable(perm)) -+ goto out; -+ -+ err = -ENOMEM; -+ hfsn = kmalloc(sizeof(*hfsn), GFP_NOFS); -+ if (unlikely(!hfsn)) -+ goto out; -+ -+ err = 0; -+ group = fsnotify_alloc_group(&au_hfsn_ops); -+ if (IS_ERR(group)) { -+ err = PTR_ERR(group); -+ pr_err("fsnotify_alloc_group() failed, %d\n", err); -+ goto out_hfsn; -+ } -+ -+ group->private = hfsn; -+ hfsn->hfsn_group = group; -+ br->br_hfsn = hfsn; -+ goto out; /* success */ -+ -+out_hfsn: -+ au_kfree_try_rcu(hfsn); -+out: -+ return err; -+} -+ -+static int au_hfsn_reset_br(unsigned int udba, struct au_branch *br, int perm) -+{ -+ int err; -+ -+ err = 0; -+ if (!br->br_hfsn) -+ err = au_hfsn_init_br(br, perm); -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static void au_hfsn_fin(void) -+{ -+ AuDbg("au_hfsn_ifree %lld\n", (long long)atomic64_read(&au_hfsn_ifree)); -+ wait_event(au_hfsn_wq, !atomic64_read(&au_hfsn_ifree)); -+} -+ -+const struct au_hnotify_op au_hnotify_op = { -+ .ctl = au_hfsn_ctl, -+ .alloc = au_hfsn_alloc, -+ .free = au_hfsn_free, -+ -+ .fin = au_hfsn_fin, -+ -+ .reset_br = au_hfsn_reset_br, -+ .fin_br = au_hfsn_fin_br, -+ .init_br = au_hfsn_init_br -+}; -diff -Nurp linux-5.6.3/fs/aufs/hfsplus.c linux-5.6.3-aufs/fs/aufs/hfsplus.c ---- linux-5.6.3/fs/aufs/hfsplus.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/hfsplus.c 2020-04-10 12:40:52.190049409 +0300 -@@ -0,0 +1,47 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2010-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * special support for filesystems which acquires an inode mutex -+ * at final closing a file, eg, hfsplus. -+ * -+ * This trick is very simple and stupid, just to open the file before really -+ * necessary open to tell hfsplus that this is not the final closing. -+ * The caller should call au_h_open_pre() after acquiring the inode mutex, -+ * and au_h_open_post() after releasing it. -+ */ -+ -+#include "aufs.h" -+ -+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex, -+ int force_wr) -+{ -+ struct file *h_file; -+ struct dentry *h_dentry; -+ -+ h_dentry = au_h_dptr(dentry, bindex); -+ AuDebugOn(!h_dentry); -+ AuDebugOn(d_is_negative(h_dentry)); -+ -+ h_file = NULL; -+ if (au_test_hfsplus(h_dentry->d_sb) -+ && d_is_reg(h_dentry)) -+ h_file = au_h_open(dentry, bindex, -+ O_RDONLY | O_NOATIME | O_LARGEFILE, -+ /*file*/NULL, force_wr); -+ return h_file; -+} -+ -+void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex, -+ struct file *h_file) -+{ -+ struct au_branch *br; -+ -+ if (h_file) { -+ fput(h_file); -+ br = au_sbr(dentry->d_sb, bindex); -+ au_lcnt_dec(&br->br_nfiles); -+ } -+} -diff -Nurp linux-5.6.3/fs/aufs/hnotify.c linux-5.6.3-aufs/fs/aufs/hnotify.c ---- linux-5.6.3/fs/aufs/hnotify.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/hnotify.c 2020-04-10 12:40:52.190049409 +0300 -@@ -0,0 +1,702 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * abstraction to notify the direct changes on lower directories -+ */ -+ -+/* #include */ -+#include "aufs.h" -+ -+int au_hn_alloc(struct au_hinode *hinode, struct inode *inode) -+{ -+ int err; -+ struct au_hnotify *hn; -+ -+ err = -ENOMEM; -+ hn = au_cache_alloc_hnotify(); -+ if (hn) { -+ hn->hn_aufs_inode = inode; -+ hinode->hi_notify = hn; -+ err = au_hnotify_op.alloc(hinode); -+ AuTraceErr(err); -+ if (unlikely(err)) { -+ hinode->hi_notify = NULL; -+ au_cache_free_hnotify(hn); -+ /* -+ * The upper dir was removed by udba, but the same named -+ * dir left. In this case, aufs assigns a new inode -+ * number and set the monitor again. -+ * For the lower dir, the old monitor is still left. -+ */ -+ if (err == -EEXIST) -+ err = 0; -+ } -+ } -+ -+ AuTraceErr(err); -+ return err; -+} -+ -+void au_hn_free(struct au_hinode *hinode) -+{ -+ struct au_hnotify *hn; -+ -+ hn = hinode->hi_notify; -+ if (hn) { -+ hinode->hi_notify = NULL; -+ if (au_hnotify_op.free(hinode, hn)) -+ au_cache_free_hnotify(hn); -+ } -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+void au_hn_ctl(struct au_hinode *hinode, int do_set) -+{ -+ if (hinode->hi_notify) -+ au_hnotify_op.ctl(hinode, do_set); -+} -+ -+void au_hn_reset(struct inode *inode, unsigned int flags) -+{ -+ aufs_bindex_t bindex, bbot; -+ struct inode *hi; -+ struct dentry *iwhdentry; -+ -+ bbot = au_ibbot(inode); -+ for (bindex = au_ibtop(inode); bindex <= bbot; bindex++) { -+ hi = au_h_iptr(inode, bindex); -+ if (!hi) -+ continue; -+ -+ /* inode_lock_nested(hi, AuLsc_I_CHILD); */ -+ iwhdentry = au_hi_wh(inode, bindex); -+ if (iwhdentry) -+ dget(iwhdentry); -+ au_igrab(hi); -+ au_set_h_iptr(inode, bindex, NULL, 0); -+ au_set_h_iptr(inode, bindex, au_igrab(hi), -+ flags & ~AuHi_XINO); -+ iput(hi); -+ dput(iwhdentry); -+ /* inode_unlock(hi); */ -+ } -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int hn_xino(struct inode *inode, struct inode *h_inode) -+{ -+ int err; -+ aufs_bindex_t bindex, bbot, bfound, btop; -+ struct inode *h_i; -+ -+ err = 0; -+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) { -+ pr_warn("branch root dir was changed\n"); -+ goto out; -+ } -+ -+ bfound = -1; -+ bbot = au_ibbot(inode); -+ btop = au_ibtop(inode); -+#if 0 /* reserved for future use */ -+ if (bindex == bbot) { -+ /* keep this ino in rename case */ -+ goto out; -+ } -+#endif -+ for (bindex = btop; bindex <= bbot; bindex++) -+ if (au_h_iptr(inode, bindex) == h_inode) { -+ bfound = bindex; -+ break; -+ } -+ if (bfound < 0) -+ goto out; -+ -+ for (bindex = btop; bindex <= bbot; bindex++) { -+ h_i = au_h_iptr(inode, bindex); -+ if (!h_i) -+ continue; -+ -+ err = au_xino_write(inode->i_sb, bindex, h_i->i_ino, /*ino*/0); -+ /* ignore this error */ -+ /* bad action? */ -+ } -+ -+ /* children inode number will be broken */ -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+static int hn_gen_tree(struct dentry *dentry) -+{ -+ int err, i, j, ndentry; -+ struct au_dcsub_pages dpages; -+ struct au_dpage *dpage; -+ struct dentry **dentries; -+ -+ err = au_dpages_init(&dpages, GFP_NOFS); -+ if (unlikely(err)) -+ goto out; -+ err = au_dcsub_pages(&dpages, dentry, NULL, NULL); -+ if (unlikely(err)) -+ goto out_dpages; -+ -+ for (i = 0; i < dpages.ndpage; i++) { -+ dpage = dpages.dpages + i; -+ dentries = dpage->dentries; -+ ndentry = dpage->ndentry; -+ for (j = 0; j < ndentry; j++) { -+ struct dentry *d; -+ -+ d = dentries[j]; -+ if (IS_ROOT(d)) -+ continue; -+ -+ au_digen_dec(d); -+ if (d_really_is_positive(d)) -+ /* todo: reset children xino? -+ cached children only? */ -+ au_iigen_dec(d_inode(d)); -+ } -+ } -+ -+out_dpages: -+ au_dpages_free(&dpages); -+out: -+ return err; -+} -+ -+/* -+ * return 0 if processed. -+ */ -+static int hn_gen_by_inode(char *name, unsigned int nlen, struct inode *inode, -+ const unsigned int isdir) -+{ -+ int err; -+ struct dentry *d; -+ struct qstr *dname; -+ -+ err = 1; -+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) { -+ pr_warn("branch root dir was changed\n"); -+ err = 0; -+ goto out; -+ } -+ -+ if (!isdir) { -+ AuDebugOn(!name); -+ au_iigen_dec(inode); -+ spin_lock(&inode->i_lock); -+ hlist_for_each_entry(d, &inode->i_dentry, d_u.d_alias) { -+ spin_lock(&d->d_lock); -+ dname = &d->d_name; -+ if (dname->len != nlen -+ && memcmp(dname->name, name, nlen)) { -+ spin_unlock(&d->d_lock); -+ continue; -+ } -+ err = 0; -+ au_digen_dec(d); -+ spin_unlock(&d->d_lock); -+ break; -+ } -+ spin_unlock(&inode->i_lock); -+ } else { -+ au_fset_si(au_sbi(inode->i_sb), FAILED_REFRESH_DIR); -+ d = d_find_any_alias(inode); -+ if (!d) { -+ au_iigen_dec(inode); -+ goto out; -+ } -+ -+ spin_lock(&d->d_lock); -+ dname = &d->d_name; -+ if (dname->len == nlen && !memcmp(dname->name, name, nlen)) { -+ spin_unlock(&d->d_lock); -+ err = hn_gen_tree(d); -+ spin_lock(&d->d_lock); -+ } -+ spin_unlock(&d->d_lock); -+ dput(d); -+ } -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+static int hn_gen_by_name(struct dentry *dentry, const unsigned int isdir) -+{ -+ int err; -+ -+ if (IS_ROOT(dentry)) { -+ pr_warn("branch root dir was changed\n"); -+ return 0; -+ } -+ -+ err = 0; -+ if (!isdir) { -+ au_digen_dec(dentry); -+ if (d_really_is_positive(dentry)) -+ au_iigen_dec(d_inode(dentry)); -+ } else { -+ au_fset_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIR); -+ if (d_really_is_positive(dentry)) -+ err = hn_gen_tree(dentry); -+ } -+ -+ AuTraceErr(err); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* hnotify job flags */ -+#define AuHnJob_XINO0 1 -+#define AuHnJob_GEN (1 << 1) -+#define AuHnJob_DIRENT (1 << 2) -+#define AuHnJob_ISDIR (1 << 3) -+#define AuHnJob_TRYXINO0 (1 << 4) -+#define AuHnJob_MNTPNT (1 << 5) -+#define au_ftest_hnjob(flags, name) ((flags) & AuHnJob_##name) -+#define au_fset_hnjob(flags, name) \ -+ do { (flags) |= AuHnJob_##name; } while (0) -+#define au_fclr_hnjob(flags, name) \ -+ do { (flags) &= ~AuHnJob_##name; } while (0) -+ -+enum { -+ AuHn_CHILD, -+ AuHn_PARENT, -+ AuHnLast -+}; -+ -+struct au_hnotify_args { -+ struct inode *h_dir, *dir, *h_child_inode; -+ u32 mask; -+ unsigned int flags[AuHnLast]; -+ unsigned int h_child_nlen; -+ char h_child_name[]; -+}; -+ -+struct hn_job_args { -+ unsigned int flags; -+ struct inode *inode, *h_inode, *dir, *h_dir; -+ struct dentry *dentry; -+ char *h_name; -+ int h_nlen; -+}; -+ -+static int hn_job(struct hn_job_args *a) -+{ -+ const unsigned int isdir = au_ftest_hnjob(a->flags, ISDIR); -+ int e; -+ -+ /* reset xino */ -+ if (au_ftest_hnjob(a->flags, XINO0) && a->inode) -+ hn_xino(a->inode, a->h_inode); /* ignore this error */ -+ -+ if (au_ftest_hnjob(a->flags, TRYXINO0) -+ && a->inode -+ && a->h_inode) { -+ inode_lock_shared_nested(a->h_inode, AuLsc_I_CHILD); -+ if (!a->h_inode->i_nlink -+ && !(a->h_inode->i_state & I_LINKABLE)) -+ hn_xino(a->inode, a->h_inode); /* ignore this error */ -+ inode_unlock_shared(a->h_inode); -+ } -+ -+ /* make the generation obsolete */ -+ if (au_ftest_hnjob(a->flags, GEN)) { -+ e = -1; -+ if (a->inode) -+ e = hn_gen_by_inode(a->h_name, a->h_nlen, a->inode, -+ isdir); -+ if (e && a->dentry) -+ hn_gen_by_name(a->dentry, isdir); -+ /* ignore this error */ -+ } -+ -+ /* make dir entries obsolete */ -+ if (au_ftest_hnjob(a->flags, DIRENT) && a->inode) { -+ struct au_vdir *vdir; -+ -+ vdir = au_ivdir(a->inode); -+ if (vdir) -+ vdir->vd_jiffy = 0; -+ /* IMustLock(a->inode); */ -+ /* inode_inc_iversion(a->inode); */ -+ } -+ -+ /* can do nothing but warn */ -+ if (au_ftest_hnjob(a->flags, MNTPNT) -+ && a->dentry -+ && d_mountpoint(a->dentry)) -+ pr_warn("mount-point %pd is removed or renamed\n", a->dentry); -+ -+ return 0; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static struct dentry *lookup_wlock_by_name(char *name, unsigned int nlen, -+ struct inode *dir) -+{ -+ struct dentry *dentry, *d, *parent; -+ struct qstr *dname; -+ -+ parent = d_find_any_alias(dir); -+ if (!parent) -+ return NULL; -+ -+ dentry = NULL; -+ spin_lock(&parent->d_lock); -+ list_for_each_entry(d, &parent->d_subdirs, d_child) { -+ /* AuDbg("%pd\n", d); */ -+ spin_lock_nested(&d->d_lock, DENTRY_D_LOCK_NESTED); -+ dname = &d->d_name; -+ if (dname->len != nlen || memcmp(dname->name, name, nlen)) -+ goto cont_unlock; -+ if (au_di(d)) -+ au_digen_dec(d); -+ else -+ goto cont_unlock; -+ if (au_dcount(d) > 0) { -+ dentry = dget_dlock(d); -+ spin_unlock(&d->d_lock); -+ break; -+ } -+ -+cont_unlock: -+ spin_unlock(&d->d_lock); -+ } -+ spin_unlock(&parent->d_lock); -+ dput(parent); -+ -+ if (dentry) -+ di_write_lock_child(dentry); -+ -+ return dentry; -+} -+ -+static struct inode *lookup_wlock_by_ino(struct super_block *sb, -+ aufs_bindex_t bindex, ino_t h_ino) -+{ -+ struct inode *inode; -+ ino_t ino; -+ int err; -+ -+ inode = NULL; -+ err = au_xino_read(sb, bindex, h_ino, &ino); -+ if (!err && ino) -+ inode = ilookup(sb, ino); -+ if (!inode) -+ goto out; -+ -+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) { -+ pr_warn("wrong root branch\n"); -+ iput(inode); -+ inode = NULL; -+ goto out; -+ } -+ -+ ii_write_lock_child(inode); -+ -+out: -+ return inode; -+} -+ -+static void au_hn_bh(void *_args) -+{ -+ struct au_hnotify_args *a = _args; -+ struct super_block *sb; -+ aufs_bindex_t bindex, bbot, bfound; -+ unsigned char xino, try_iput; -+ int err; -+ struct inode *inode; -+ ino_t h_ino; -+ struct hn_job_args args; -+ struct dentry *dentry; -+ struct au_sbinfo *sbinfo; -+ -+ AuDebugOn(!_args); -+ AuDebugOn(!a->h_dir); -+ AuDebugOn(!a->dir); -+ AuDebugOn(!a->mask); -+ AuDbg("mask 0x%x, i%lu, hi%lu, hci%lu\n", -+ a->mask, a->dir->i_ino, a->h_dir->i_ino, -+ a->h_child_inode ? a->h_child_inode->i_ino : 0); -+ -+ inode = NULL; -+ dentry = NULL; -+ /* -+ * do not lock a->dir->i_mutex here -+ * because of d_revalidate() may cause a deadlock. -+ */ -+ sb = a->dir->i_sb; -+ AuDebugOn(!sb); -+ sbinfo = au_sbi(sb); -+ AuDebugOn(!sbinfo); -+ si_write_lock(sb, AuLock_NOPLMW); -+ -+ if (au_opt_test(sbinfo->si_mntflags, DIRREN)) -+ switch (a->mask & FS_EVENTS_POSS_ON_CHILD) { -+ case FS_MOVED_FROM: -+ case FS_MOVED_TO: -+ AuWarn1("DIRREN with UDBA may not work correctly " -+ "for the direct rename(2)\n"); -+ } -+ -+ ii_read_lock_parent(a->dir); -+ bfound = -1; -+ bbot = au_ibbot(a->dir); -+ for (bindex = au_ibtop(a->dir); bindex <= bbot; bindex++) -+ if (au_h_iptr(a->dir, bindex) == a->h_dir) { -+ bfound = bindex; -+ break; -+ } -+ ii_read_unlock(a->dir); -+ if (unlikely(bfound < 0)) -+ goto out; -+ -+ xino = !!au_opt_test(au_mntflags(sb), XINO); -+ h_ino = 0; -+ if (a->h_child_inode) -+ h_ino = a->h_child_inode->i_ino; -+ -+ if (a->h_child_nlen -+ && (au_ftest_hnjob(a->flags[AuHn_CHILD], GEN) -+ || au_ftest_hnjob(a->flags[AuHn_CHILD], MNTPNT))) -+ dentry = lookup_wlock_by_name(a->h_child_name, a->h_child_nlen, -+ a->dir); -+ try_iput = 0; -+ if (dentry && d_really_is_positive(dentry)) -+ inode = d_inode(dentry); -+ if (xino && !inode && h_ino -+ && (au_ftest_hnjob(a->flags[AuHn_CHILD], XINO0) -+ || au_ftest_hnjob(a->flags[AuHn_CHILD], TRYXINO0) -+ || au_ftest_hnjob(a->flags[AuHn_CHILD], GEN))) { -+ inode = lookup_wlock_by_ino(sb, bfound, h_ino); -+ try_iput = 1; -+ } -+ -+ args.flags = a->flags[AuHn_CHILD]; -+ args.dentry = dentry; -+ args.inode = inode; -+ args.h_inode = a->h_child_inode; -+ args.dir = a->dir; -+ args.h_dir = a->h_dir; -+ args.h_name = a->h_child_name; -+ args.h_nlen = a->h_child_nlen; -+ err = hn_job(&args); -+ if (dentry) { -+ if (au_di(dentry)) -+ di_write_unlock(dentry); -+ dput(dentry); -+ } -+ if (inode && try_iput) { -+ ii_write_unlock(inode); -+ iput(inode); -+ } -+ -+ ii_write_lock_parent(a->dir); -+ args.flags = a->flags[AuHn_PARENT]; -+ args.dentry = NULL; -+ args.inode = a->dir; -+ args.h_inode = a->h_dir; -+ args.dir = NULL; -+ args.h_dir = NULL; -+ args.h_name = NULL; -+ args.h_nlen = 0; -+ err = hn_job(&args); -+ ii_write_unlock(a->dir); -+ -+out: -+ iput(a->h_child_inode); -+ iput(a->h_dir); -+ iput(a->dir); -+ si_write_unlock(sb); -+ au_nwt_done(&sbinfo->si_nowait); -+ au_kfree_rcu(a); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+int au_hnotify(struct inode *h_dir, struct au_hnotify *hnotify, u32 mask, -+ const struct qstr *h_child_qstr, struct inode *h_child_inode) -+{ -+ int err, len; -+ unsigned int flags[AuHnLast], f; -+ unsigned char isdir, isroot, wh; -+ struct inode *dir; -+ struct au_hnotify_args *args; -+ char *p, *h_child_name; -+ -+ err = 0; -+ AuDebugOn(!hnotify || !hnotify->hn_aufs_inode); -+ dir = igrab(hnotify->hn_aufs_inode); -+ if (!dir) -+ goto out; -+ -+ isroot = (dir->i_ino == AUFS_ROOT_INO); -+ wh = 0; -+ h_child_name = (void *)h_child_qstr->name; -+ len = h_child_qstr->len; -+ if (h_child_name) { -+ if (len > AUFS_WH_PFX_LEN -+ && !memcmp(h_child_name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) { -+ h_child_name += AUFS_WH_PFX_LEN; -+ len -= AUFS_WH_PFX_LEN; -+ wh = 1; -+ } -+ } -+ -+ isdir = 0; -+ if (h_child_inode) -+ isdir = !!S_ISDIR(h_child_inode->i_mode); -+ flags[AuHn_PARENT] = AuHnJob_ISDIR; -+ flags[AuHn_CHILD] = 0; -+ if (isdir) -+ flags[AuHn_CHILD] = AuHnJob_ISDIR; -+ au_fset_hnjob(flags[AuHn_PARENT], DIRENT); -+ au_fset_hnjob(flags[AuHn_CHILD], GEN); -+ switch (mask & ALL_FSNOTIFY_DIRENT_EVENTS) { -+ case FS_MOVED_FROM: -+ case FS_MOVED_TO: -+ au_fset_hnjob(flags[AuHn_CHILD], XINO0); -+ au_fset_hnjob(flags[AuHn_CHILD], MNTPNT); -+ /*FALLTHROUGH*/ -+ case FS_CREATE: -+ AuDebugOn(!h_child_name); -+ break; -+ -+ case FS_DELETE: -+ /* -+ * aufs never be able to get this child inode. -+ * revalidation should be in d_revalidate() -+ * by checking i_nlink, i_generation or d_unhashed(). -+ */ -+ AuDebugOn(!h_child_name); -+ au_fset_hnjob(flags[AuHn_CHILD], TRYXINO0); -+ au_fset_hnjob(flags[AuHn_CHILD], MNTPNT); -+ break; -+ -+ default: -+ AuDebugOn(1); -+ } -+ -+ if (wh) -+ h_child_inode = NULL; -+ -+ err = -ENOMEM; -+ /* iput() and kfree() will be called in au_hnotify() */ -+ args = kmalloc(sizeof(*args) + len + 1, GFP_NOFS); -+ if (unlikely(!args)) { -+ AuErr1("no memory\n"); -+ iput(dir); -+ goto out; -+ } -+ args->flags[AuHn_PARENT] = flags[AuHn_PARENT]; -+ args->flags[AuHn_CHILD] = flags[AuHn_CHILD]; -+ args->mask = mask; -+ args->dir = dir; -+ args->h_dir = igrab(h_dir); -+ if (h_child_inode) -+ h_child_inode = igrab(h_child_inode); /* can be NULL */ -+ args->h_child_inode = h_child_inode; -+ args->h_child_nlen = len; -+ if (len) { -+ p = (void *)args; -+ p += sizeof(*args); -+ memcpy(p, h_child_name, len); -+ p[len] = 0; -+ } -+ -+ /* NFS fires the event for silly-renamed one from kworker */ -+ f = 0; -+ if (!dir->i_nlink -+ || (au_test_nfs(h_dir->i_sb) && (mask & FS_DELETE))) -+ f = AuWkq_NEST; -+ err = au_wkq_nowait(au_hn_bh, args, dir->i_sb, f); -+ if (unlikely(err)) { -+ pr_err("wkq %d\n", err); -+ iput(args->h_child_inode); -+ iput(args->h_dir); -+ iput(args->dir); -+ au_kfree_rcu(args); -+ } -+ -+out: -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+int au_hnotify_reset_br(unsigned int udba, struct au_branch *br, int perm) -+{ -+ int err; -+ -+ AuDebugOn(!(udba & AuOptMask_UDBA)); -+ -+ err = 0; -+ if (au_hnotify_op.reset_br) -+ err = au_hnotify_op.reset_br(udba, br, perm); -+ -+ return err; -+} -+ -+int au_hnotify_init_br(struct au_branch *br, int perm) -+{ -+ int err; -+ -+ err = 0; -+ if (au_hnotify_op.init_br) -+ err = au_hnotify_op.init_br(br, perm); -+ -+ return err; -+} -+ -+void au_hnotify_fin_br(struct au_branch *br) -+{ -+ if (au_hnotify_op.fin_br) -+ au_hnotify_op.fin_br(br); -+} -+ -+static void au_hn_destroy_cache(void) -+{ -+ kmem_cache_destroy(au_cache[AuCache_HNOTIFY]); -+ au_cache[AuCache_HNOTIFY] = NULL; -+} -+ -+int __init au_hnotify_init(void) -+{ -+ int err; -+ -+ err = -ENOMEM; -+ au_cache[AuCache_HNOTIFY] = AuCache(au_hnotify); -+ if (au_cache[AuCache_HNOTIFY]) { -+ err = 0; -+ if (au_hnotify_op.init) -+ err = au_hnotify_op.init(); -+ if (unlikely(err)) -+ au_hn_destroy_cache(); -+ } -+ AuTraceErr(err); -+ return err; -+} -+ -+void au_hnotify_fin(void) -+{ -+ if (au_hnotify_op.fin) -+ au_hnotify_op.fin(); -+ -+ /* cf. au_cache_fin() */ -+ if (au_cache[AuCache_HNOTIFY]) -+ au_hn_destroy_cache(); -+} -diff -Nurp linux-5.6.3/fs/aufs/iinfo.c linux-5.6.3-aufs/fs/aufs/iinfo.c ---- linux-5.6.3/fs/aufs/iinfo.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/iinfo.c 2020-04-10 12:40:52.191049456 +0300 -@@ -0,0 +1,273 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * inode private data -+ */ -+ -+#include "aufs.h" -+ -+struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex) -+{ -+ struct inode *h_inode; -+ struct au_hinode *hinode; -+ -+ IiMustAnyLock(inode); -+ -+ hinode = au_hinode(au_ii(inode), bindex); -+ h_inode = hinode->hi_inode; -+ AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0); -+ return h_inode; -+} -+ -+/* todo: hard/soft set? */ -+void au_hiput(struct au_hinode *hinode) -+{ -+ au_hn_free(hinode); -+ dput(hinode->hi_whdentry); -+ iput(hinode->hi_inode); -+} -+ -+unsigned int au_hi_flags(struct inode *inode, int isdir) -+{ -+ unsigned int flags; -+ const unsigned int mnt_flags = au_mntflags(inode->i_sb); -+ -+ flags = 0; -+ if (au_opt_test(mnt_flags, XINO)) -+ au_fset_hi(flags, XINO); -+ if (isdir && au_opt_test(mnt_flags, UDBA_HNOTIFY)) -+ au_fset_hi(flags, HNOTIFY); -+ return flags; -+} -+ -+void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex, -+ struct inode *h_inode, unsigned int flags) -+{ -+ struct au_hinode *hinode; -+ struct inode *hi; -+ struct au_iinfo *iinfo = au_ii(inode); -+ -+ IiMustWriteLock(inode); -+ -+ hinode = au_hinode(iinfo, bindex); -+ hi = hinode->hi_inode; -+ AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0); -+ -+ if (hi) -+ au_hiput(hinode); -+ hinode->hi_inode = h_inode; -+ if (h_inode) { -+ int err; -+ struct super_block *sb = inode->i_sb; -+ struct au_branch *br; -+ -+ AuDebugOn(inode->i_mode -+ && (h_inode->i_mode & S_IFMT) -+ != (inode->i_mode & S_IFMT)); -+ if (bindex == iinfo->ii_btop) -+ au_cpup_igen(inode, h_inode); -+ br = au_sbr(sb, bindex); -+ hinode->hi_id = br->br_id; -+ if (au_ftest_hi(flags, XINO)) { -+ err = au_xino_write(sb, bindex, h_inode->i_ino, -+ inode->i_ino); -+ if (unlikely(err)) -+ AuIOErr1("failed au_xino_write() %d\n", err); -+ } -+ -+ if (au_ftest_hi(flags, HNOTIFY) -+ && au_br_hnotifyable(br->br_perm)) { -+ err = au_hn_alloc(hinode, inode); -+ if (unlikely(err)) -+ AuIOErr1("au_hn_alloc() %d\n", err); -+ } -+ } -+} -+ -+void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex, -+ struct dentry *h_wh) -+{ -+ struct au_hinode *hinode; -+ -+ IiMustWriteLock(inode); -+ -+ hinode = au_hinode(au_ii(inode), bindex); -+ AuDebugOn(hinode->hi_whdentry); -+ hinode->hi_whdentry = h_wh; -+} -+ -+void au_update_iigen(struct inode *inode, int half) -+{ -+ struct au_iinfo *iinfo; -+ struct au_iigen *iigen; -+ unsigned int sigen; -+ -+ sigen = au_sigen(inode->i_sb); -+ iinfo = au_ii(inode); -+ iigen = &iinfo->ii_generation; -+ spin_lock(&iigen->ig_spin); -+ iigen->ig_generation = sigen; -+ if (half) -+ au_ig_fset(iigen->ig_flags, HALF_REFRESHED); -+ else -+ au_ig_fclr(iigen->ig_flags, HALF_REFRESHED); -+ spin_unlock(&iigen->ig_spin); -+} -+ -+/* it may be called at remount time, too */ -+void au_update_ibrange(struct inode *inode, int do_put_zero) -+{ -+ struct au_iinfo *iinfo; -+ aufs_bindex_t bindex, bbot; -+ -+ AuDebugOn(au_is_bad_inode(inode)); -+ IiMustWriteLock(inode); -+ -+ iinfo = au_ii(inode); -+ if (do_put_zero && iinfo->ii_btop >= 0) { -+ for (bindex = iinfo->ii_btop; bindex <= iinfo->ii_bbot; -+ bindex++) { -+ struct inode *h_i; -+ -+ h_i = au_hinode(iinfo, bindex)->hi_inode; -+ if (h_i -+ && !h_i->i_nlink -+ && !(h_i->i_state & I_LINKABLE)) -+ au_set_h_iptr(inode, bindex, NULL, 0); -+ } -+ } -+ -+ iinfo->ii_btop = -1; -+ iinfo->ii_bbot = -1; -+ bbot = au_sbbot(inode->i_sb); -+ for (bindex = 0; bindex <= bbot; bindex++) -+ if (au_hinode(iinfo, bindex)->hi_inode) { -+ iinfo->ii_btop = bindex; -+ break; -+ } -+ if (iinfo->ii_btop >= 0) -+ for (bindex = bbot; bindex >= iinfo->ii_btop; bindex--) -+ if (au_hinode(iinfo, bindex)->hi_inode) { -+ iinfo->ii_bbot = bindex; -+ break; -+ } -+ AuDebugOn(iinfo->ii_btop > iinfo->ii_bbot); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+void au_icntnr_init_once(void *_c) -+{ -+ struct au_icntnr *c = _c; -+ struct au_iinfo *iinfo = &c->iinfo; -+ -+ spin_lock_init(&iinfo->ii_generation.ig_spin); -+ au_rw_init(&iinfo->ii_rwsem); -+ inode_init_once(&c->vfs_inode); -+} -+ -+void au_hinode_init(struct au_hinode *hinode) -+{ -+ hinode->hi_inode = NULL; -+ hinode->hi_id = -1; -+ au_hn_init(hinode); -+ hinode->hi_whdentry = NULL; -+} -+ -+int au_iinfo_init(struct inode *inode) -+{ -+ struct au_iinfo *iinfo; -+ struct super_block *sb; -+ struct au_hinode *hi; -+ int nbr, i; -+ -+ sb = inode->i_sb; -+ iinfo = &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo); -+ nbr = au_sbbot(sb) + 1; -+ if (unlikely(nbr <= 0)) -+ nbr = 1; -+ hi = kmalloc_array(nbr, sizeof(*iinfo->ii_hinode), GFP_NOFS); -+ if (hi) { -+ au_lcnt_inc(&au_sbi(sb)->si_ninodes); -+ -+ iinfo->ii_hinode = hi; -+ for (i = 0; i < nbr; i++, hi++) -+ au_hinode_init(hi); -+ -+ iinfo->ii_generation.ig_generation = au_sigen(sb); -+ iinfo->ii_btop = -1; -+ iinfo->ii_bbot = -1; -+ iinfo->ii_vdir = NULL; -+ return 0; -+ } -+ return -ENOMEM; -+} -+ -+int au_hinode_realloc(struct au_iinfo *iinfo, int nbr, int may_shrink) -+{ -+ int err, i; -+ struct au_hinode *hip; -+ -+ AuRwMustWriteLock(&iinfo->ii_rwsem); -+ -+ err = -ENOMEM; -+ hip = au_krealloc(iinfo->ii_hinode, sizeof(*hip) * nbr, GFP_NOFS, -+ may_shrink); -+ if (hip) { -+ iinfo->ii_hinode = hip; -+ i = iinfo->ii_bbot + 1; -+ hip += i; -+ for (; i < nbr; i++, hip++) -+ au_hinode_init(hip); -+ err = 0; -+ } -+ -+ return err; -+} -+ -+void au_iinfo_fin(struct inode *inode) -+{ -+ struct au_iinfo *iinfo; -+ struct au_hinode *hi; -+ struct super_block *sb; -+ aufs_bindex_t bindex, bbot; -+ const unsigned char unlinked = !inode->i_nlink; -+ -+ AuDebugOn(au_is_bad_inode(inode)); -+ -+ sb = inode->i_sb; -+ au_lcnt_dec(&au_sbi(sb)->si_ninodes); -+ if (si_pid_test(sb)) -+ au_xino_delete_inode(inode, unlinked); -+ else { -+ /* -+ * it is safe to hide the dependency between sbinfo and -+ * sb->s_umount. -+ */ -+ lockdep_off(); -+ si_noflush_read_lock(sb); -+ au_xino_delete_inode(inode, unlinked); -+ si_read_unlock(sb); -+ lockdep_on(); -+ } -+ -+ iinfo = au_ii(inode); -+ if (iinfo->ii_vdir) -+ au_vdir_free(iinfo->ii_vdir); -+ -+ bindex = iinfo->ii_btop; -+ if (bindex >= 0) { -+ hi = au_hinode(iinfo, bindex); -+ bbot = iinfo->ii_bbot; -+ while (bindex++ <= bbot) { -+ if (hi->hi_inode) -+ au_hiput(hi); -+ hi++; -+ } -+ } -+ au_kfree_rcu(iinfo->ii_hinode); -+ AuRwDestroy(&iinfo->ii_rwsem); -+} -diff -Nurp linux-5.6.3/fs/aufs/inode.c linux-5.6.3-aufs/fs/aufs/inode.c ---- linux-5.6.3/fs/aufs/inode.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/inode.c 2020-04-10 12:40:52.191049456 +0300 -@@ -0,0 +1,516 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * inode functions -+ */ -+ -+#include -+#include "aufs.h" -+ -+struct inode *au_igrab(struct inode *inode) -+{ -+ if (inode) { -+ AuDebugOn(!atomic_read(&inode->i_count)); -+ ihold(inode); -+ } -+ return inode; -+} -+ -+static void au_refresh_hinode_attr(struct inode *inode, int do_version) -+{ -+ au_cpup_attr_all(inode, /*force*/0); -+ au_update_iigen(inode, /*half*/1); -+ if (do_version) -+ inode_inc_iversion(inode); -+} -+ -+static int au_ii_refresh(struct inode *inode, int *update) -+{ -+ int err, e, nbr; -+ umode_t type; -+ aufs_bindex_t bindex, new_bindex; -+ struct super_block *sb; -+ struct au_iinfo *iinfo; -+ struct au_hinode *p, *q, tmp; -+ -+ AuDebugOn(au_is_bad_inode(inode)); -+ IiMustWriteLock(inode); -+ -+ *update = 0; -+ sb = inode->i_sb; -+ nbr = au_sbbot(sb) + 1; -+ type = inode->i_mode & S_IFMT; -+ iinfo = au_ii(inode); -+ err = au_hinode_realloc(iinfo, nbr, /*may_shrink*/0); -+ if (unlikely(err)) -+ goto out; -+ -+ AuDebugOn(iinfo->ii_btop < 0); -+ p = au_hinode(iinfo, iinfo->ii_btop); -+ for (bindex = iinfo->ii_btop; bindex <= iinfo->ii_bbot; -+ bindex++, p++) { -+ if (!p->hi_inode) -+ continue; -+ -+ AuDebugOn(type != (p->hi_inode->i_mode & S_IFMT)); -+ new_bindex = au_br_index(sb, p->hi_id); -+ if (new_bindex == bindex) -+ continue; -+ -+ if (new_bindex < 0) { -+ *update = 1; -+ au_hiput(p); -+ p->hi_inode = NULL; -+ continue; -+ } -+ -+ if (new_bindex < iinfo->ii_btop) -+ iinfo->ii_btop = new_bindex; -+ if (iinfo->ii_bbot < new_bindex) -+ iinfo->ii_bbot = new_bindex; -+ /* swap two lower inode, and loop again */ -+ q = au_hinode(iinfo, new_bindex); -+ tmp = *q; -+ *q = *p; -+ *p = tmp; -+ if (tmp.hi_inode) { -+ bindex--; -+ p--; -+ } -+ } -+ au_update_ibrange(inode, /*do_put_zero*/0); -+ au_hinode_realloc(iinfo, nbr, /*may_shrink*/1); /* harmless if err */ -+ e = au_dy_irefresh(inode); -+ if (unlikely(e && !err)) -+ err = e; -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+void au_refresh_iop(struct inode *inode, int force_getattr) -+{ -+ int type; -+ struct au_sbinfo *sbi = au_sbi(inode->i_sb); -+ const struct inode_operations *iop -+ = force_getattr ? aufs_iop : sbi->si_iop_array; -+ -+ if (inode->i_op == iop) -+ return; -+ -+ switch (inode->i_mode & S_IFMT) { -+ case S_IFDIR: -+ type = AuIop_DIR; -+ break; -+ case S_IFLNK: -+ type = AuIop_SYMLINK; -+ break; -+ default: -+ type = AuIop_OTHER; -+ break; -+ } -+ -+ inode->i_op = iop + type; -+ /* unnecessary smp_wmb() */ -+} -+ -+int au_refresh_hinode_self(struct inode *inode) -+{ -+ int err, update; -+ -+ err = au_ii_refresh(inode, &update); -+ if (!err) -+ au_refresh_hinode_attr(inode, update && S_ISDIR(inode->i_mode)); -+ -+ AuTraceErr(err); -+ return err; -+} -+ -+int au_refresh_hinode(struct inode *inode, struct dentry *dentry) -+{ -+ int err, e, update; -+ unsigned int flags; -+ umode_t mode; -+ aufs_bindex_t bindex, bbot; -+ unsigned char isdir; -+ struct au_hinode *p; -+ struct au_iinfo *iinfo; -+ -+ err = au_ii_refresh(inode, &update); -+ if (unlikely(err)) -+ goto out; -+ -+ update = 0; -+ iinfo = au_ii(inode); -+ p = au_hinode(iinfo, iinfo->ii_btop); -+ mode = (inode->i_mode & S_IFMT); -+ isdir = S_ISDIR(mode); -+ flags = au_hi_flags(inode, isdir); -+ bbot = au_dbbot(dentry); -+ for (bindex = au_dbtop(dentry); bindex <= bbot; bindex++) { -+ struct inode *h_i, *h_inode; -+ struct dentry *h_d; -+ -+ h_d = au_h_dptr(dentry, bindex); -+ if (!h_d || d_is_negative(h_d)) -+ continue; -+ -+ h_inode = d_inode(h_d); -+ AuDebugOn(mode != (h_inode->i_mode & S_IFMT)); -+ if (iinfo->ii_btop <= bindex && bindex <= iinfo->ii_bbot) { -+ h_i = au_h_iptr(inode, bindex); -+ if (h_i) { -+ if (h_i == h_inode) -+ continue; -+ err = -EIO; -+ break; -+ } -+ } -+ if (bindex < iinfo->ii_btop) -+ iinfo->ii_btop = bindex; -+ if (iinfo->ii_bbot < bindex) -+ iinfo->ii_bbot = bindex; -+ au_set_h_iptr(inode, bindex, au_igrab(h_inode), flags); -+ update = 1; -+ } -+ au_update_ibrange(inode, /*do_put_zero*/0); -+ e = au_dy_irefresh(inode); -+ if (unlikely(e && !err)) -+ err = e; -+ if (!err) -+ au_refresh_hinode_attr(inode, update && isdir); -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+static int set_inode(struct inode *inode, struct dentry *dentry) -+{ -+ int err; -+ unsigned int flags; -+ umode_t mode; -+ aufs_bindex_t bindex, btop, btail; -+ unsigned char isdir; -+ struct dentry *h_dentry; -+ struct inode *h_inode; -+ struct au_iinfo *iinfo; -+ const struct inode_operations *iop; -+ -+ IiMustWriteLock(inode); -+ -+ err = 0; -+ isdir = 0; -+ iop = au_sbi(inode->i_sb)->si_iop_array; -+ btop = au_dbtop(dentry); -+ h_dentry = au_h_dptr(dentry, btop); -+ h_inode = d_inode(h_dentry); -+ mode = h_inode->i_mode; -+ switch (mode & S_IFMT) { -+ case S_IFREG: -+ btail = au_dbtail(dentry); -+ inode->i_op = iop + AuIop_OTHER; -+ inode->i_fop = &aufs_file_fop; -+ err = au_dy_iaop(inode, btop, h_inode); -+ if (unlikely(err)) -+ goto out; -+ break; -+ case S_IFDIR: -+ isdir = 1; -+ btail = au_dbtaildir(dentry); -+ inode->i_op = iop + AuIop_DIR; -+ inode->i_fop = &aufs_dir_fop; -+ break; -+ case S_IFLNK: -+ btail = au_dbtail(dentry); -+ inode->i_op = iop + AuIop_SYMLINK; -+ break; -+ case S_IFBLK: -+ case S_IFCHR: -+ case S_IFIFO: -+ case S_IFSOCK: -+ btail = au_dbtail(dentry); -+ inode->i_op = iop + AuIop_OTHER; -+ init_special_inode(inode, mode, h_inode->i_rdev); -+ break; -+ default: -+ AuIOErr("Unknown file type 0%o\n", mode); -+ err = -EIO; -+ goto out; -+ } -+ -+ /* do not set hnotify for whiteouted dirs (SHWH mode) */ -+ flags = au_hi_flags(inode, isdir); -+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH) -+ && au_ftest_hi(flags, HNOTIFY) -+ && dentry->d_name.len > AUFS_WH_PFX_LEN -+ && !memcmp(dentry->d_name.name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) -+ au_fclr_hi(flags, HNOTIFY); -+ iinfo = au_ii(inode); -+ iinfo->ii_btop = btop; -+ iinfo->ii_bbot = btail; -+ for (bindex = btop; bindex <= btail; bindex++) { -+ h_dentry = au_h_dptr(dentry, bindex); -+ if (h_dentry) -+ au_set_h_iptr(inode, bindex, -+ au_igrab(d_inode(h_dentry)), flags); -+ } -+ au_cpup_attr_all(inode, /*force*/1); -+ /* -+ * to force calling aufs_get_acl() every time, -+ * do not call cache_no_acl() for aufs inode. -+ */ -+ -+out: -+ return err; -+} -+ -+/* -+ * successful returns with iinfo write_locked -+ * minus: errno -+ * zero: success, matched -+ * plus: no error, but unmatched -+ */ -+static int reval_inode(struct inode *inode, struct dentry *dentry) -+{ -+ int err; -+ unsigned int gen, igflags; -+ aufs_bindex_t bindex, bbot; -+ struct inode *h_inode, *h_dinode; -+ struct dentry *h_dentry; -+ -+ /* -+ * before this function, if aufs got any iinfo lock, it must be only -+ * one, the parent dir. -+ * it can happen by UDBA and the obsoleted inode number. -+ */ -+ err = -EIO; -+ if (unlikely(inode->i_ino == parent_ino(dentry))) -+ goto out; -+ -+ err = 1; -+ ii_write_lock_new_child(inode); -+ h_dentry = au_h_dptr(dentry, au_dbtop(dentry)); -+ h_dinode = d_inode(h_dentry); -+ bbot = au_ibbot(inode); -+ for (bindex = au_ibtop(inode); bindex <= bbot; bindex++) { -+ h_inode = au_h_iptr(inode, bindex); -+ if (!h_inode || h_inode != h_dinode) -+ continue; -+ -+ err = 0; -+ gen = au_iigen(inode, &igflags); -+ if (gen == au_digen(dentry) -+ && !au_ig_ftest(igflags, HALF_REFRESHED)) -+ break; -+ -+ /* fully refresh inode using dentry */ -+ err = au_refresh_hinode(inode, dentry); -+ if (!err) -+ au_update_iigen(inode, /*half*/0); -+ break; -+ } -+ -+ if (unlikely(err)) -+ ii_write_unlock(inode); -+out: -+ return err; -+} -+ -+int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, -+ unsigned int d_type, ino_t *ino) -+{ -+ int err, idx; -+ const int isnondir = d_type != DT_DIR; -+ -+ /* prevent hardlinked inode number from race condition */ -+ if (isnondir) { -+ err = au_xinondir_enter(sb, bindex, h_ino, &idx); -+ if (unlikely(err)) -+ goto out; -+ } -+ -+ err = au_xino_read(sb, bindex, h_ino, ino); -+ if (unlikely(err)) -+ goto out_xinondir; -+ -+ if (!*ino) { -+ err = -EIO; -+ *ino = au_xino_new_ino(sb); -+ if (unlikely(!*ino)) -+ goto out_xinondir; -+ err = au_xino_write(sb, bindex, h_ino, *ino); -+ if (unlikely(err)) -+ goto out_xinondir; -+ } -+ -+out_xinondir: -+ if (isnondir && idx >= 0) -+ au_xinondir_leave(sb, bindex, h_ino, idx); -+out: -+ return err; -+} -+ -+/* successful returns with iinfo write_locked */ -+/* todo: return with unlocked? */ -+struct inode *au_new_inode(struct dentry *dentry, int must_new) -+{ -+ struct inode *inode, *h_inode; -+ struct dentry *h_dentry; -+ struct super_block *sb; -+ ino_t h_ino, ino; -+ int err, idx, hlinked; -+ aufs_bindex_t btop; -+ -+ sb = dentry->d_sb; -+ btop = au_dbtop(dentry); -+ h_dentry = au_h_dptr(dentry, btop); -+ h_inode = d_inode(h_dentry); -+ h_ino = h_inode->i_ino; -+ hlinked = !d_is_dir(h_dentry) && h_inode->i_nlink > 1; -+ -+new_ino: -+ /* -+ * stop 'race'-ing between hardlinks under different -+ * parents. -+ */ -+ if (hlinked) { -+ err = au_xinondir_enter(sb, btop, h_ino, &idx); -+ inode = ERR_PTR(err); -+ if (unlikely(err)) -+ goto out; -+ } -+ -+ err = au_xino_read(sb, btop, h_ino, &ino); -+ inode = ERR_PTR(err); -+ if (unlikely(err)) -+ goto out_xinondir; -+ -+ if (!ino) { -+ ino = au_xino_new_ino(sb); -+ if (unlikely(!ino)) { -+ inode = ERR_PTR(-EIO); -+ goto out_xinondir; -+ } -+ } -+ -+ AuDbg("i%lu\n", (unsigned long)ino); -+ inode = au_iget_locked(sb, ino); -+ err = PTR_ERR(inode); -+ if (IS_ERR(inode)) -+ goto out_xinondir; -+ -+ AuDbg("%lx, new %d\n", inode->i_state, !!(inode->i_state & I_NEW)); -+ if (inode->i_state & I_NEW) { -+ ii_write_lock_new_child(inode); -+ err = set_inode(inode, dentry); -+ if (!err) { -+ unlock_new_inode(inode); -+ goto out_xinondir; /* success */ -+ } -+ -+ /* -+ * iget_failed() calls iput(), but we need to call -+ * ii_write_unlock() after iget_failed(). so dirty hack for -+ * i_count. -+ */ -+ atomic_inc(&inode->i_count); -+ iget_failed(inode); -+ ii_write_unlock(inode); -+ au_xino_write(sb, btop, h_ino, /*ino*/0); -+ /* ignore this error */ -+ goto out_iput; -+ } else if (!must_new && !IS_DEADDIR(inode) && inode->i_nlink) { -+ /* -+ * horrible race condition between lookup, readdir and copyup -+ * (or something). -+ */ -+ if (hlinked && idx >= 0) -+ au_xinondir_leave(sb, btop, h_ino, idx); -+ err = reval_inode(inode, dentry); -+ if (unlikely(err < 0)) { -+ hlinked = 0; -+ goto out_iput; -+ } -+ if (!err) -+ goto out; /* success */ -+ else if (hlinked && idx >= 0) { -+ err = au_xinondir_enter(sb, btop, h_ino, &idx); -+ if (unlikely(err)) { -+ iput(inode); -+ inode = ERR_PTR(err); -+ goto out; -+ } -+ } -+ } -+ -+ if (unlikely(au_test_fs_unique_ino(h_inode))) -+ AuWarn1("Warning: Un-notified UDBA or repeatedly renamed dir," -+ " b%d, %s, %pd, hi%lu, i%lu.\n", -+ btop, au_sbtype(h_dentry->d_sb), dentry, -+ (unsigned long)h_ino, (unsigned long)ino); -+ ino = 0; -+ err = au_xino_write(sb, btop, h_ino, /*ino*/0); -+ if (!err) { -+ iput(inode); -+ if (hlinked && idx >= 0) -+ au_xinondir_leave(sb, btop, h_ino, idx); -+ goto new_ino; -+ } -+ -+out_iput: -+ iput(inode); -+ inode = ERR_PTR(err); -+out_xinondir: -+ if (hlinked && idx >= 0) -+ au_xinondir_leave(sb, btop, h_ino, idx); -+out: -+ return inode; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+int au_test_ro(struct super_block *sb, aufs_bindex_t bindex, -+ struct inode *inode) -+{ -+ int err; -+ struct inode *hi; -+ -+ err = au_br_rdonly(au_sbr(sb, bindex)); -+ -+ /* pseudo-link after flushed may happen out of bounds */ -+ if (!err -+ && inode -+ && au_ibtop(inode) <= bindex -+ && bindex <= au_ibbot(inode)) { -+ /* -+ * permission check is unnecessary since vfsub routine -+ * will be called later -+ */ -+ hi = au_h_iptr(inode, bindex); -+ if (hi) -+ err = IS_IMMUTABLE(hi) ? -EROFS : 0; -+ } -+ -+ return err; -+} -+ -+int au_test_h_perm(struct inode *h_inode, int mask) -+{ -+ if (uid_eq(current_fsuid(), GLOBAL_ROOT_UID)) -+ return 0; -+ return inode_permission(h_inode, mask); -+} -+ -+int au_test_h_perm_sio(struct inode *h_inode, int mask) -+{ -+ if (au_test_nfs(h_inode->i_sb) -+ && (mask & MAY_WRITE) -+ && S_ISDIR(h_inode->i_mode)) -+ mask |= MAY_READ; /* force permission check */ -+ return au_test_h_perm(h_inode, mask); -+} -diff -Nurp linux-5.6.3/fs/aufs/inode.h linux-5.6.3-aufs/fs/aufs/inode.h ---- linux-5.6.3/fs/aufs/inode.h 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/inode.h 2020-04-10 12:40:52.191049456 +0300 -@@ -0,0 +1,685 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * inode operations -+ */ -+ -+#ifndef __AUFS_INODE_H__ -+#define __AUFS_INODE_H__ -+ -+#ifdef __KERNEL__ -+ -+#include -+#include "rwsem.h" -+ -+struct vfsmount; -+ -+struct au_hnotify { -+#ifdef CONFIG_AUFS_HNOTIFY -+#ifdef CONFIG_AUFS_HFSNOTIFY -+ /* never use fsnotify_add_vfsmount_mark() */ -+ struct fsnotify_mark hn_mark; -+#endif -+ struct inode *hn_aufs_inode; /* no get/put */ -+ struct rcu_head rcu; -+#endif -+} ____cacheline_aligned_in_smp; -+ -+struct au_hinode { -+ struct inode *hi_inode; -+ aufs_bindex_t hi_id; -+#ifdef CONFIG_AUFS_HNOTIFY -+ struct au_hnotify *hi_notify; -+#endif -+ -+ /* reference to the copied-up whiteout with get/put */ -+ struct dentry *hi_whdentry; -+}; -+ -+/* ig_flags */ -+#define AuIG_HALF_REFRESHED 1 -+#define au_ig_ftest(flags, name) ((flags) & AuIG_##name) -+#define au_ig_fset(flags, name) \ -+ do { (flags) |= AuIG_##name; } while (0) -+#define au_ig_fclr(flags, name) \ -+ do { (flags) &= ~AuIG_##name; } while (0) -+ -+struct au_iigen { -+ spinlock_t ig_spin; -+ __u32 ig_generation, ig_flags; -+}; -+ -+struct au_vdir; -+struct au_iinfo { -+ struct au_iigen ii_generation; -+ struct super_block *ii_hsb1; /* no get/put */ -+ -+ struct au_rwsem ii_rwsem; -+ aufs_bindex_t ii_btop, ii_bbot; -+ __u32 ii_higen; -+ struct au_hinode *ii_hinode; -+ struct au_vdir *ii_vdir; -+}; -+ -+struct au_icntnr { -+ struct au_iinfo iinfo; -+ struct inode vfs_inode; -+ struct hlist_bl_node plink; -+ struct rcu_head rcu; -+} ____cacheline_aligned_in_smp; -+ -+/* au_pin flags */ -+#define AuPin_DI_LOCKED 1 -+#define AuPin_MNT_WRITE (1 << 1) -+#define au_ftest_pin(flags, name) ((flags) & AuPin_##name) -+#define au_fset_pin(flags, name) \ -+ do { (flags) |= AuPin_##name; } while (0) -+#define au_fclr_pin(flags, name) \ -+ do { (flags) &= ~AuPin_##name; } while (0) -+ -+struct au_pin { -+ /* input */ -+ struct dentry *dentry; -+ unsigned int udba; -+ unsigned char lsc_di, lsc_hi, flags; -+ aufs_bindex_t bindex; -+ -+ /* output */ -+ struct dentry *parent; -+ struct au_hinode *hdir; -+ struct vfsmount *h_mnt; -+ -+ /* temporary unlock/relock for copyup */ -+ struct dentry *h_dentry, *h_parent; -+ struct au_branch *br; -+ struct task_struct *task; -+}; -+ -+void au_pin_hdir_unlock(struct au_pin *p); -+int au_pin_hdir_lock(struct au_pin *p); -+int au_pin_hdir_relock(struct au_pin *p); -+void au_pin_hdir_acquire_nest(struct au_pin *p); -+void au_pin_hdir_release(struct au_pin *p); -+ -+/* ---------------------------------------------------------------------- */ -+ -+static inline struct au_iinfo *au_ii(struct inode *inode) -+{ -+ BUG_ON(is_bad_inode(inode)); -+ return &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* inode.c */ -+struct inode *au_igrab(struct inode *inode); -+void au_refresh_iop(struct inode *inode, int force_getattr); -+int au_refresh_hinode_self(struct inode *inode); -+int au_refresh_hinode(struct inode *inode, struct dentry *dentry); -+int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, -+ unsigned int d_type, ino_t *ino); -+struct inode *au_new_inode(struct dentry *dentry, int must_new); -+int au_test_ro(struct super_block *sb, aufs_bindex_t bindex, -+ struct inode *inode); -+int au_test_h_perm(struct inode *h_inode, int mask); -+int au_test_h_perm_sio(struct inode *h_inode, int mask); -+ -+static inline int au_wh_ino(struct super_block *sb, aufs_bindex_t bindex, -+ ino_t h_ino, unsigned int d_type, ino_t *ino) -+{ -+#ifdef CONFIG_AUFS_SHWH -+ return au_ino(sb, bindex, h_ino, d_type, ino); -+#else -+ return 0; -+#endif -+} -+ -+/* i_op.c */ -+enum { -+ AuIop_SYMLINK, -+ AuIop_DIR, -+ AuIop_OTHER, -+ AuIop_Last -+}; -+extern struct inode_operations aufs_iop[AuIop_Last], /* not const */ -+ aufs_iop_nogetattr[AuIop_Last]; -+ -+/* au_wr_dir flags */ -+#define AuWrDir_ADD_ENTRY 1 -+#define AuWrDir_ISDIR (1 << 1) -+#define AuWrDir_TMPFILE (1 << 2) -+#define au_ftest_wrdir(flags, name) ((flags) & AuWrDir_##name) -+#define au_fset_wrdir(flags, name) \ -+ do { (flags) |= AuWrDir_##name; } while (0) -+#define au_fclr_wrdir(flags, name) \ -+ do { (flags) &= ~AuWrDir_##name; } while (0) -+ -+struct au_wr_dir_args { -+ aufs_bindex_t force_btgt; -+ unsigned char flags; -+}; -+int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry, -+ struct au_wr_dir_args *args); -+ -+struct dentry *au_pinned_h_parent(struct au_pin *pin); -+void au_pin_init(struct au_pin *pin, struct dentry *dentry, -+ aufs_bindex_t bindex, int lsc_di, int lsc_hi, -+ unsigned int udba, unsigned char flags); -+int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex, -+ unsigned int udba, unsigned char flags) __must_check; -+int au_do_pin(struct au_pin *pin) __must_check; -+void au_unpin(struct au_pin *pin); -+int au_reval_for_attr(struct dentry *dentry, unsigned int sigen); -+ -+#define AuIcpup_DID_CPUP 1 -+#define au_ftest_icpup(flags, name) ((flags) & AuIcpup_##name) -+#define au_fset_icpup(flags, name) \ -+ do { (flags) |= AuIcpup_##name; } while (0) -+#define au_fclr_icpup(flags, name) \ -+ do { (flags) &= ~AuIcpup_##name; } while (0) -+ -+struct au_icpup_args { -+ unsigned char flags; -+ unsigned char pin_flags; -+ aufs_bindex_t btgt; -+ unsigned int udba; -+ struct au_pin pin; -+ struct path h_path; -+ struct inode *h_inode; -+}; -+ -+int au_pin_and_icpup(struct dentry *dentry, struct iattr *ia, -+ struct au_icpup_args *a); -+ -+int au_h_path_getattr(struct dentry *dentry, int force, struct path *h_path, -+ int locked); -+ -+/* i_op_add.c */ -+int au_may_add(struct dentry *dentry, aufs_bindex_t bindex, -+ struct dentry *h_parent, int isdir); -+int aufs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, -+ dev_t dev); -+int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname); -+int aufs_create(struct inode *dir, struct dentry *dentry, umode_t mode, -+ bool want_excl); -+struct vfsub_aopen_args; -+int au_aopen_or_create(struct inode *dir, struct dentry *dentry, -+ struct vfsub_aopen_args *args); -+int aufs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode); -+int aufs_link(struct dentry *src_dentry, struct inode *dir, -+ struct dentry *dentry); -+int aufs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode); -+ -+/* i_op_del.c */ -+int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup); -+int au_may_del(struct dentry *dentry, aufs_bindex_t bindex, -+ struct dentry *h_parent, int isdir); -+int aufs_unlink(struct inode *dir, struct dentry *dentry); -+int aufs_rmdir(struct inode *dir, struct dentry *dentry); -+ -+/* i_op_ren.c */ -+int au_wbr(struct dentry *dentry, aufs_bindex_t btgt); -+int aufs_rename(struct inode *src_dir, struct dentry *src_dentry, -+ struct inode *dir, struct dentry *dentry, -+ unsigned int flags); -+ -+/* iinfo.c */ -+struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex); -+void au_hiput(struct au_hinode *hinode); -+void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex, -+ struct dentry *h_wh); -+unsigned int au_hi_flags(struct inode *inode, int isdir); -+ -+/* hinode flags */ -+#define AuHi_XINO 1 -+#define AuHi_HNOTIFY (1 << 1) -+#define au_ftest_hi(flags, name) ((flags) & AuHi_##name) -+#define au_fset_hi(flags, name) \ -+ do { (flags) |= AuHi_##name; } while (0) -+#define au_fclr_hi(flags, name) \ -+ do { (flags) &= ~AuHi_##name; } while (0) -+ -+#ifndef CONFIG_AUFS_HNOTIFY -+#undef AuHi_HNOTIFY -+#define AuHi_HNOTIFY 0 -+#endif -+ -+void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex, -+ struct inode *h_inode, unsigned int flags); -+ -+void au_update_iigen(struct inode *inode, int half); -+void au_update_ibrange(struct inode *inode, int do_put_zero); -+ -+void au_icntnr_init_once(void *_c); -+void au_hinode_init(struct au_hinode *hinode); -+int au_iinfo_init(struct inode *inode); -+void au_iinfo_fin(struct inode *inode); -+int au_hinode_realloc(struct au_iinfo *iinfo, int nbr, int may_shrink); -+ -+#ifdef CONFIG_PROC_FS -+/* plink.c */ -+int au_plink_maint(struct super_block *sb, int flags); -+struct au_sbinfo; -+void au_plink_maint_leave(struct au_sbinfo *sbinfo); -+int au_plink_maint_enter(struct super_block *sb); -+#ifdef CONFIG_AUFS_DEBUG -+void au_plink_list(struct super_block *sb); -+#else -+AuStubVoid(au_plink_list, struct super_block *sb) -+#endif -+int au_plink_test(struct inode *inode); -+struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex); -+void au_plink_append(struct inode *inode, aufs_bindex_t bindex, -+ struct dentry *h_dentry); -+void au_plink_put(struct super_block *sb, int verbose); -+void au_plink_clean(struct super_block *sb, int verbose); -+void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id); -+#else -+AuStubInt0(au_plink_maint, struct super_block *sb, int flags); -+AuStubVoid(au_plink_maint_leave, struct au_sbinfo *sbinfo); -+AuStubInt0(au_plink_maint_enter, struct super_block *sb); -+AuStubVoid(au_plink_list, struct super_block *sb); -+AuStubInt0(au_plink_test, struct inode *inode); -+AuStub(struct dentry *, au_plink_lkup, return NULL, -+ struct inode *inode, aufs_bindex_t bindex); -+AuStubVoid(au_plink_append, struct inode *inode, aufs_bindex_t bindex, -+ struct dentry *h_dentry); -+AuStubVoid(au_plink_put, struct super_block *sb, int verbose); -+AuStubVoid(au_plink_clean, struct super_block *sb, int verbose); -+AuStubVoid(au_plink_half_refresh, struct super_block *sb, aufs_bindex_t br_id); -+#endif /* CONFIG_PROC_FS */ -+ -+#ifdef CONFIG_AUFS_XATTR -+/* xattr.c */ -+int au_cpup_xattr(struct dentry *h_dst, struct dentry *h_src, int ignore_flags, -+ unsigned int verbose); -+ssize_t aufs_listxattr(struct dentry *dentry, char *list, size_t size); -+void au_xattr_init(struct super_block *sb); -+#else -+AuStubInt0(au_cpup_xattr, struct dentry *h_dst, struct dentry *h_src, -+ int ignore_flags, unsigned int verbose); -+AuStubVoid(au_xattr_init, struct super_block *sb); -+#endif -+ -+#ifdef CONFIG_FS_POSIX_ACL -+struct posix_acl *aufs_get_acl(struct inode *inode, int type); -+int aufs_set_acl(struct inode *inode, struct posix_acl *acl, int type); -+#endif -+ -+#if IS_ENABLED(CONFIG_AUFS_XATTR) || IS_ENABLED(CONFIG_FS_POSIX_ACL) -+enum { -+ AU_XATTR_SET, -+ AU_ACL_SET -+}; -+ -+struct au_sxattr { -+ int type; -+ union { -+ struct { -+ const char *name; -+ const void *value; -+ size_t size; -+ int flags; -+ } set; -+ struct { -+ struct posix_acl *acl; -+ int type; -+ } acl_set; -+ } u; -+}; -+ssize_t au_sxattr(struct dentry *dentry, struct inode *inode, -+ struct au_sxattr *arg); -+#endif -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* lock subclass for iinfo */ -+enum { -+ AuLsc_II_CHILD, /* child first */ -+ AuLsc_II_CHILD2, /* rename(2), link(2), and cpup at hnotify */ -+ AuLsc_II_CHILD3, /* copyup dirs */ -+ AuLsc_II_PARENT, /* see AuLsc_I_PARENT in vfsub.h */ -+ AuLsc_II_PARENT2, -+ AuLsc_II_PARENT3, /* copyup dirs */ -+ AuLsc_II_NEW_CHILD -+}; -+ -+/* -+ * ii_read_lock_child, ii_write_lock_child, -+ * ii_read_lock_child2, ii_write_lock_child2, -+ * ii_read_lock_child3, ii_write_lock_child3, -+ * ii_read_lock_parent, ii_write_lock_parent, -+ * ii_read_lock_parent2, ii_write_lock_parent2, -+ * ii_read_lock_parent3, ii_write_lock_parent3, -+ * ii_read_lock_new_child, ii_write_lock_new_child, -+ */ -+#define AuReadLockFunc(name, lsc) \ -+static inline void ii_read_lock_##name(struct inode *i) \ -+{ \ -+ au_rw_read_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \ -+} -+ -+#define AuWriteLockFunc(name, lsc) \ -+static inline void ii_write_lock_##name(struct inode *i) \ -+{ \ -+ au_rw_write_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \ -+} -+ -+#define AuRWLockFuncs(name, lsc) \ -+ AuReadLockFunc(name, lsc) \ -+ AuWriteLockFunc(name, lsc) -+ -+AuRWLockFuncs(child, CHILD); -+AuRWLockFuncs(child2, CHILD2); -+AuRWLockFuncs(child3, CHILD3); -+AuRWLockFuncs(parent, PARENT); -+AuRWLockFuncs(parent2, PARENT2); -+AuRWLockFuncs(parent3, PARENT3); -+AuRWLockFuncs(new_child, NEW_CHILD); -+ -+#undef AuReadLockFunc -+#undef AuWriteLockFunc -+#undef AuRWLockFuncs -+ -+#define ii_read_unlock(i) au_rw_read_unlock(&au_ii(i)->ii_rwsem) -+#define ii_write_unlock(i) au_rw_write_unlock(&au_ii(i)->ii_rwsem) -+#define ii_downgrade_lock(i) au_rw_dgrade_lock(&au_ii(i)->ii_rwsem) -+ -+#define IiMustNoWaiters(i) AuRwMustNoWaiters(&au_ii(i)->ii_rwsem) -+#define IiMustAnyLock(i) AuRwMustAnyLock(&au_ii(i)->ii_rwsem) -+#define IiMustWriteLock(i) AuRwMustWriteLock(&au_ii(i)->ii_rwsem) -+ -+/* ---------------------------------------------------------------------- */ -+ -+static inline void au_icntnr_init(struct au_icntnr *c) -+{ -+#ifdef CONFIG_AUFS_DEBUG -+ c->vfs_inode.i_mode = 0; -+#endif -+} -+ -+static inline unsigned int au_iigen(struct inode *inode, unsigned int *igflags) -+{ -+ unsigned int gen; -+ struct au_iinfo *iinfo; -+ struct au_iigen *iigen; -+ -+ iinfo = au_ii(inode); -+ iigen = &iinfo->ii_generation; -+ spin_lock(&iigen->ig_spin); -+ if (igflags) -+ *igflags = iigen->ig_flags; -+ gen = iigen->ig_generation; -+ spin_unlock(&iigen->ig_spin); -+ -+ return gen; -+} -+ -+/* tiny test for inode number */ -+/* tmpfs generation is too rough */ -+static inline int au_test_higen(struct inode *inode, struct inode *h_inode) -+{ -+ struct au_iinfo *iinfo; -+ -+ iinfo = au_ii(inode); -+ AuRwMustAnyLock(&iinfo->ii_rwsem); -+ return !(iinfo->ii_hsb1 == h_inode->i_sb -+ && iinfo->ii_higen == h_inode->i_generation); -+} -+ -+static inline void au_iigen_dec(struct inode *inode) -+{ -+ struct au_iinfo *iinfo; -+ struct au_iigen *iigen; -+ -+ iinfo = au_ii(inode); -+ iigen = &iinfo->ii_generation; -+ spin_lock(&iigen->ig_spin); -+ iigen->ig_generation--; -+ spin_unlock(&iigen->ig_spin); -+} -+ -+static inline int au_iigen_test(struct inode *inode, unsigned int sigen) -+{ -+ int err; -+ -+ err = 0; -+ if (unlikely(inode && au_iigen(inode, NULL) != sigen)) -+ err = -EIO; -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static inline struct au_hinode *au_hinode(struct au_iinfo *iinfo, -+ aufs_bindex_t bindex) -+{ -+ return iinfo->ii_hinode + bindex; -+} -+ -+static inline int au_is_bad_inode(struct inode *inode) -+{ -+ return !!(is_bad_inode(inode) || !au_hinode(au_ii(inode), 0)); -+} -+ -+static inline aufs_bindex_t au_ii_br_id(struct inode *inode, -+ aufs_bindex_t bindex) -+{ -+ IiMustAnyLock(inode); -+ return au_hinode(au_ii(inode), bindex)->hi_id; -+} -+ -+static inline aufs_bindex_t au_ibtop(struct inode *inode) -+{ -+ IiMustAnyLock(inode); -+ return au_ii(inode)->ii_btop; -+} -+ -+static inline aufs_bindex_t au_ibbot(struct inode *inode) -+{ -+ IiMustAnyLock(inode); -+ return au_ii(inode)->ii_bbot; -+} -+ -+static inline struct au_vdir *au_ivdir(struct inode *inode) -+{ -+ IiMustAnyLock(inode); -+ return au_ii(inode)->ii_vdir; -+} -+ -+static inline struct dentry *au_hi_wh(struct inode *inode, aufs_bindex_t bindex) -+{ -+ IiMustAnyLock(inode); -+ return au_hinode(au_ii(inode), bindex)->hi_whdentry; -+} -+ -+static inline void au_set_ibtop(struct inode *inode, aufs_bindex_t bindex) -+{ -+ IiMustWriteLock(inode); -+ au_ii(inode)->ii_btop = bindex; -+} -+ -+static inline void au_set_ibbot(struct inode *inode, aufs_bindex_t bindex) -+{ -+ IiMustWriteLock(inode); -+ au_ii(inode)->ii_bbot = bindex; -+} -+ -+static inline void au_set_ivdir(struct inode *inode, struct au_vdir *vdir) -+{ -+ IiMustWriteLock(inode); -+ au_ii(inode)->ii_vdir = vdir; -+} -+ -+static inline struct au_hinode *au_hi(struct inode *inode, aufs_bindex_t bindex) -+{ -+ IiMustAnyLock(inode); -+ return au_hinode(au_ii(inode), bindex); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static inline struct dentry *au_pinned_parent(struct au_pin *pin) -+{ -+ if (pin) -+ return pin->parent; -+ return NULL; -+} -+ -+static inline struct inode *au_pinned_h_dir(struct au_pin *pin) -+{ -+ if (pin && pin->hdir) -+ return pin->hdir->hi_inode; -+ return NULL; -+} -+ -+static inline struct au_hinode *au_pinned_hdir(struct au_pin *pin) -+{ -+ if (pin) -+ return pin->hdir; -+ return NULL; -+} -+ -+static inline void au_pin_set_dentry(struct au_pin *pin, struct dentry *dentry) -+{ -+ if (pin) -+ pin->dentry = dentry; -+} -+ -+static inline void au_pin_set_parent_lflag(struct au_pin *pin, -+ unsigned char lflag) -+{ -+ if (pin) { -+ if (lflag) -+ au_fset_pin(pin->flags, DI_LOCKED); -+ else -+ au_fclr_pin(pin->flags, DI_LOCKED); -+ } -+} -+ -+#if 0 /* reserved */ -+static inline void au_pin_set_parent(struct au_pin *pin, struct dentry *parent) -+{ -+ if (pin) { -+ dput(pin->parent); -+ pin->parent = dget(parent); -+ } -+} -+#endif -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct au_branch; -+#ifdef CONFIG_AUFS_HNOTIFY -+struct au_hnotify_op { -+ void (*ctl)(struct au_hinode *hinode, int do_set); -+ int (*alloc)(struct au_hinode *hinode); -+ -+ /* -+ * if it returns true, the the caller should free hinode->hi_notify, -+ * otherwise ->free() frees it. -+ */ -+ int (*free)(struct au_hinode *hinode, -+ struct au_hnotify *hn) __must_check; -+ -+ void (*fin)(void); -+ int (*init)(void); -+ -+ int (*reset_br)(unsigned int udba, struct au_branch *br, int perm); -+ void (*fin_br)(struct au_branch *br); -+ int (*init_br)(struct au_branch *br, int perm); -+}; -+ -+/* hnotify.c */ -+int au_hn_alloc(struct au_hinode *hinode, struct inode *inode); -+void au_hn_free(struct au_hinode *hinode); -+void au_hn_ctl(struct au_hinode *hinode, int do_set); -+void au_hn_reset(struct inode *inode, unsigned int flags); -+int au_hnotify(struct inode *h_dir, struct au_hnotify *hnotify, u32 mask, -+ const struct qstr *h_child_qstr, struct inode *h_child_inode); -+int au_hnotify_reset_br(unsigned int udba, struct au_branch *br, int perm); -+int au_hnotify_init_br(struct au_branch *br, int perm); -+void au_hnotify_fin_br(struct au_branch *br); -+int __init au_hnotify_init(void); -+void au_hnotify_fin(void); -+ -+/* hfsnotify.c */ -+extern const struct au_hnotify_op au_hnotify_op; -+ -+static inline -+void au_hn_init(struct au_hinode *hinode) -+{ -+ hinode->hi_notify = NULL; -+} -+ -+static inline struct au_hnotify *au_hn(struct au_hinode *hinode) -+{ -+ return hinode->hi_notify; -+} -+ -+#else -+AuStub(int, au_hn_alloc, return -EOPNOTSUPP, -+ struct au_hinode *hinode __maybe_unused, -+ struct inode *inode __maybe_unused) -+AuStub(struct au_hnotify *, au_hn, return NULL, struct au_hinode *hinode) -+AuStubVoid(au_hn_free, struct au_hinode *hinode __maybe_unused) -+AuStubVoid(au_hn_ctl, struct au_hinode *hinode __maybe_unused, -+ int do_set __maybe_unused) -+AuStubVoid(au_hn_reset, struct inode *inode __maybe_unused, -+ unsigned int flags __maybe_unused) -+AuStubInt0(au_hnotify_reset_br, unsigned int udba __maybe_unused, -+ struct au_branch *br __maybe_unused, -+ int perm __maybe_unused) -+AuStubInt0(au_hnotify_init_br, struct au_branch *br __maybe_unused, -+ int perm __maybe_unused) -+AuStubVoid(au_hnotify_fin_br, struct au_branch *br __maybe_unused) -+AuStubInt0(__init au_hnotify_init, void) -+AuStubVoid(au_hnotify_fin, void) -+AuStubVoid(au_hn_init, struct au_hinode *hinode __maybe_unused) -+#endif /* CONFIG_AUFS_HNOTIFY */ -+ -+static inline void au_hn_suspend(struct au_hinode *hdir) -+{ -+ au_hn_ctl(hdir, /*do_set*/0); -+} -+ -+static inline void au_hn_resume(struct au_hinode *hdir) -+{ -+ au_hn_ctl(hdir, /*do_set*/1); -+} -+ -+static inline void au_hn_inode_lock(struct au_hinode *hdir) -+{ -+ inode_lock(hdir->hi_inode); -+ au_hn_suspend(hdir); -+} -+ -+static inline void au_hn_inode_lock_nested(struct au_hinode *hdir, -+ unsigned int sc __maybe_unused) -+{ -+ inode_lock_nested(hdir->hi_inode, sc); -+ au_hn_suspend(hdir); -+} -+ -+#if 0 /* unused */ -+#include "vfsub.h" -+static inline void au_hn_inode_lock_shared_nested(struct au_hinode *hdir, -+ unsigned int sc) -+{ -+ inode_lock_shared_nested(hdir->hi_inode, sc); -+ au_hn_suspend(hdir); -+} -+#endif -+ -+static inline void au_hn_inode_unlock(struct au_hinode *hdir) -+{ -+ au_hn_resume(hdir); -+ inode_unlock(hdir->hi_inode); -+} -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_INODE_H__ */ -diff -Nurp linux-5.6.3/fs/aufs/ioctl.c linux-5.6.3-aufs/fs/aufs/ioctl.c ---- linux-5.6.3/fs/aufs/ioctl.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/ioctl.c 2020-04-10 12:40:52.191049456 +0300 -@@ -0,0 +1,207 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * ioctl -+ * plink-management and readdir in userspace. -+ * assist the pathconf(3) wrapper library. -+ * move-down -+ * File-based Hierarchical Storage Management. -+ */ -+ -+#include -+#include -+#include "aufs.h" -+ -+static int au_wbr_fd(struct path *path, struct aufs_wbr_fd __user *arg) -+{ -+ int err, fd; -+ aufs_bindex_t wbi, bindex, bbot; -+ struct file *h_file; -+ struct super_block *sb; -+ struct dentry *root; -+ struct au_branch *br; -+ struct aufs_wbr_fd wbrfd = { -+ .oflags = au_dir_roflags, -+ .brid = -1 -+ }; -+ const int valid = O_RDONLY | O_NONBLOCK | O_LARGEFILE | O_DIRECTORY -+ | O_NOATIME | O_CLOEXEC; -+ -+ AuDebugOn(wbrfd.oflags & ~valid); -+ -+ if (arg) { -+ err = copy_from_user(&wbrfd, arg, sizeof(wbrfd)); -+ if (unlikely(err)) { -+ err = -EFAULT; -+ goto out; -+ } -+ -+ err = -EINVAL; -+ AuDbg("wbrfd{0%o, %d}\n", wbrfd.oflags, wbrfd.brid); -+ wbrfd.oflags |= au_dir_roflags; -+ AuDbg("0%o\n", wbrfd.oflags); -+ if (unlikely(wbrfd.oflags & ~valid)) -+ goto out; -+ } -+ -+ fd = get_unused_fd_flags(0); -+ err = fd; -+ if (unlikely(fd < 0)) -+ goto out; -+ -+ h_file = ERR_PTR(-EINVAL); -+ wbi = 0; -+ br = NULL; -+ sb = path->dentry->d_sb; -+ root = sb->s_root; -+ aufs_read_lock(root, AuLock_IR); -+ bbot = au_sbbot(sb); -+ if (wbrfd.brid >= 0) { -+ wbi = au_br_index(sb, wbrfd.brid); -+ if (unlikely(wbi < 0 || wbi > bbot)) -+ goto out_unlock; -+ } -+ -+ h_file = ERR_PTR(-ENOENT); -+ br = au_sbr(sb, wbi); -+ if (!au_br_writable(br->br_perm)) { -+ if (arg) -+ goto out_unlock; -+ -+ bindex = wbi + 1; -+ wbi = -1; -+ for (; bindex <= bbot; bindex++) { -+ br = au_sbr(sb, bindex); -+ if (au_br_writable(br->br_perm)) { -+ wbi = bindex; -+ br = au_sbr(sb, wbi); -+ break; -+ } -+ } -+ } -+ AuDbg("wbi %d\n", wbi); -+ if (wbi >= 0) -+ h_file = au_h_open(root, wbi, wbrfd.oflags, NULL, -+ /*force_wr*/0); -+ -+out_unlock: -+ aufs_read_unlock(root, AuLock_IR); -+ err = PTR_ERR(h_file); -+ if (IS_ERR(h_file)) -+ goto out_fd; -+ -+ au_lcnt_dec(&br->br_nfiles); /* cf. au_h_open() */ -+ fd_install(fd, h_file); -+ err = fd; -+ goto out; /* success */ -+ -+out_fd: -+ put_unused_fd(fd); -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg) -+{ -+ long err; -+ struct dentry *dentry; -+ -+ switch (cmd) { -+ case AUFS_CTL_RDU: -+ case AUFS_CTL_RDU_INO: -+ err = au_rdu_ioctl(file, cmd, arg); -+ break; -+ -+ case AUFS_CTL_WBR_FD: -+ err = au_wbr_fd(&file->f_path, (void __user *)arg); -+ break; -+ -+ case AUFS_CTL_IBUSY: -+ err = au_ibusy_ioctl(file, arg); -+ break; -+ -+ case AUFS_CTL_BRINFO: -+ err = au_brinfo_ioctl(file, arg); -+ break; -+ -+ case AUFS_CTL_FHSM_FD: -+ dentry = file->f_path.dentry; -+ if (IS_ROOT(dentry)) -+ err = au_fhsm_fd(dentry->d_sb, arg); -+ else -+ err = -ENOTTY; -+ break; -+ -+ default: -+ /* do not call the lower */ -+ AuDbg("0x%x\n", cmd); -+ err = -ENOTTY; -+ } -+ -+ AuTraceErr(err); -+ return err; -+} -+ -+long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg) -+{ -+ long err; -+ -+ switch (cmd) { -+ case AUFS_CTL_MVDOWN: -+ err = au_mvdown(file->f_path.dentry, (void __user *)arg); -+ break; -+ -+ case AUFS_CTL_WBR_FD: -+ err = au_wbr_fd(&file->f_path, (void __user *)arg); -+ break; -+ -+ default: -+ /* do not call the lower */ -+ AuDbg("0x%x\n", cmd); -+ err = -ENOTTY; -+ } -+ -+ AuTraceErr(err); -+ return err; -+} -+ -+#ifdef CONFIG_COMPAT -+long aufs_compat_ioctl_dir(struct file *file, unsigned int cmd, -+ unsigned long arg) -+{ -+ long err; -+ -+ switch (cmd) { -+ case AUFS_CTL_RDU: -+ case AUFS_CTL_RDU_INO: -+ err = au_rdu_compat_ioctl(file, cmd, arg); -+ break; -+ -+ case AUFS_CTL_IBUSY: -+ err = au_ibusy_compat_ioctl(file, arg); -+ break; -+ -+ case AUFS_CTL_BRINFO: -+ err = au_brinfo_compat_ioctl(file, arg); -+ break; -+ -+ default: -+ err = aufs_ioctl_dir(file, cmd, arg); -+ } -+ -+ AuTraceErr(err); -+ return err; -+} -+ -+long aufs_compat_ioctl_nondir(struct file *file, unsigned int cmd, -+ unsigned long arg) -+{ -+ return aufs_ioctl_nondir(file, cmd, (unsigned long)compat_ptr(arg)); -+} -+#endif -diff -Nurp linux-5.6.3/fs/aufs/i_op_add.c linux-5.6.3-aufs/fs/aufs/i_op_add.c ---- linux-5.6.3/fs/aufs/i_op_add.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/i_op_add.c 2020-04-10 12:40:52.191049456 +0300 -@@ -0,0 +1,923 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * inode operations (add entry) -+ */ -+ -+#include -+#include "aufs.h" -+ -+/* -+ * final procedure of adding a new entry, except link(2). -+ * remove whiteout, instantiate, copyup the parent dir's times and size -+ * and update version. -+ * if it failed, re-create the removed whiteout. -+ */ -+static int epilog(struct inode *dir, aufs_bindex_t bindex, -+ struct dentry *wh_dentry, struct dentry *dentry) -+{ -+ int err, rerr; -+ aufs_bindex_t bwh; -+ struct path h_path; -+ struct super_block *sb; -+ struct inode *inode, *h_dir; -+ struct dentry *wh; -+ -+ bwh = -1; -+ sb = dir->i_sb; -+ if (wh_dentry) { -+ h_dir = d_inode(wh_dentry->d_parent); /* dir inode is locked */ -+ IMustLock(h_dir); -+ AuDebugOn(au_h_iptr(dir, bindex) != h_dir); -+ bwh = au_dbwh(dentry); -+ h_path.dentry = wh_dentry; -+ h_path.mnt = au_sbr_mnt(sb, bindex); -+ err = au_wh_unlink_dentry(au_h_iptr(dir, bindex), &h_path, -+ dentry); -+ if (unlikely(err)) -+ goto out; -+ } -+ -+ inode = au_new_inode(dentry, /*must_new*/1); -+ if (!IS_ERR(inode)) { -+ d_instantiate(dentry, inode); -+ dir = d_inode(dentry->d_parent); /* dir inode is locked */ -+ IMustLock(dir); -+ au_dir_ts(dir, bindex); -+ inode_inc_iversion(dir); -+ au_fhsm_wrote(sb, bindex, /*force*/0); -+ return 0; /* success */ -+ } -+ -+ err = PTR_ERR(inode); -+ if (!wh_dentry) -+ goto out; -+ -+ /* revert */ -+ /* dir inode is locked */ -+ wh = au_wh_create(dentry, bwh, wh_dentry->d_parent); -+ rerr = PTR_ERR(wh); -+ if (IS_ERR(wh)) { -+ AuIOErr("%pd reverting whiteout failed(%d, %d)\n", -+ dentry, err, rerr); -+ err = -EIO; -+ } else -+ dput(wh); -+ -+out: -+ return err; -+} -+ -+static int au_d_may_add(struct dentry *dentry) -+{ -+ int err; -+ -+ err = 0; -+ if (unlikely(d_unhashed(dentry))) -+ err = -ENOENT; -+ if (unlikely(d_really_is_positive(dentry))) -+ err = -EEXIST; -+ return err; -+} -+ -+/* -+ * simple tests for the adding inode operations. -+ * following the checks in vfs, plus the parent-child relationship. -+ */ -+int au_may_add(struct dentry *dentry, aufs_bindex_t bindex, -+ struct dentry *h_parent, int isdir) -+{ -+ int err; -+ umode_t h_mode; -+ struct dentry *h_dentry; -+ struct inode *h_inode; -+ -+ err = -ENAMETOOLONG; -+ if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN)) -+ goto out; -+ -+ h_dentry = au_h_dptr(dentry, bindex); -+ if (d_really_is_negative(dentry)) { -+ err = -EEXIST; -+ if (unlikely(d_is_positive(h_dentry))) -+ goto out; -+ } else { -+ /* rename(2) case */ -+ err = -EIO; -+ if (unlikely(d_is_negative(h_dentry))) -+ goto out; -+ h_inode = d_inode(h_dentry); -+ if (unlikely(!h_inode->i_nlink)) -+ goto out; -+ -+ h_mode = h_inode->i_mode; -+ if (!isdir) { -+ err = -EISDIR; -+ if (unlikely(S_ISDIR(h_mode))) -+ goto out; -+ } else if (unlikely(!S_ISDIR(h_mode))) { -+ err = -ENOTDIR; -+ goto out; -+ } -+ } -+ -+ err = 0; -+ /* expected parent dir is locked */ -+ if (unlikely(h_parent != h_dentry->d_parent)) -+ err = -EIO; -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+/* -+ * initial procedure of adding a new entry. -+ * prepare writable branch and the parent dir, lock it, -+ * and lookup whiteout for the new entry. -+ */ -+static struct dentry* -+lock_hdir_lkup_wh(struct dentry *dentry, struct au_dtime *dt, -+ struct dentry *src_dentry, struct au_pin *pin, -+ struct au_wr_dir_args *wr_dir_args) -+{ -+ struct dentry *wh_dentry, *h_parent; -+ struct super_block *sb; -+ struct au_branch *br; -+ int err; -+ unsigned int udba; -+ aufs_bindex_t bcpup; -+ -+ AuDbg("%pd\n", dentry); -+ -+ err = au_wr_dir(dentry, src_dentry, wr_dir_args); -+ bcpup = err; -+ wh_dentry = ERR_PTR(err); -+ if (unlikely(err < 0)) -+ goto out; -+ -+ sb = dentry->d_sb; -+ udba = au_opt_udba(sb); -+ err = au_pin(pin, dentry, bcpup, udba, -+ AuPin_DI_LOCKED | AuPin_MNT_WRITE); -+ wh_dentry = ERR_PTR(err); -+ if (unlikely(err)) -+ goto out; -+ -+ h_parent = au_pinned_h_parent(pin); -+ if (udba != AuOpt_UDBA_NONE -+ && au_dbtop(dentry) == bcpup) -+ err = au_may_add(dentry, bcpup, h_parent, -+ au_ftest_wrdir(wr_dir_args->flags, ISDIR)); -+ else if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN)) -+ err = -ENAMETOOLONG; -+ wh_dentry = ERR_PTR(err); -+ if (unlikely(err)) -+ goto out_unpin; -+ -+ br = au_sbr(sb, bcpup); -+ if (dt) { -+ struct path tmp = { -+ .dentry = h_parent, -+ .mnt = au_br_mnt(br) -+ }; -+ au_dtime_store(dt, au_pinned_parent(pin), &tmp); -+ } -+ -+ wh_dentry = NULL; -+ if (bcpup != au_dbwh(dentry)) -+ goto out; /* success */ -+ -+ /* -+ * ENAMETOOLONG here means that if we allowed create such name, then it -+ * would not be able to removed in the future. So we don't allow such -+ * name here and we don't handle ENAMETOOLONG differently here. -+ */ -+ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, br); -+ -+out_unpin: -+ if (IS_ERR(wh_dentry)) -+ au_unpin(pin); -+out: -+ return wh_dentry; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+enum { Mknod, Symlink, Creat }; -+struct simple_arg { -+ int type; -+ union { -+ struct { -+ umode_t mode; -+ bool want_excl; -+ bool try_aopen; -+ struct vfsub_aopen_args *aopen; -+ } c; -+ struct { -+ const char *symname; -+ } s; -+ struct { -+ umode_t mode; -+ dev_t dev; -+ } m; -+ } u; -+}; -+ -+static int add_simple(struct inode *dir, struct dentry *dentry, -+ struct simple_arg *arg) -+{ -+ int err, rerr; -+ aufs_bindex_t btop; -+ unsigned char created; -+ const unsigned char try_aopen -+ = (arg->type == Creat && arg->u.c.try_aopen); -+ struct vfsub_aopen_args *aopen = arg->u.c.aopen; -+ struct dentry *wh_dentry, *parent; -+ struct inode *h_dir; -+ struct super_block *sb; -+ struct au_branch *br; -+ /* to reduce stack size */ -+ struct { -+ struct au_dtime dt; -+ struct au_pin pin; -+ struct path h_path; -+ struct au_wr_dir_args wr_dir_args; -+ } *a; -+ -+ AuDbg("%pd\n", dentry); -+ IMustLock(dir); -+ -+ err = -ENOMEM; -+ a = kmalloc(sizeof(*a), GFP_NOFS); -+ if (unlikely(!a)) -+ goto out; -+ a->wr_dir_args.force_btgt = -1; -+ a->wr_dir_args.flags = AuWrDir_ADD_ENTRY; -+ -+ parent = dentry->d_parent; /* dir inode is locked */ -+ if (!try_aopen) { -+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN); -+ if (unlikely(err)) -+ goto out_free; -+ } -+ err = au_d_may_add(dentry); -+ if (unlikely(err)) -+ goto out_unlock; -+ if (!try_aopen) -+ di_write_lock_parent(parent); -+ wh_dentry = lock_hdir_lkup_wh(dentry, &a->dt, /*src_dentry*/NULL, -+ &a->pin, &a->wr_dir_args); -+ err = PTR_ERR(wh_dentry); -+ if (IS_ERR(wh_dentry)) -+ goto out_parent; -+ -+ btop = au_dbtop(dentry); -+ sb = dentry->d_sb; -+ br = au_sbr(sb, btop); -+ a->h_path.dentry = au_h_dptr(dentry, btop); -+ a->h_path.mnt = au_br_mnt(br); -+ h_dir = au_pinned_h_dir(&a->pin); -+ switch (arg->type) { -+ case Creat: -+ if (!try_aopen || !h_dir->i_op->atomic_open) { -+ err = vfsub_create(h_dir, &a->h_path, arg->u.c.mode, -+ arg->u.c.want_excl); -+ created = !err; -+ if (!err && try_aopen) -+ aopen->file->f_mode |= FMODE_CREATED; -+ } else { -+ aopen->br = br; -+ err = vfsub_atomic_open(h_dir, a->h_path.dentry, aopen); -+ AuDbg("err %d\n", err); -+ AuDbgFile(aopen->file); -+ created = err >= 0 -+ && !!(aopen->file->f_mode & FMODE_CREATED); -+ } -+ break; -+ case Symlink: -+ err = vfsub_symlink(h_dir, &a->h_path, arg->u.s.symname); -+ created = !err; -+ break; -+ case Mknod: -+ err = vfsub_mknod(h_dir, &a->h_path, arg->u.m.mode, -+ arg->u.m.dev); -+ created = !err; -+ break; -+ default: -+ BUG(); -+ } -+ if (unlikely(err < 0)) -+ goto out_unpin; -+ -+ err = epilog(dir, btop, wh_dentry, dentry); -+ if (!err) -+ goto out_unpin; /* success */ -+ -+ /* revert */ -+ if (created /* && d_is_positive(a->h_path.dentry) */) { -+ /* no delegation since it is just created */ -+ rerr = vfsub_unlink(h_dir, &a->h_path, /*delegated*/NULL, -+ /*force*/0); -+ if (rerr) { -+ AuIOErr("%pd revert failure(%d, %d)\n", -+ dentry, err, rerr); -+ err = -EIO; -+ } -+ au_dtime_revert(&a->dt); -+ } -+ if (try_aopen && h_dir->i_op->atomic_open -+ && (aopen->file->f_mode & FMODE_OPENED)) -+ /* aopen->file is still opened */ -+ au_lcnt_dec(&aopen->br->br_nfiles); -+ -+out_unpin: -+ au_unpin(&a->pin); -+ dput(wh_dentry); -+out_parent: -+ if (!try_aopen) -+ di_write_unlock(parent); -+out_unlock: -+ if (unlikely(err)) { -+ au_update_dbtop(dentry); -+ d_drop(dentry); -+ } -+ if (!try_aopen) -+ aufs_read_unlock(dentry, AuLock_DW); -+out_free: -+ au_kfree_rcu(a); -+out: -+ return err; -+} -+ -+int aufs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, -+ dev_t dev) -+{ -+ struct simple_arg arg = { -+ .type = Mknod, -+ .u.m = { -+ .mode = mode, -+ .dev = dev -+ } -+ }; -+ return add_simple(dir, dentry, &arg); -+} -+ -+int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) -+{ -+ struct simple_arg arg = { -+ .type = Symlink, -+ .u.s.symname = symname -+ }; -+ return add_simple(dir, dentry, &arg); -+} -+ -+int aufs_create(struct inode *dir, struct dentry *dentry, umode_t mode, -+ bool want_excl) -+{ -+ struct simple_arg arg = { -+ .type = Creat, -+ .u.c = { -+ .mode = mode, -+ .want_excl = want_excl -+ } -+ }; -+ return add_simple(dir, dentry, &arg); -+} -+ -+int au_aopen_or_create(struct inode *dir, struct dentry *dentry, -+ struct vfsub_aopen_args *aopen_args) -+{ -+ struct simple_arg arg = { -+ .type = Creat, -+ .u.c = { -+ .mode = aopen_args->create_mode, -+ .want_excl = aopen_args->open_flag & O_EXCL, -+ .try_aopen = true, -+ .aopen = aopen_args -+ } -+ }; -+ return add_simple(dir, dentry, &arg); -+} -+ -+int aufs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode) -+{ -+ int err; -+ aufs_bindex_t bindex; -+ struct super_block *sb; -+ struct dentry *parent, *h_parent, *h_dentry; -+ struct inode *h_dir, *inode; -+ struct vfsmount *h_mnt; -+ struct au_wr_dir_args wr_dir_args = { -+ .force_btgt = -1, -+ .flags = AuWrDir_TMPFILE -+ }; -+ -+ /* copy-up may happen */ -+ inode_lock(dir); -+ -+ sb = dir->i_sb; -+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM); -+ if (unlikely(err)) -+ goto out; -+ -+ err = au_di_init(dentry); -+ if (unlikely(err)) -+ goto out_si; -+ -+ err = -EBUSY; -+ parent = d_find_any_alias(dir); -+ AuDebugOn(!parent); -+ di_write_lock_parent(parent); -+ if (unlikely(d_inode(parent) != dir)) -+ goto out_parent; -+ -+ err = au_digen_test(parent, au_sigen(sb)); -+ if (unlikely(err)) -+ goto out_parent; -+ -+ bindex = au_dbtop(parent); -+ au_set_dbtop(dentry, bindex); -+ au_set_dbbot(dentry, bindex); -+ err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args); -+ bindex = err; -+ if (unlikely(err < 0)) -+ goto out_parent; -+ -+ err = -EOPNOTSUPP; -+ h_dir = au_h_iptr(dir, bindex); -+ if (unlikely(!h_dir->i_op->tmpfile)) -+ goto out_parent; -+ -+ h_mnt = au_sbr_mnt(sb, bindex); -+ err = vfsub_mnt_want_write(h_mnt); -+ if (unlikely(err)) -+ goto out_parent; -+ -+ h_parent = au_h_dptr(parent, bindex); -+ h_dentry = vfs_tmpfile(h_parent, mode, /*open_flag*/0); -+ if (IS_ERR(h_dentry)) { -+ err = PTR_ERR(h_dentry); -+ goto out_mnt; -+ } -+ -+ au_set_dbtop(dentry, bindex); -+ au_set_dbbot(dentry, bindex); -+ au_set_h_dptr(dentry, bindex, dget(h_dentry)); -+ inode = au_new_inode(dentry, /*must_new*/1); -+ if (IS_ERR(inode)) { -+ err = PTR_ERR(inode); -+ au_set_h_dptr(dentry, bindex, NULL); -+ au_set_dbtop(dentry, -1); -+ au_set_dbbot(dentry, -1); -+ } else { -+ if (!inode->i_nlink) -+ set_nlink(inode, 1); -+ d_tmpfile(dentry, inode); -+ au_di(dentry)->di_tmpfile = 1; -+ -+ /* update without i_mutex */ -+ if (au_ibtop(dir) == au_dbtop(dentry)) -+ au_cpup_attr_timesizes(dir); -+ } -+ dput(h_dentry); -+ -+out_mnt: -+ vfsub_mnt_drop_write(h_mnt); -+out_parent: -+ di_write_unlock(parent); -+ dput(parent); -+ di_write_unlock(dentry); -+ if (unlikely(err)) { -+ au_di_fin(dentry); -+ dentry->d_fsdata = NULL; -+ } -+out_si: -+ si_read_unlock(sb); -+out: -+ inode_unlock(dir); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct au_link_args { -+ aufs_bindex_t bdst, bsrc; -+ struct au_pin pin; -+ struct path h_path; -+ struct dentry *src_parent, *parent; -+}; -+ -+static int au_cpup_before_link(struct dentry *src_dentry, -+ struct au_link_args *a) -+{ -+ int err; -+ struct dentry *h_src_dentry; -+ struct au_cp_generic cpg = { -+ .dentry = src_dentry, -+ .bdst = a->bdst, -+ .bsrc = a->bsrc, -+ .len = -1, -+ .pin = &a->pin, -+ .flags = AuCpup_DTIME | AuCpup_HOPEN /* | AuCpup_KEEPLINO */ -+ }; -+ -+ di_read_lock_parent(a->src_parent, AuLock_IR); -+ err = au_test_and_cpup_dirs(src_dentry, a->bdst); -+ if (unlikely(err)) -+ goto out; -+ -+ h_src_dentry = au_h_dptr(src_dentry, a->bsrc); -+ err = au_pin(&a->pin, src_dentry, a->bdst, -+ au_opt_udba(src_dentry->d_sb), -+ AuPin_DI_LOCKED | AuPin_MNT_WRITE); -+ if (unlikely(err)) -+ goto out; -+ -+ err = au_sio_cpup_simple(&cpg); -+ au_unpin(&a->pin); -+ -+out: -+ di_read_unlock(a->src_parent, AuLock_IR); -+ return err; -+} -+ -+static int au_cpup_or_link(struct dentry *src_dentry, struct dentry *dentry, -+ struct au_link_args *a) -+{ -+ int err; -+ unsigned char plink; -+ aufs_bindex_t bbot; -+ struct dentry *h_src_dentry; -+ struct inode *h_inode, *inode, *delegated; -+ struct super_block *sb; -+ struct file *h_file; -+ -+ plink = 0; -+ h_inode = NULL; -+ sb = src_dentry->d_sb; -+ inode = d_inode(src_dentry); -+ if (au_ibtop(inode) <= a->bdst) -+ h_inode = au_h_iptr(inode, a->bdst); -+ if (!h_inode || !h_inode->i_nlink) { -+ /* copyup src_dentry as the name of dentry. */ -+ bbot = au_dbbot(dentry); -+ if (bbot < a->bsrc) -+ au_set_dbbot(dentry, a->bsrc); -+ au_set_h_dptr(dentry, a->bsrc, -+ dget(au_h_dptr(src_dentry, a->bsrc))); -+ dget(a->h_path.dentry); -+ au_set_h_dptr(dentry, a->bdst, NULL); -+ AuDbg("temporary d_inode...\n"); -+ spin_lock(&dentry->d_lock); -+ dentry->d_inode = d_inode(src_dentry); /* tmp */ -+ spin_unlock(&dentry->d_lock); -+ h_file = au_h_open_pre(dentry, a->bsrc, /*force_wr*/0); -+ if (IS_ERR(h_file)) -+ err = PTR_ERR(h_file); -+ else { -+ struct au_cp_generic cpg = { -+ .dentry = dentry, -+ .bdst = a->bdst, -+ .bsrc = -1, -+ .len = -1, -+ .pin = &a->pin, -+ .flags = AuCpup_KEEPLINO -+ }; -+ err = au_sio_cpup_simple(&cpg); -+ au_h_open_post(dentry, a->bsrc, h_file); -+ if (!err) { -+ dput(a->h_path.dentry); -+ a->h_path.dentry = au_h_dptr(dentry, a->bdst); -+ } else -+ au_set_h_dptr(dentry, a->bdst, -+ a->h_path.dentry); -+ } -+ spin_lock(&dentry->d_lock); -+ dentry->d_inode = NULL; /* restore */ -+ spin_unlock(&dentry->d_lock); -+ AuDbg("temporary d_inode...done\n"); -+ au_set_h_dptr(dentry, a->bsrc, NULL); -+ au_set_dbbot(dentry, bbot); -+ } else { -+ /* the inode of src_dentry already exists on a.bdst branch */ -+ h_src_dentry = d_find_alias(h_inode); -+ if (!h_src_dentry && au_plink_test(inode)) { -+ plink = 1; -+ h_src_dentry = au_plink_lkup(inode, a->bdst); -+ err = PTR_ERR(h_src_dentry); -+ if (IS_ERR(h_src_dentry)) -+ goto out; -+ -+ if (unlikely(d_is_negative(h_src_dentry))) { -+ dput(h_src_dentry); -+ h_src_dentry = NULL; -+ } -+ -+ } -+ if (h_src_dentry) { -+ delegated = NULL; -+ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin), -+ &a->h_path, &delegated); -+ if (unlikely(err == -EWOULDBLOCK)) { -+ pr_warn("cannot retry for NFSv4 delegation" -+ " for an internal link\n"); -+ iput(delegated); -+ } -+ dput(h_src_dentry); -+ } else { -+ AuIOErr("no dentry found for hi%lu on b%d\n", -+ h_inode->i_ino, a->bdst); -+ err = -EIO; -+ } -+ } -+ -+ if (!err && !plink) -+ au_plink_append(inode, a->bdst, a->h_path.dentry); -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+int aufs_link(struct dentry *src_dentry, struct inode *dir, -+ struct dentry *dentry) -+{ -+ int err, rerr; -+ struct au_dtime dt; -+ struct au_link_args *a; -+ struct dentry *wh_dentry, *h_src_dentry; -+ struct inode *inode, *delegated; -+ struct super_block *sb; -+ struct au_wr_dir_args wr_dir_args = { -+ /* .force_btgt = -1, */ -+ .flags = AuWrDir_ADD_ENTRY -+ }; -+ -+ IMustLock(dir); -+ inode = d_inode(src_dentry); -+ IMustLock(inode); -+ -+ err = -ENOMEM; -+ a = kzalloc(sizeof(*a), GFP_NOFS); -+ if (unlikely(!a)) -+ goto out; -+ -+ a->parent = dentry->d_parent; /* dir inode is locked */ -+ err = aufs_read_and_write_lock2(dentry, src_dentry, -+ AuLock_NOPLM | AuLock_GEN); -+ if (unlikely(err)) -+ goto out_kfree; -+ err = au_d_linkable(src_dentry); -+ if (unlikely(err)) -+ goto out_unlock; -+ err = au_d_may_add(dentry); -+ if (unlikely(err)) -+ goto out_unlock; -+ -+ a->src_parent = dget_parent(src_dentry); -+ wr_dir_args.force_btgt = au_ibtop(inode); -+ -+ di_write_lock_parent(a->parent); -+ wr_dir_args.force_btgt = au_wbr(dentry, wr_dir_args.force_btgt); -+ wh_dentry = lock_hdir_lkup_wh(dentry, &dt, src_dentry, &a->pin, -+ &wr_dir_args); -+ err = PTR_ERR(wh_dentry); -+ if (IS_ERR(wh_dentry)) -+ goto out_parent; -+ -+ err = 0; -+ sb = dentry->d_sb; -+ a->bdst = au_dbtop(dentry); -+ a->h_path.dentry = au_h_dptr(dentry, a->bdst); -+ a->h_path.mnt = au_sbr_mnt(sb, a->bdst); -+ a->bsrc = au_ibtop(inode); -+ h_src_dentry = au_h_d_alias(src_dentry, a->bsrc); -+ if (!h_src_dentry && au_di(src_dentry)->di_tmpfile) -+ h_src_dentry = dget(au_hi_wh(inode, a->bsrc)); -+ if (!h_src_dentry) { -+ a->bsrc = au_dbtop(src_dentry); -+ h_src_dentry = au_h_d_alias(src_dentry, a->bsrc); -+ AuDebugOn(!h_src_dentry); -+ } else if (IS_ERR(h_src_dentry)) { -+ err = PTR_ERR(h_src_dentry); -+ goto out_parent; -+ } -+ -+ /* -+ * aufs doesn't touch the credential so -+ * security_dentry_create_files_as() is unnecessary. -+ */ -+ if (au_opt_test(au_mntflags(sb), PLINK)) { -+ if (a->bdst < a->bsrc -+ /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */) -+ err = au_cpup_or_link(src_dentry, dentry, a); -+ else { -+ delegated = NULL; -+ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin), -+ &a->h_path, &delegated); -+ if (unlikely(err == -EWOULDBLOCK)) { -+ pr_warn("cannot retry for NFSv4 delegation" -+ " for an internal link\n"); -+ iput(delegated); -+ } -+ } -+ dput(h_src_dentry); -+ } else { -+ /* -+ * copyup src_dentry to the branch we process, -+ * and then link(2) to it. -+ */ -+ dput(h_src_dentry); -+ if (a->bdst < a->bsrc -+ /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */) { -+ au_unpin(&a->pin); -+ di_write_unlock(a->parent); -+ err = au_cpup_before_link(src_dentry, a); -+ di_write_lock_parent(a->parent); -+ if (!err) -+ err = au_pin(&a->pin, dentry, a->bdst, -+ au_opt_udba(sb), -+ AuPin_DI_LOCKED | AuPin_MNT_WRITE); -+ if (unlikely(err)) -+ goto out_wh; -+ } -+ if (!err) { -+ h_src_dentry = au_h_dptr(src_dentry, a->bdst); -+ err = -ENOENT; -+ if (h_src_dentry && d_is_positive(h_src_dentry)) { -+ delegated = NULL; -+ err = vfsub_link(h_src_dentry, -+ au_pinned_h_dir(&a->pin), -+ &a->h_path, &delegated); -+ if (unlikely(err == -EWOULDBLOCK)) { -+ pr_warn("cannot retry" -+ " for NFSv4 delegation" -+ " for an internal link\n"); -+ iput(delegated); -+ } -+ } -+ } -+ } -+ if (unlikely(err)) -+ goto out_unpin; -+ -+ if (wh_dentry) { -+ a->h_path.dentry = wh_dentry; -+ err = au_wh_unlink_dentry(au_pinned_h_dir(&a->pin), &a->h_path, -+ dentry); -+ if (unlikely(err)) -+ goto out_revert; -+ } -+ -+ au_dir_ts(dir, a->bdst); -+ inode_inc_iversion(dir); -+ inc_nlink(inode); -+ inode->i_ctime = dir->i_ctime; -+ d_instantiate(dentry, au_igrab(inode)); -+ if (d_unhashed(a->h_path.dentry)) -+ /* some filesystem calls d_drop() */ -+ d_drop(dentry); -+ /* some filesystems consume an inode even hardlink */ -+ au_fhsm_wrote(sb, a->bdst, /*force*/0); -+ goto out_unpin; /* success */ -+ -+out_revert: -+ /* no delegation since it is just created */ -+ rerr = vfsub_unlink(au_pinned_h_dir(&a->pin), &a->h_path, -+ /*delegated*/NULL, /*force*/0); -+ if (unlikely(rerr)) { -+ AuIOErr("%pd reverting failed(%d, %d)\n", dentry, err, rerr); -+ err = -EIO; -+ } -+ au_dtime_revert(&dt); -+out_unpin: -+ au_unpin(&a->pin); -+out_wh: -+ dput(wh_dentry); -+out_parent: -+ di_write_unlock(a->parent); -+ dput(a->src_parent); -+out_unlock: -+ if (unlikely(err)) { -+ au_update_dbtop(dentry); -+ d_drop(dentry); -+ } -+ aufs_read_and_write_unlock2(dentry, src_dentry); -+out_kfree: -+ au_kfree_rcu(a); -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+int aufs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) -+{ -+ int err, rerr; -+ aufs_bindex_t bindex; -+ unsigned char diropq; -+ struct path h_path; -+ struct dentry *wh_dentry, *parent, *opq_dentry; -+ struct inode *h_inode; -+ struct super_block *sb; -+ struct { -+ struct au_pin pin; -+ struct au_dtime dt; -+ } *a; /* reduce the stack usage */ -+ struct au_wr_dir_args wr_dir_args = { -+ .force_btgt = -1, -+ .flags = AuWrDir_ADD_ENTRY | AuWrDir_ISDIR -+ }; -+ -+ IMustLock(dir); -+ -+ err = -ENOMEM; -+ a = kmalloc(sizeof(*a), GFP_NOFS); -+ if (unlikely(!a)) -+ goto out; -+ -+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN); -+ if (unlikely(err)) -+ goto out_free; -+ err = au_d_may_add(dentry); -+ if (unlikely(err)) -+ goto out_unlock; -+ -+ parent = dentry->d_parent; /* dir inode is locked */ -+ di_write_lock_parent(parent); -+ wh_dentry = lock_hdir_lkup_wh(dentry, &a->dt, /*src_dentry*/NULL, -+ &a->pin, &wr_dir_args); -+ err = PTR_ERR(wh_dentry); -+ if (IS_ERR(wh_dentry)) -+ goto out_parent; -+ -+ sb = dentry->d_sb; -+ bindex = au_dbtop(dentry); -+ h_path.dentry = au_h_dptr(dentry, bindex); -+ h_path.mnt = au_sbr_mnt(sb, bindex); -+ err = vfsub_mkdir(au_pinned_h_dir(&a->pin), &h_path, mode); -+ if (unlikely(err)) -+ goto out_unpin; -+ -+ /* make the dir opaque */ -+ diropq = 0; -+ h_inode = d_inode(h_path.dentry); -+ if (wh_dentry -+ || au_opt_test(au_mntflags(sb), ALWAYS_DIROPQ)) { -+ inode_lock_nested(h_inode, AuLsc_I_CHILD); -+ opq_dentry = au_diropq_create(dentry, bindex); -+ inode_unlock(h_inode); -+ err = PTR_ERR(opq_dentry); -+ if (IS_ERR(opq_dentry)) -+ goto out_dir; -+ dput(opq_dentry); -+ diropq = 1; -+ } -+ -+ err = epilog(dir, bindex, wh_dentry, dentry); -+ if (!err) { -+ inc_nlink(dir); -+ goto out_unpin; /* success */ -+ } -+ -+ /* revert */ -+ if (diropq) { -+ AuLabel(revert opq); -+ inode_lock_nested(h_inode, AuLsc_I_CHILD); -+ rerr = au_diropq_remove(dentry, bindex); -+ inode_unlock(h_inode); -+ if (rerr) { -+ AuIOErr("%pd reverting diropq failed(%d, %d)\n", -+ dentry, err, rerr); -+ err = -EIO; -+ } -+ } -+ -+out_dir: -+ AuLabel(revert dir); -+ rerr = vfsub_rmdir(au_pinned_h_dir(&a->pin), &h_path); -+ if (rerr) { -+ AuIOErr("%pd reverting dir failed(%d, %d)\n", -+ dentry, err, rerr); -+ err = -EIO; -+ } -+ au_dtime_revert(&a->dt); -+out_unpin: -+ au_unpin(&a->pin); -+ dput(wh_dentry); -+out_parent: -+ di_write_unlock(parent); -+out_unlock: -+ if (unlikely(err)) { -+ au_update_dbtop(dentry); -+ d_drop(dentry); -+ } -+ aufs_read_unlock(dentry, AuLock_DW); -+out_free: -+ au_kfree_rcu(a); -+out: -+ return err; -+} -diff -Nurp linux-5.6.3/fs/aufs/i_op.c linux-5.6.3-aufs/fs/aufs/i_op.c ---- linux-5.6.3/fs/aufs/i_op.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/i_op.c 2020-04-10 12:40:52.191049456 +0300 -@@ -0,0 +1,1485 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * inode operations (except add/del/rename) -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include "aufs.h" -+ -+static int h_permission(struct inode *h_inode, int mask, -+ struct path *h_path, int brperm) -+{ -+ int err; -+ const unsigned char write_mask = !!(mask & (MAY_WRITE | MAY_APPEND)); -+ -+ err = -EPERM; -+ if (write_mask && IS_IMMUTABLE(h_inode)) -+ goto out; -+ -+ err = -EACCES; -+ if (((mask & MAY_EXEC) -+ && S_ISREG(h_inode->i_mode) -+ && (path_noexec(h_path) -+ || !(h_inode->i_mode & 0111)))) -+ goto out; -+ -+ /* -+ * - skip the lower fs test in the case of write to ro branch. -+ * - nfs dir permission write check is optimized, but a policy for -+ * link/rename requires a real check. -+ * - nfs always sets SB_POSIXACL regardless its mount option 'noacl.' -+ * in this case, generic_permission() returns -EOPNOTSUPP. -+ */ -+ if ((write_mask && !au_br_writable(brperm)) -+ || (au_test_nfs(h_inode->i_sb) && S_ISDIR(h_inode->i_mode) -+ && write_mask && !(mask & MAY_READ)) -+ || !h_inode->i_op->permission) { -+ /* AuLabel(generic_permission); */ -+ /* AuDbg("get_acl %ps\n", h_inode->i_op->get_acl); */ -+ err = generic_permission(h_inode, mask); -+ if (err == -EOPNOTSUPP && au_test_nfs_noacl(h_inode)) -+ err = h_inode->i_op->permission(h_inode, mask); -+ AuTraceErr(err); -+ } else { -+ /* AuLabel(h_inode->permission); */ -+ err = h_inode->i_op->permission(h_inode, mask); -+ AuTraceErr(err); -+ } -+ -+ if (!err) -+ err = devcgroup_inode_permission(h_inode, mask); -+ if (!err) -+ err = security_inode_permission(h_inode, mask); -+ -+out: -+ return err; -+} -+ -+static int aufs_permission(struct inode *inode, int mask) -+{ -+ int err; -+ aufs_bindex_t bindex, bbot; -+ const unsigned char isdir = !!S_ISDIR(inode->i_mode), -+ write_mask = !!(mask & (MAY_WRITE | MAY_APPEND)); -+ struct inode *h_inode; -+ struct super_block *sb; -+ struct au_branch *br; -+ -+ /* todo: support rcu-walk? */ -+ if (mask & MAY_NOT_BLOCK) -+ return -ECHILD; -+ -+ sb = inode->i_sb; -+ si_read_lock(sb, AuLock_FLUSH); -+ ii_read_lock_child(inode); -+#if 0 /* reserved for future use */ -+ /* -+ * This test may be rather 'too much' since the test is essentially done -+ * in the aufs_lookup(). Theoretically it is possible that the inode -+ * generation doesn't match to the superblock's here. But it isn't a -+ * big deal I suppose. -+ */ -+ err = au_iigen_test(inode, au_sigen(sb)); -+ if (unlikely(err)) -+ goto out; -+#endif -+ -+ if (!isdir -+ || write_mask -+ || au_opt_test(au_mntflags(sb), DIRPERM1)) { -+ err = au_busy_or_stale(); -+ h_inode = au_h_iptr(inode, au_ibtop(inode)); -+ if (unlikely(!h_inode -+ || (h_inode->i_mode & S_IFMT) -+ != (inode->i_mode & S_IFMT))) -+ goto out; -+ -+ err = 0; -+ bindex = au_ibtop(inode); -+ br = au_sbr(sb, bindex); -+ err = h_permission(h_inode, mask, &br->br_path, br->br_perm); -+ if (write_mask -+ && !err -+ && !special_file(h_inode->i_mode)) { -+ /* test whether the upper writable branch exists */ -+ err = -EROFS; -+ for (; bindex >= 0; bindex--) -+ if (!au_br_rdonly(au_sbr(sb, bindex))) { -+ err = 0; -+ break; -+ } -+ } -+ goto out; -+ } -+ -+ /* non-write to dir */ -+ err = 0; -+ bbot = au_ibbot(inode); -+ for (bindex = au_ibtop(inode); !err && bindex <= bbot; bindex++) { -+ h_inode = au_h_iptr(inode, bindex); -+ if (h_inode) { -+ err = au_busy_or_stale(); -+ if (unlikely(!S_ISDIR(h_inode->i_mode))) -+ break; -+ -+ br = au_sbr(sb, bindex); -+ err = h_permission(h_inode, mask, &br->br_path, -+ br->br_perm); -+ } -+ } -+ -+out: -+ ii_read_unlock(inode); -+ si_read_unlock(sb); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static struct dentry *aufs_lookup(struct inode *dir, struct dentry *dentry, -+ unsigned int flags) -+{ -+ struct dentry *ret, *parent; -+ struct inode *inode; -+ struct super_block *sb; -+ int err, npositive; -+ -+ IMustLock(dir); -+ -+ /* todo: support rcu-walk? */ -+ ret = ERR_PTR(-ECHILD); -+ if (flags & LOOKUP_RCU) -+ goto out; -+ -+ ret = ERR_PTR(-ENAMETOOLONG); -+ if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN)) -+ goto out; -+ -+ sb = dir->i_sb; -+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM); -+ ret = ERR_PTR(err); -+ if (unlikely(err)) -+ goto out; -+ -+ err = au_di_init(dentry); -+ ret = ERR_PTR(err); -+ if (unlikely(err)) -+ goto out_si; -+ -+ inode = NULL; -+ npositive = 0; /* suppress a warning */ -+ parent = dentry->d_parent; /* dir inode is locked */ -+ di_read_lock_parent(parent, AuLock_IR); -+ err = au_alive_dir(parent); -+ if (!err) -+ err = au_digen_test(parent, au_sigen(sb)); -+ if (!err) { -+ /* regardless LOOKUP_CREATE, always ALLOW_NEG */ -+ npositive = au_lkup_dentry(dentry, au_dbtop(parent), -+ AuLkup_ALLOW_NEG); -+ err = npositive; -+ } -+ di_read_unlock(parent, AuLock_IR); -+ ret = ERR_PTR(err); -+ if (unlikely(err < 0)) -+ goto out_unlock; -+ -+ if (npositive) { -+ inode = au_new_inode(dentry, /*must_new*/0); -+ if (IS_ERR(inode)) { -+ ret = (void *)inode; -+ inode = NULL; -+ goto out_unlock; -+ } -+ } -+ -+ if (inode) -+ atomic_inc(&inode->i_count); -+ ret = d_splice_alias(inode, dentry); -+#if 0 /* reserved for future use */ -+ if (unlikely(d_need_lookup(dentry))) { -+ spin_lock(&dentry->d_lock); -+ dentry->d_flags &= ~DCACHE_NEED_LOOKUP; -+ spin_unlock(&dentry->d_lock); -+ } else -+#endif -+ if (inode) { -+ if (!IS_ERR(ret)) { -+ iput(inode); -+ if (ret && ret != dentry) -+ ii_write_unlock(inode); -+ } else { -+ ii_write_unlock(inode); -+ iput(inode); -+ inode = NULL; -+ } -+ } -+ -+out_unlock: -+ di_write_unlock(dentry); -+out_si: -+ si_read_unlock(sb); -+out: -+ return ret; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * very dirty and complicated aufs ->atomic_open(). -+ * aufs_atomic_open() -+ * + au_aopen_or_create() -+ * + add_simple() -+ * + vfsub_atomic_open() -+ * + branch fs ->atomic_open() -+ * may call the actual 'open' for h_file -+ * + inc br_nfiles only if opened -+ * + au_aopen_no_open() or au_aopen_do_open() -+ * -+ * au_aopen_do_open() -+ * + finish_open() -+ * + au_do_aopen() -+ * + au_do_open() the body of all 'open' -+ * + au_do_open_nondir() -+ * set the passed h_file -+ * -+ * au_aopen_no_open() -+ * + finish_no_open() -+ */ -+ -+struct aopen_node { -+ struct hlist_bl_node hblist; -+ struct file *file, *h_file; -+}; -+ -+static int au_do_aopen(struct inode *inode, struct file *file) -+{ -+ struct hlist_bl_head *aopen; -+ struct hlist_bl_node *pos; -+ struct aopen_node *node; -+ struct au_do_open_args args = { -+ .aopen = 1, -+ .open = au_do_open_nondir -+ }; -+ -+ aopen = &au_sbi(inode->i_sb)->si_aopen; -+ hlist_bl_lock(aopen); -+ hlist_bl_for_each_entry(node, pos, aopen, hblist) -+ if (node->file == file) { -+ args.h_file = node->h_file; -+ break; -+ } -+ hlist_bl_unlock(aopen); -+ /* AuDebugOn(!args.h_file); */ -+ -+ return au_do_open(file, &args); -+} -+ -+static int au_aopen_do_open(struct file *file, struct dentry *dentry, -+ struct aopen_node *aopen_node) -+{ -+ int err; -+ struct hlist_bl_head *aopen; -+ -+ AuLabel(here); -+ aopen = &au_sbi(dentry->d_sb)->si_aopen; -+ au_hbl_add(&aopen_node->hblist, aopen); -+ err = finish_open(file, dentry, au_do_aopen); -+ au_hbl_del(&aopen_node->hblist, aopen); -+ /* AuDbgFile(file); */ -+ AuDbg("%pd%s%s\n", dentry, -+ (file->f_mode & FMODE_CREATED) ? " created" : "", -+ (file->f_mode & FMODE_OPENED) ? " opened" : ""); -+ -+ AuTraceErr(err); -+ return err; -+} -+ -+static int au_aopen_no_open(struct file *file, struct dentry *dentry) -+{ -+ int err; -+ -+ AuLabel(here); -+ dget(dentry); -+ err = finish_no_open(file, dentry); -+ -+ AuTraceErr(err); -+ return err; -+} -+ -+static int aufs_atomic_open(struct inode *dir, struct dentry *dentry, -+ struct file *file, unsigned int open_flag, -+ umode_t create_mode) -+{ -+ int err, did_open; -+ unsigned int lkup_flags; -+ aufs_bindex_t bindex; -+ struct super_block *sb; -+ struct dentry *parent, *d; -+ struct vfsub_aopen_args args = { -+ .open_flag = open_flag, -+ .create_mode = create_mode -+ }; -+ struct aopen_node aopen_node = { -+ .file = file -+ }; -+ -+ IMustLock(dir); -+ AuDbg("open_flag 0%o\n", open_flag); -+ AuDbgDentry(dentry); -+ -+ err = 0; -+ if (!au_di(dentry)) { -+ lkup_flags = LOOKUP_OPEN; -+ if (open_flag & O_CREAT) -+ lkup_flags |= LOOKUP_CREATE; -+ d = aufs_lookup(dir, dentry, lkup_flags); -+ if (IS_ERR(d)) { -+ err = PTR_ERR(d); -+ AuTraceErr(err); -+ goto out; -+ } else if (d) { -+ /* -+ * obsoleted dentry found. -+ * another error will be returned later. -+ */ -+ d_drop(d); -+ AuDbgDentry(d); -+ dput(d); -+ } -+ AuDbgDentry(dentry); -+ } -+ -+ if (d_is_positive(dentry) -+ || d_unhashed(dentry) -+ || d_unlinked(dentry) -+ || !(open_flag & O_CREAT)) { -+ err = au_aopen_no_open(file, dentry); -+ goto out; /* success */ -+ } -+ -+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH | AuLock_GEN); -+ if (unlikely(err)) -+ goto out; -+ -+ sb = dentry->d_sb; -+ parent = dentry->d_parent; /* dir is locked */ -+ di_write_lock_parent(parent); -+ err = au_lkup_dentry(dentry, /*btop*/0, AuLkup_ALLOW_NEG); -+ if (unlikely(err < 0)) -+ goto out_parent; -+ -+ AuDbgDentry(dentry); -+ if (d_is_positive(dentry)) { -+ err = au_aopen_no_open(file, dentry); -+ goto out_parent; /* success */ -+ } -+ -+ args.file = alloc_empty_file(file->f_flags, current_cred()); -+ err = PTR_ERR(args.file); -+ if (IS_ERR(args.file)) -+ goto out_parent; -+ -+ bindex = au_dbtop(dentry); -+ err = au_aopen_or_create(dir, dentry, &args); -+ AuTraceErr(err); -+ AuDbgFile(args.file); -+ file->f_mode = args.file->f_mode & ~FMODE_OPENED; -+ did_open = !!(args.file->f_mode & FMODE_OPENED); -+ if (!did_open) { -+ fput(args.file); -+ args.file = NULL; -+ } -+ di_write_unlock(parent); -+ di_write_unlock(dentry); -+ if (unlikely(err < 0)) { -+ if (args.file) -+ fput(args.file); -+ goto out_sb; -+ } -+ -+ if (!did_open) -+ err = au_aopen_no_open(file, dentry); -+ else { -+ aopen_node.h_file = args.file; -+ err = au_aopen_do_open(file, dentry, &aopen_node); -+ } -+ if (unlikely(err < 0)) { -+ if (args.file) -+ fput(args.file); -+ if (did_open) -+ au_lcnt_dec(&args.br->br_nfiles); -+ } -+ goto out_sb; /* success */ -+ -+out_parent: -+ di_write_unlock(parent); -+ di_write_unlock(dentry); -+out_sb: -+ si_read_unlock(sb); -+out: -+ AuTraceErr(err); -+ AuDbgFile(file); -+ return err; -+} -+ -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int au_wr_dir_cpup(struct dentry *dentry, struct dentry *parent, -+ const unsigned char add_entry, aufs_bindex_t bcpup, -+ aufs_bindex_t btop) -+{ -+ int err; -+ struct dentry *h_parent; -+ struct inode *h_dir; -+ -+ if (add_entry) -+ IMustLock(d_inode(parent)); -+ else -+ di_write_lock_parent(parent); -+ -+ err = 0; -+ if (!au_h_dptr(parent, bcpup)) { -+ if (btop > bcpup) -+ err = au_cpup_dirs(dentry, bcpup); -+ else if (btop < bcpup) -+ err = au_cpdown_dirs(dentry, bcpup); -+ else -+ BUG(); -+ } -+ if (!err && add_entry && !au_ftest_wrdir(add_entry, TMPFILE)) { -+ h_parent = au_h_dptr(parent, bcpup); -+ h_dir = d_inode(h_parent); -+ inode_lock_shared_nested(h_dir, AuLsc_I_PARENT); -+ err = au_lkup_neg(dentry, bcpup, /*wh*/0); -+ /* todo: no unlock here */ -+ inode_unlock_shared(h_dir); -+ -+ AuDbg("bcpup %d\n", bcpup); -+ if (!err) { -+ if (d_really_is_negative(dentry)) -+ au_set_h_dptr(dentry, btop, NULL); -+ au_update_dbrange(dentry, /*do_put_zero*/0); -+ } -+ } -+ -+ if (!add_entry) -+ di_write_unlock(parent); -+ if (!err) -+ err = bcpup; /* success */ -+ -+ AuTraceErr(err); -+ return err; -+} -+ -+/* -+ * decide the branch and the parent dir where we will create a new entry. -+ * returns new bindex or an error. -+ * copyup the parent dir if needed. -+ */ -+int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry, -+ struct au_wr_dir_args *args) -+{ -+ int err; -+ unsigned int flags; -+ aufs_bindex_t bcpup, btop, src_btop; -+ const unsigned char add_entry -+ = au_ftest_wrdir(args->flags, ADD_ENTRY) -+ | au_ftest_wrdir(args->flags, TMPFILE); -+ struct super_block *sb; -+ struct dentry *parent; -+ struct au_sbinfo *sbinfo; -+ -+ sb = dentry->d_sb; -+ sbinfo = au_sbi(sb); -+ parent = dget_parent(dentry); -+ btop = au_dbtop(dentry); -+ bcpup = btop; -+ if (args->force_btgt < 0) { -+ if (src_dentry) { -+ src_btop = au_dbtop(src_dentry); -+ if (src_btop < btop) -+ bcpup = src_btop; -+ } else if (add_entry) { -+ flags = 0; -+ if (au_ftest_wrdir(args->flags, ISDIR)) -+ au_fset_wbr(flags, DIR); -+ err = AuWbrCreate(sbinfo, dentry, flags); -+ bcpup = err; -+ } -+ -+ if (bcpup < 0 || au_test_ro(sb, bcpup, d_inode(dentry))) { -+ if (add_entry) -+ err = AuWbrCopyup(sbinfo, dentry); -+ else { -+ if (!IS_ROOT(dentry)) { -+ di_read_lock_parent(parent, !AuLock_IR); -+ err = AuWbrCopyup(sbinfo, dentry); -+ di_read_unlock(parent, !AuLock_IR); -+ } else -+ err = AuWbrCopyup(sbinfo, dentry); -+ } -+ bcpup = err; -+ if (unlikely(err < 0)) -+ goto out; -+ } -+ } else { -+ bcpup = args->force_btgt; -+ AuDebugOn(au_test_ro(sb, bcpup, d_inode(dentry))); -+ } -+ -+ AuDbg("btop %d, bcpup %d\n", btop, bcpup); -+ err = bcpup; -+ if (bcpup == btop) -+ goto out; /* success */ -+ -+ /* copyup the new parent into the branch we process */ -+ err = au_wr_dir_cpup(dentry, parent, add_entry, bcpup, btop); -+ if (err >= 0) { -+ if (d_really_is_negative(dentry)) { -+ au_set_h_dptr(dentry, btop, NULL); -+ au_set_dbtop(dentry, bcpup); -+ au_set_dbbot(dentry, bcpup); -+ } -+ AuDebugOn(add_entry -+ && !au_ftest_wrdir(args->flags, TMPFILE) -+ && !au_h_dptr(dentry, bcpup)); -+ } -+ -+out: -+ dput(parent); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+void au_pin_hdir_unlock(struct au_pin *p) -+{ -+ if (p->hdir) -+ au_hn_inode_unlock(p->hdir); -+} -+ -+int au_pin_hdir_lock(struct au_pin *p) -+{ -+ int err; -+ -+ err = 0; -+ if (!p->hdir) -+ goto out; -+ -+ /* even if an error happens later, keep this lock */ -+ au_hn_inode_lock_nested(p->hdir, p->lsc_hi); -+ -+ err = -EBUSY; -+ if (unlikely(p->hdir->hi_inode != d_inode(p->h_parent))) -+ goto out; -+ -+ err = 0; -+ if (p->h_dentry) -+ err = au_h_verify(p->h_dentry, p->udba, p->hdir->hi_inode, -+ p->h_parent, p->br); -+ -+out: -+ return err; -+} -+ -+int au_pin_hdir_relock(struct au_pin *p) -+{ -+ int err, i; -+ struct inode *h_i; -+ struct dentry *h_d[] = { -+ p->h_dentry, -+ p->h_parent -+ }; -+ -+ err = au_pin_hdir_lock(p); -+ if (unlikely(err)) -+ goto out; -+ -+ for (i = 0; !err && i < sizeof(h_d)/sizeof(*h_d); i++) { -+ if (!h_d[i]) -+ continue; -+ if (d_is_positive(h_d[i])) { -+ h_i = d_inode(h_d[i]); -+ err = !h_i->i_nlink; -+ } -+ } -+ -+out: -+ return err; -+} -+ -+static void au_pin_hdir_set_owner(struct au_pin *p, struct task_struct *task) -+{ -+ atomic_long_set(&p->hdir->hi_inode->i_rwsem.owner, (long)task); -+} -+ -+void au_pin_hdir_acquire_nest(struct au_pin *p) -+{ -+ if (p->hdir) { -+ rwsem_acquire_nest(&p->hdir->hi_inode->i_rwsem.dep_map, -+ p->lsc_hi, 0, NULL, _RET_IP_); -+ au_pin_hdir_set_owner(p, current); -+ } -+} -+ -+void au_pin_hdir_release(struct au_pin *p) -+{ -+ if (p->hdir) { -+ au_pin_hdir_set_owner(p, p->task); -+ rwsem_release(&p->hdir->hi_inode->i_rwsem.dep_map, _RET_IP_); -+ } -+} -+ -+struct dentry *au_pinned_h_parent(struct au_pin *pin) -+{ -+ if (pin && pin->parent) -+ return au_h_dptr(pin->parent, pin->bindex); -+ return NULL; -+} -+ -+void au_unpin(struct au_pin *p) -+{ -+ if (p->hdir) -+ au_pin_hdir_unlock(p); -+ if (p->h_mnt && au_ftest_pin(p->flags, MNT_WRITE)) -+ vfsub_mnt_drop_write(p->h_mnt); -+ if (!p->hdir) -+ return; -+ -+ if (!au_ftest_pin(p->flags, DI_LOCKED)) -+ di_read_unlock(p->parent, AuLock_IR); -+ iput(p->hdir->hi_inode); -+ dput(p->parent); -+ p->parent = NULL; -+ p->hdir = NULL; -+ p->h_mnt = NULL; -+ /* do not clear p->task */ -+} -+ -+int au_do_pin(struct au_pin *p) -+{ -+ int err; -+ struct super_block *sb; -+ struct inode *h_dir; -+ -+ err = 0; -+ sb = p->dentry->d_sb; -+ p->br = au_sbr(sb, p->bindex); -+ if (IS_ROOT(p->dentry)) { -+ if (au_ftest_pin(p->flags, MNT_WRITE)) { -+ p->h_mnt = au_br_mnt(p->br); -+ err = vfsub_mnt_want_write(p->h_mnt); -+ if (unlikely(err)) { -+ au_fclr_pin(p->flags, MNT_WRITE); -+ goto out_err; -+ } -+ } -+ goto out; -+ } -+ -+ p->h_dentry = NULL; -+ if (p->bindex <= au_dbbot(p->dentry)) -+ p->h_dentry = au_h_dptr(p->dentry, p->bindex); -+ -+ p->parent = dget_parent(p->dentry); -+ if (!au_ftest_pin(p->flags, DI_LOCKED)) -+ di_read_lock(p->parent, AuLock_IR, p->lsc_di); -+ -+ h_dir = NULL; -+ p->h_parent = au_h_dptr(p->parent, p->bindex); -+ p->hdir = au_hi(d_inode(p->parent), p->bindex); -+ if (p->hdir) -+ h_dir = p->hdir->hi_inode; -+ -+ /* -+ * udba case, or -+ * if DI_LOCKED is not set, then p->parent may be different -+ * and h_parent can be NULL. -+ */ -+ if (unlikely(!p->hdir || !h_dir || !p->h_parent)) { -+ err = -EBUSY; -+ if (!au_ftest_pin(p->flags, DI_LOCKED)) -+ di_read_unlock(p->parent, AuLock_IR); -+ dput(p->parent); -+ p->parent = NULL; -+ goto out_err; -+ } -+ -+ if (au_ftest_pin(p->flags, MNT_WRITE)) { -+ p->h_mnt = au_br_mnt(p->br); -+ err = vfsub_mnt_want_write(p->h_mnt); -+ if (unlikely(err)) { -+ au_fclr_pin(p->flags, MNT_WRITE); -+ if (!au_ftest_pin(p->flags, DI_LOCKED)) -+ di_read_unlock(p->parent, AuLock_IR); -+ dput(p->parent); -+ p->parent = NULL; -+ goto out_err; -+ } -+ } -+ -+ au_igrab(h_dir); -+ err = au_pin_hdir_lock(p); -+ if (!err) -+ goto out; /* success */ -+ -+ au_unpin(p); -+ -+out_err: -+ pr_err("err %d\n", err); -+ err = au_busy_or_stale(); -+out: -+ return err; -+} -+ -+void au_pin_init(struct au_pin *p, struct dentry *dentry, -+ aufs_bindex_t bindex, int lsc_di, int lsc_hi, -+ unsigned int udba, unsigned char flags) -+{ -+ p->dentry = dentry; -+ p->udba = udba; -+ p->lsc_di = lsc_di; -+ p->lsc_hi = lsc_hi; -+ p->flags = flags; -+ p->bindex = bindex; -+ -+ p->parent = NULL; -+ p->hdir = NULL; -+ p->h_mnt = NULL; -+ -+ p->h_dentry = NULL; -+ p->h_parent = NULL; -+ p->br = NULL; -+ p->task = current; -+} -+ -+int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex, -+ unsigned int udba, unsigned char flags) -+{ -+ au_pin_init(pin, dentry, bindex, AuLsc_DI_PARENT, AuLsc_I_PARENT2, -+ udba, flags); -+ return au_do_pin(pin); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * ->setattr() and ->getattr() are called in various cases. -+ * chmod, stat: dentry is revalidated. -+ * fchmod, fstat: file and dentry are not revalidated, additionally they may be -+ * unhashed. -+ * for ->setattr(), ia->ia_file is passed from ftruncate only. -+ */ -+/* todo: consolidate with do_refresh() and simple_reval_dpath() */ -+int au_reval_for_attr(struct dentry *dentry, unsigned int sigen) -+{ -+ int err; -+ struct dentry *parent; -+ -+ err = 0; -+ if (au_digen_test(dentry, sigen)) { -+ parent = dget_parent(dentry); -+ di_read_lock_parent(parent, AuLock_IR); -+ err = au_refresh_dentry(dentry, parent); -+ di_read_unlock(parent, AuLock_IR); -+ dput(parent); -+ } -+ -+ AuTraceErr(err); -+ return err; -+} -+ -+int au_pin_and_icpup(struct dentry *dentry, struct iattr *ia, -+ struct au_icpup_args *a) -+{ -+ int err; -+ loff_t sz; -+ aufs_bindex_t btop, ibtop; -+ struct dentry *hi_wh, *parent; -+ struct inode *inode; -+ struct au_wr_dir_args wr_dir_args = { -+ .force_btgt = -1, -+ .flags = 0 -+ }; -+ -+ if (d_is_dir(dentry)) -+ au_fset_wrdir(wr_dir_args.flags, ISDIR); -+ /* plink or hi_wh() case */ -+ btop = au_dbtop(dentry); -+ inode = d_inode(dentry); -+ ibtop = au_ibtop(inode); -+ if (btop != ibtop && !au_test_ro(inode->i_sb, ibtop, inode)) -+ wr_dir_args.force_btgt = ibtop; -+ err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args); -+ if (unlikely(err < 0)) -+ goto out; -+ a->btgt = err; -+ if (err != btop) -+ au_fset_icpup(a->flags, DID_CPUP); -+ -+ err = 0; -+ a->pin_flags = AuPin_MNT_WRITE; -+ parent = NULL; -+ if (!IS_ROOT(dentry)) { -+ au_fset_pin(a->pin_flags, DI_LOCKED); -+ parent = dget_parent(dentry); -+ di_write_lock_parent(parent); -+ } -+ -+ err = au_pin(&a->pin, dentry, a->btgt, a->udba, a->pin_flags); -+ if (unlikely(err)) -+ goto out_parent; -+ -+ sz = -1; -+ a->h_path.dentry = au_h_dptr(dentry, btop); -+ a->h_inode = d_inode(a->h_path.dentry); -+ if (ia && (ia->ia_valid & ATTR_SIZE)) { -+ inode_lock_shared_nested(a->h_inode, AuLsc_I_CHILD); -+ if (ia->ia_size < i_size_read(a->h_inode)) -+ sz = ia->ia_size; -+ inode_unlock_shared(a->h_inode); -+ } -+ -+ hi_wh = NULL; -+ if (au_ftest_icpup(a->flags, DID_CPUP) && d_unlinked(dentry)) { -+ hi_wh = au_hi_wh(inode, a->btgt); -+ if (!hi_wh) { -+ struct au_cp_generic cpg = { -+ .dentry = dentry, -+ .bdst = a->btgt, -+ .bsrc = -1, -+ .len = sz, -+ .pin = &a->pin -+ }; -+ err = au_sio_cpup_wh(&cpg, /*file*/NULL); -+ if (unlikely(err)) -+ goto out_unlock; -+ hi_wh = au_hi_wh(inode, a->btgt); -+ /* todo: revalidate hi_wh? */ -+ } -+ } -+ -+ if (parent) { -+ au_pin_set_parent_lflag(&a->pin, /*lflag*/0); -+ di_downgrade_lock(parent, AuLock_IR); -+ dput(parent); -+ parent = NULL; -+ } -+ if (!au_ftest_icpup(a->flags, DID_CPUP)) -+ goto out; /* success */ -+ -+ if (!d_unhashed(dentry)) { -+ struct au_cp_generic cpg = { -+ .dentry = dentry, -+ .bdst = a->btgt, -+ .bsrc = btop, -+ .len = sz, -+ .pin = &a->pin, -+ .flags = AuCpup_DTIME | AuCpup_HOPEN -+ }; -+ err = au_sio_cpup_simple(&cpg); -+ if (!err) -+ a->h_path.dentry = au_h_dptr(dentry, a->btgt); -+ } else if (!hi_wh) -+ a->h_path.dentry = au_h_dptr(dentry, a->btgt); -+ else -+ a->h_path.dentry = hi_wh; /* do not dget here */ -+ -+out_unlock: -+ a->h_inode = d_inode(a->h_path.dentry); -+ if (!err) -+ goto out; /* success */ -+ au_unpin(&a->pin); -+out_parent: -+ if (parent) { -+ di_write_unlock(parent); -+ dput(parent); -+ } -+out: -+ if (!err) -+ inode_lock_nested(a->h_inode, AuLsc_I_CHILD); -+ return err; -+} -+ -+static int aufs_setattr(struct dentry *dentry, struct iattr *ia) -+{ -+ int err; -+ struct inode *inode, *delegated; -+ struct super_block *sb; -+ struct file *file; -+ struct au_icpup_args *a; -+ -+ inode = d_inode(dentry); -+ IMustLock(inode); -+ -+ err = setattr_prepare(dentry, ia); -+ if (unlikely(err)) -+ goto out; -+ -+ err = -ENOMEM; -+ a = kzalloc(sizeof(*a), GFP_NOFS); -+ if (unlikely(!a)) -+ goto out; -+ -+ if (ia->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID)) -+ ia->ia_valid &= ~ATTR_MODE; -+ -+ file = NULL; -+ sb = dentry->d_sb; -+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM); -+ if (unlikely(err)) -+ goto out_kfree; -+ -+ if (ia->ia_valid & ATTR_FILE) { -+ /* currently ftruncate(2) only */ -+ AuDebugOn(!d_is_reg(dentry)); -+ file = ia->ia_file; -+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1, -+ /*fi_lsc*/0); -+ if (unlikely(err)) -+ goto out_si; -+ ia->ia_file = au_hf_top(file); -+ a->udba = AuOpt_UDBA_NONE; -+ } else { -+ /* fchmod() doesn't pass ia_file */ -+ a->udba = au_opt_udba(sb); -+ di_write_lock_child(dentry); -+ /* no d_unlinked(), to set UDBA_NONE for root */ -+ if (d_unhashed(dentry)) -+ a->udba = AuOpt_UDBA_NONE; -+ if (a->udba != AuOpt_UDBA_NONE) { -+ AuDebugOn(IS_ROOT(dentry)); -+ err = au_reval_for_attr(dentry, au_sigen(sb)); -+ if (unlikely(err)) -+ goto out_dentry; -+ } -+ } -+ -+ err = au_pin_and_icpup(dentry, ia, a); -+ if (unlikely(err < 0)) -+ goto out_dentry; -+ if (au_ftest_icpup(a->flags, DID_CPUP)) { -+ ia->ia_file = NULL; -+ ia->ia_valid &= ~ATTR_FILE; -+ } -+ -+ a->h_path.mnt = au_sbr_mnt(sb, a->btgt); -+ if ((ia->ia_valid & (ATTR_MODE | ATTR_CTIME)) -+ == (ATTR_MODE | ATTR_CTIME)) { -+ err = security_path_chmod(&a->h_path, ia->ia_mode); -+ if (unlikely(err)) -+ goto out_unlock; -+ } else if ((ia->ia_valid & (ATTR_UID | ATTR_GID)) -+ && (ia->ia_valid & ATTR_CTIME)) { -+ err = security_path_chown(&a->h_path, ia->ia_uid, ia->ia_gid); -+ if (unlikely(err)) -+ goto out_unlock; -+ } -+ -+ if (ia->ia_valid & ATTR_SIZE) { -+ struct file *f; -+ -+ if (ia->ia_size < i_size_read(inode)) -+ /* unmap only */ -+ truncate_setsize(inode, ia->ia_size); -+ -+ f = NULL; -+ if (ia->ia_valid & ATTR_FILE) -+ f = ia->ia_file; -+ inode_unlock(a->h_inode); -+ err = vfsub_trunc(&a->h_path, ia->ia_size, ia->ia_valid, f); -+ inode_lock_nested(a->h_inode, AuLsc_I_CHILD); -+ } else { -+ delegated = NULL; -+ while (1) { -+ err = vfsub_notify_change(&a->h_path, ia, &delegated); -+ if (delegated) { -+ err = break_deleg_wait(&delegated); -+ if (!err) -+ continue; -+ } -+ break; -+ } -+ } -+ /* -+ * regardless aufs 'acl' option setting. -+ * why don't all acl-aware fs call this func from their ->setattr()? -+ */ -+ if (!err && (ia->ia_valid & ATTR_MODE)) -+ err = vfsub_acl_chmod(a->h_inode, ia->ia_mode); -+ if (!err) -+ au_cpup_attr_changeable(inode); -+ -+out_unlock: -+ inode_unlock(a->h_inode); -+ au_unpin(&a->pin); -+ if (unlikely(err)) -+ au_update_dbtop(dentry); -+out_dentry: -+ di_write_unlock(dentry); -+ if (file) { -+ fi_write_unlock(file); -+ ia->ia_file = file; -+ ia->ia_valid |= ATTR_FILE; -+ } -+out_si: -+ si_read_unlock(sb); -+out_kfree: -+ au_kfree_rcu(a); -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+#if IS_ENABLED(CONFIG_AUFS_XATTR) || IS_ENABLED(CONFIG_FS_POSIX_ACL) -+static int au_h_path_to_set_attr(struct dentry *dentry, -+ struct au_icpup_args *a, struct path *h_path) -+{ -+ int err; -+ struct super_block *sb; -+ -+ sb = dentry->d_sb; -+ a->udba = au_opt_udba(sb); -+ /* no d_unlinked(), to set UDBA_NONE for root */ -+ if (d_unhashed(dentry)) -+ a->udba = AuOpt_UDBA_NONE; -+ if (a->udba != AuOpt_UDBA_NONE) { -+ AuDebugOn(IS_ROOT(dentry)); -+ err = au_reval_for_attr(dentry, au_sigen(sb)); -+ if (unlikely(err)) -+ goto out; -+ } -+ err = au_pin_and_icpup(dentry, /*ia*/NULL, a); -+ if (unlikely(err < 0)) -+ goto out; -+ -+ h_path->dentry = a->h_path.dentry; -+ h_path->mnt = au_sbr_mnt(sb, a->btgt); -+ -+out: -+ return err; -+} -+ -+ssize_t au_sxattr(struct dentry *dentry, struct inode *inode, -+ struct au_sxattr *arg) -+{ -+ int err; -+ struct path h_path; -+ struct super_block *sb; -+ struct au_icpup_args *a; -+ struct inode *h_inode; -+ -+ IMustLock(inode); -+ -+ err = -ENOMEM; -+ a = kzalloc(sizeof(*a), GFP_NOFS); -+ if (unlikely(!a)) -+ goto out; -+ -+ sb = dentry->d_sb; -+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM); -+ if (unlikely(err)) -+ goto out_kfree; -+ -+ h_path.dentry = NULL; /* silence gcc */ -+ di_write_lock_child(dentry); -+ err = au_h_path_to_set_attr(dentry, a, &h_path); -+ if (unlikely(err)) -+ goto out_di; -+ -+ inode_unlock(a->h_inode); -+ switch (arg->type) { -+ case AU_XATTR_SET: -+ AuDebugOn(d_is_negative(h_path.dentry)); -+ err = vfsub_setxattr(h_path.dentry, -+ arg->u.set.name, arg->u.set.value, -+ arg->u.set.size, arg->u.set.flags); -+ break; -+ case AU_ACL_SET: -+ err = -EOPNOTSUPP; -+ h_inode = d_inode(h_path.dentry); -+ if (h_inode->i_op->set_acl) -+ /* this will call posix_acl_update_mode */ -+ err = h_inode->i_op->set_acl(h_inode, -+ arg->u.acl_set.acl, -+ arg->u.acl_set.type); -+ break; -+ } -+ if (!err) -+ au_cpup_attr_timesizes(inode); -+ -+ au_unpin(&a->pin); -+ if (unlikely(err)) -+ au_update_dbtop(dentry); -+ -+out_di: -+ di_write_unlock(dentry); -+ si_read_unlock(sb); -+out_kfree: -+ au_kfree_rcu(a); -+out: -+ AuTraceErr(err); -+ return err; -+} -+#endif -+ -+static void au_refresh_iattr(struct inode *inode, struct kstat *st, -+ unsigned int nlink) -+{ -+ unsigned int n; -+ -+ inode->i_mode = st->mode; -+ /* don't i_[ug]id_write() here */ -+ inode->i_uid = st->uid; -+ inode->i_gid = st->gid; -+ inode->i_atime = st->atime; -+ inode->i_mtime = st->mtime; -+ inode->i_ctime = st->ctime; -+ -+ au_cpup_attr_nlink(inode, /*force*/0); -+ if (S_ISDIR(inode->i_mode)) { -+ n = inode->i_nlink; -+ n -= nlink; -+ n += st->nlink; -+ smp_mb(); /* for i_nlink */ -+ /* 0 can happen */ -+ set_nlink(inode, n); -+ } -+ -+ spin_lock(&inode->i_lock); -+ inode->i_blocks = st->blocks; -+ i_size_write(inode, st->size); -+ spin_unlock(&inode->i_lock); -+} -+ -+/* -+ * common routine for aufs_getattr() and au_getxattr(). -+ * returns zero or negative (an error). -+ * @dentry will be read-locked in success. -+ */ -+int au_h_path_getattr(struct dentry *dentry, int force, struct path *h_path, -+ int locked) -+{ -+ int err; -+ unsigned int mnt_flags, sigen; -+ unsigned char udba_none; -+ aufs_bindex_t bindex; -+ struct super_block *sb, *h_sb; -+ struct inode *inode; -+ -+ h_path->mnt = NULL; -+ h_path->dentry = NULL; -+ -+ err = 0; -+ sb = dentry->d_sb; -+ mnt_flags = au_mntflags(sb); -+ udba_none = !!au_opt_test(mnt_flags, UDBA_NONE); -+ -+ if (unlikely(locked)) -+ goto body; /* skip locking dinfo */ -+ -+ /* support fstat(2) */ -+ if (!d_unlinked(dentry) && !udba_none) { -+ sigen = au_sigen(sb); -+ err = au_digen_test(dentry, sigen); -+ if (!err) { -+ di_read_lock_child(dentry, AuLock_IR); -+ err = au_dbrange_test(dentry); -+ if (unlikely(err)) { -+ di_read_unlock(dentry, AuLock_IR); -+ goto out; -+ } -+ } else { -+ AuDebugOn(IS_ROOT(dentry)); -+ di_write_lock_child(dentry); -+ err = au_dbrange_test(dentry); -+ if (!err) -+ err = au_reval_for_attr(dentry, sigen); -+ if (!err) -+ di_downgrade_lock(dentry, AuLock_IR); -+ else { -+ di_write_unlock(dentry); -+ goto out; -+ } -+ } -+ } else -+ di_read_lock_child(dentry, AuLock_IR); -+ -+body: -+ inode = d_inode(dentry); -+ bindex = au_ibtop(inode); -+ h_path->mnt = au_sbr_mnt(sb, bindex); -+ h_sb = h_path->mnt->mnt_sb; -+ if (!force -+ && !au_test_fs_bad_iattr(h_sb) -+ && udba_none) -+ goto out; /* success */ -+ -+ if (au_dbtop(dentry) == bindex) -+ h_path->dentry = au_h_dptr(dentry, bindex); -+ else if (au_opt_test(mnt_flags, PLINK) && au_plink_test(inode)) { -+ h_path->dentry = au_plink_lkup(inode, bindex); -+ if (IS_ERR(h_path->dentry)) -+ /* pretending success */ -+ h_path->dentry = NULL; -+ else -+ dput(h_path->dentry); -+ } -+ -+out: -+ return err; -+} -+ -+static int aufs_getattr(const struct path *path, struct kstat *st, -+ u32 request, unsigned int query) -+{ -+ int err; -+ unsigned char positive; -+ struct path h_path; -+ struct dentry *dentry; -+ struct inode *inode; -+ struct super_block *sb; -+ -+ dentry = path->dentry; -+ inode = d_inode(dentry); -+ sb = dentry->d_sb; -+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM); -+ if (unlikely(err)) -+ goto out; -+ err = au_h_path_getattr(dentry, /*force*/0, &h_path, /*locked*/0); -+ if (unlikely(err)) -+ goto out_si; -+ if (unlikely(!h_path.dentry)) -+ /* illegally overlapped or something */ -+ goto out_fill; /* pretending success */ -+ -+ positive = d_is_positive(h_path.dentry); -+ if (positive) -+ /* no vfsub version */ -+ err = vfs_getattr(&h_path, st, request, query); -+ if (!err) { -+ if (positive) -+ au_refresh_iattr(inode, st, -+ d_inode(h_path.dentry)->i_nlink); -+ goto out_fill; /* success */ -+ } -+ AuTraceErr(err); -+ goto out_di; -+ -+out_fill: -+ generic_fillattr(inode, st); -+out_di: -+ di_read_unlock(dentry, AuLock_IR); -+out_si: -+ si_read_unlock(sb); -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static const char *aufs_get_link(struct dentry *dentry, struct inode *inode, -+ struct delayed_call *done) -+{ -+ const char *ret; -+ struct dentry *h_dentry; -+ struct inode *h_inode; -+ int err; -+ aufs_bindex_t bindex; -+ -+ ret = NULL; /* suppress a warning */ -+ err = -ECHILD; -+ if (!dentry) -+ goto out; -+ -+ err = aufs_read_lock(dentry, AuLock_IR | AuLock_GEN); -+ if (unlikely(err)) -+ goto out; -+ -+ err = au_d_hashed_positive(dentry); -+ if (unlikely(err)) -+ goto out_unlock; -+ -+ err = -EINVAL; -+ inode = d_inode(dentry); -+ bindex = au_ibtop(inode); -+ h_inode = au_h_iptr(inode, bindex); -+ if (unlikely(!h_inode->i_op->get_link)) -+ goto out_unlock; -+ -+ err = -EBUSY; -+ h_dentry = NULL; -+ if (au_dbtop(dentry) <= bindex) { -+ h_dentry = au_h_dptr(dentry, bindex); -+ if (h_dentry) -+ dget(h_dentry); -+ } -+ if (!h_dentry) { -+ h_dentry = d_find_any_alias(h_inode); -+ if (IS_ERR(h_dentry)) { -+ err = PTR_ERR(h_dentry); -+ goto out_unlock; -+ } -+ } -+ if (unlikely(!h_dentry)) -+ goto out_unlock; -+ -+ err = 0; -+ AuDbg("%ps\n", h_inode->i_op->get_link); -+ AuDbgDentry(h_dentry); -+ ret = vfs_get_link(h_dentry, done); -+ dput(h_dentry); -+ if (IS_ERR(ret)) -+ err = PTR_ERR(ret); -+ -+out_unlock: -+ aufs_read_unlock(dentry, AuLock_IR); -+out: -+ if (unlikely(err)) -+ ret = ERR_PTR(err); -+ AuTraceErrPtr(ret); -+ return ret; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int au_is_special(struct inode *inode) -+{ -+ return (inode->i_mode & (S_IFBLK | S_IFCHR | S_IFIFO | S_IFSOCK)); -+} -+ -+static int aufs_update_time(struct inode *inode, struct timespec64 *ts, -+ int flags) -+{ -+ int err; -+ aufs_bindex_t bindex; -+ struct super_block *sb; -+ struct inode *h_inode; -+ struct vfsmount *h_mnt; -+ -+ sb = inode->i_sb; -+ WARN_ONCE((flags & S_ATIME) && !IS_NOATIME(inode), -+ "unexpected s_flags 0x%lx", sb->s_flags); -+ -+ /* mmap_sem might be acquired already, cf. aufs_mmap() */ -+ lockdep_off(); -+ si_read_lock(sb, AuLock_FLUSH); -+ ii_write_lock_child(inode); -+ -+ err = 0; -+ bindex = au_ibtop(inode); -+ h_inode = au_h_iptr(inode, bindex); -+ if (!au_test_ro(sb, bindex, inode)) { -+ h_mnt = au_sbr_mnt(sb, bindex); -+ err = vfsub_mnt_want_write(h_mnt); -+ if (!err) { -+ err = vfsub_update_time(h_inode, ts, flags); -+ vfsub_mnt_drop_write(h_mnt); -+ } -+ } else if (au_is_special(h_inode)) { -+ /* -+ * Never copy-up here. -+ * These special files may already be opened and used for -+ * communicating. If we copied it up, then the communication -+ * would be corrupted. -+ */ -+ AuWarn1("timestamps for i%lu are ignored " -+ "since it is on readonly branch (hi%lu).\n", -+ inode->i_ino, h_inode->i_ino); -+ } else if (flags & ~S_ATIME) { -+ err = -EIO; -+ AuIOErr1("unexpected flags 0x%x\n", flags); -+ AuDebugOn(1); -+ } -+ -+ if (!err) -+ au_cpup_attr_timesizes(inode); -+ ii_write_unlock(inode); -+ si_read_unlock(sb); -+ lockdep_on(); -+ -+ if (!err && (flags & S_VERSION)) -+ inode_inc_iversion(inode); -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* no getattr version will be set by module.c:aufs_init() */ -+struct inode_operations aufs_iop_nogetattr[AuIop_Last], -+ aufs_iop[] = { -+ [AuIop_SYMLINK] = { -+ .permission = aufs_permission, -+#ifdef CONFIG_FS_POSIX_ACL -+ .get_acl = aufs_get_acl, -+ .set_acl = aufs_set_acl, /* unsupport for symlink? */ -+#endif -+ -+ .setattr = aufs_setattr, -+ .getattr = aufs_getattr, -+ -+#ifdef CONFIG_AUFS_XATTR -+ .listxattr = aufs_listxattr, -+#endif -+ -+ .get_link = aufs_get_link, -+ -+ /* .update_time = aufs_update_time */ -+ }, -+ [AuIop_DIR] = { -+ .create = aufs_create, -+ .lookup = aufs_lookup, -+ .link = aufs_link, -+ .unlink = aufs_unlink, -+ .symlink = aufs_symlink, -+ .mkdir = aufs_mkdir, -+ .rmdir = aufs_rmdir, -+ .mknod = aufs_mknod, -+ .rename = aufs_rename, -+ -+ .permission = aufs_permission, -+#ifdef CONFIG_FS_POSIX_ACL -+ .get_acl = aufs_get_acl, -+ .set_acl = aufs_set_acl, -+#endif -+ -+ .setattr = aufs_setattr, -+ .getattr = aufs_getattr, -+ -+#ifdef CONFIG_AUFS_XATTR -+ .listxattr = aufs_listxattr, -+#endif -+ -+ .update_time = aufs_update_time, -+ .atomic_open = aufs_atomic_open, -+ .tmpfile = aufs_tmpfile -+ }, -+ [AuIop_OTHER] = { -+ .permission = aufs_permission, -+#ifdef CONFIG_FS_POSIX_ACL -+ .get_acl = aufs_get_acl, -+ .set_acl = aufs_set_acl, -+#endif -+ -+ .setattr = aufs_setattr, -+ .getattr = aufs_getattr, -+ -+#ifdef CONFIG_AUFS_XATTR -+ .listxattr = aufs_listxattr, -+#endif -+ -+ .update_time = aufs_update_time -+ } -+}; -diff -Nurp linux-5.6.3/fs/aufs/i_op_del.c linux-5.6.3-aufs/fs/aufs/i_op_del.c ---- linux-5.6.3/fs/aufs/i_op_del.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/i_op_del.c 2020-04-10 12:40:52.191049456 +0300 -@@ -0,0 +1,500 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * inode operations (del entry) -+ */ -+ -+#include -+#include "aufs.h" -+ -+/* -+ * decide if a new whiteout for @dentry is necessary or not. -+ * when it is necessary, prepare the parent dir for the upper branch whose -+ * branch index is @bcpup for creation. the actual creation of the whiteout will -+ * be done by caller. -+ * return value: -+ * 0: wh is unnecessary -+ * plus: wh is necessary -+ * minus: error -+ */ -+int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup) -+{ -+ int need_wh, err; -+ aufs_bindex_t btop; -+ struct super_block *sb; -+ -+ sb = dentry->d_sb; -+ btop = au_dbtop(dentry); -+ if (*bcpup < 0) { -+ *bcpup = btop; -+ if (au_test_ro(sb, btop, d_inode(dentry))) { -+ err = AuWbrCopyup(au_sbi(sb), dentry); -+ *bcpup = err; -+ if (unlikely(err < 0)) -+ goto out; -+ } -+ } else -+ AuDebugOn(btop < *bcpup -+ || au_test_ro(sb, *bcpup, d_inode(dentry))); -+ AuDbg("bcpup %d, btop %d\n", *bcpup, btop); -+ -+ if (*bcpup != btop) { -+ err = au_cpup_dirs(dentry, *bcpup); -+ if (unlikely(err)) -+ goto out; -+ need_wh = 1; -+ } else { -+ struct au_dinfo *dinfo, *tmp; -+ -+ need_wh = -ENOMEM; -+ dinfo = au_di(dentry); -+ tmp = au_di_alloc(sb, AuLsc_DI_TMP); -+ if (tmp) { -+ au_di_cp(tmp, dinfo); -+ au_di_swap(tmp, dinfo); -+ /* returns the number of positive dentries */ -+ need_wh = au_lkup_dentry(dentry, btop + 1, -+ /* AuLkup_IGNORE_PERM */ 0); -+ au_di_swap(tmp, dinfo); -+ au_rw_write_unlock(&tmp->di_rwsem); -+ au_di_free(tmp); -+ } -+ } -+ AuDbg("need_wh %d\n", need_wh); -+ err = need_wh; -+ -+out: -+ return err; -+} -+ -+/* -+ * simple tests for the del-entry operations. -+ * following the checks in vfs, plus the parent-child relationship. -+ */ -+int au_may_del(struct dentry *dentry, aufs_bindex_t bindex, -+ struct dentry *h_parent, int isdir) -+{ -+ int err; -+ umode_t h_mode; -+ struct dentry *h_dentry, *h_latest; -+ struct inode *h_inode; -+ -+ h_dentry = au_h_dptr(dentry, bindex); -+ if (d_really_is_positive(dentry)) { -+ err = -ENOENT; -+ if (unlikely(d_is_negative(h_dentry))) -+ goto out; -+ h_inode = d_inode(h_dentry); -+ if (unlikely(!h_inode->i_nlink)) -+ goto out; -+ -+ h_mode = h_inode->i_mode; -+ if (!isdir) { -+ err = -EISDIR; -+ if (unlikely(S_ISDIR(h_mode))) -+ goto out; -+ } else if (unlikely(!S_ISDIR(h_mode))) { -+ err = -ENOTDIR; -+ goto out; -+ } -+ } else { -+ /* rename(2) case */ -+ err = -EIO; -+ if (unlikely(d_is_positive(h_dentry))) -+ goto out; -+ } -+ -+ err = -ENOENT; -+ /* expected parent dir is locked */ -+ if (unlikely(h_parent != h_dentry->d_parent)) -+ goto out; -+ err = 0; -+ -+ /* -+ * rmdir a dir may break the consistency on some filesystem. -+ * let's try heavy test. -+ */ -+ err = -EACCES; -+ if (unlikely(!au_opt_test(au_mntflags(dentry->d_sb), DIRPERM1) -+ && au_test_h_perm(d_inode(h_parent), -+ MAY_EXEC | MAY_WRITE))) -+ goto out; -+ -+ h_latest = au_sio_lkup_one(&dentry->d_name, h_parent); -+ err = -EIO; -+ if (IS_ERR(h_latest)) -+ goto out; -+ if (h_latest == h_dentry) -+ err = 0; -+ dput(h_latest); -+ -+out: -+ return err; -+} -+ -+/* -+ * decide the branch where we operate for @dentry. the branch index will be set -+ * @rbcpup. after deciding it, 'pin' it and store the timestamps of the parent -+ * dir for reverting. -+ * when a new whiteout is necessary, create it. -+ */ -+static struct dentry* -+lock_hdir_create_wh(struct dentry *dentry, int isdir, aufs_bindex_t *rbcpup, -+ struct au_dtime *dt, struct au_pin *pin) -+{ -+ struct dentry *wh_dentry; -+ struct super_block *sb; -+ struct path h_path; -+ int err, need_wh; -+ unsigned int udba; -+ aufs_bindex_t bcpup; -+ -+ need_wh = au_wr_dir_need_wh(dentry, isdir, rbcpup); -+ wh_dentry = ERR_PTR(need_wh); -+ if (unlikely(need_wh < 0)) -+ goto out; -+ -+ sb = dentry->d_sb; -+ udba = au_opt_udba(sb); -+ bcpup = *rbcpup; -+ err = au_pin(pin, dentry, bcpup, udba, -+ AuPin_DI_LOCKED | AuPin_MNT_WRITE); -+ wh_dentry = ERR_PTR(err); -+ if (unlikely(err)) -+ goto out; -+ -+ h_path.dentry = au_pinned_h_parent(pin); -+ if (udba != AuOpt_UDBA_NONE -+ && au_dbtop(dentry) == bcpup) { -+ err = au_may_del(dentry, bcpup, h_path.dentry, isdir); -+ wh_dentry = ERR_PTR(err); -+ if (unlikely(err)) -+ goto out_unpin; -+ } -+ -+ h_path.mnt = au_sbr_mnt(sb, bcpup); -+ au_dtime_store(dt, au_pinned_parent(pin), &h_path); -+ wh_dentry = NULL; -+ if (!need_wh) -+ goto out; /* success, no need to create whiteout */ -+ -+ wh_dentry = au_wh_create(dentry, bcpup, h_path.dentry); -+ if (IS_ERR(wh_dentry)) -+ goto out_unpin; -+ -+ /* returns with the parent is locked and wh_dentry is dget-ed */ -+ goto out; /* success */ -+ -+out_unpin: -+ au_unpin(pin); -+out: -+ return wh_dentry; -+} -+ -+/* -+ * when removing a dir, rename it to a unique temporary whiteout-ed name first -+ * in order to be revertible and save time for removing many child whiteouts -+ * under the dir. -+ * returns 1 when there are too many child whiteout and caller should remove -+ * them asynchronously. returns 0 when the number of children is enough small to -+ * remove now or the branch fs is a remote fs. -+ * otherwise return an error. -+ */ -+static int renwh_and_rmdir(struct dentry *dentry, aufs_bindex_t bindex, -+ struct au_nhash *whlist, struct inode *dir) -+{ -+ int rmdir_later, err, dirwh; -+ struct dentry *h_dentry; -+ struct super_block *sb; -+ struct inode *inode; -+ -+ sb = dentry->d_sb; -+ SiMustAnyLock(sb); -+ h_dentry = au_h_dptr(dentry, bindex); -+ err = au_whtmp_ren(h_dentry, au_sbr(sb, bindex)); -+ if (unlikely(err)) -+ goto out; -+ -+ /* stop monitoring */ -+ inode = d_inode(dentry); -+ au_hn_free(au_hi(inode, bindex)); -+ -+ if (!au_test_fs_remote(h_dentry->d_sb)) { -+ dirwh = au_sbi(sb)->si_dirwh; -+ rmdir_later = (dirwh <= 1); -+ if (!rmdir_later) -+ rmdir_later = au_nhash_test_longer_wh(whlist, bindex, -+ dirwh); -+ if (rmdir_later) -+ return rmdir_later; -+ } -+ -+ err = au_whtmp_rmdir(dir, bindex, h_dentry, whlist); -+ if (unlikely(err)) { -+ AuIOErr("rmdir %pd, b%d failed, %d. ignored\n", -+ h_dentry, bindex, err); -+ err = 0; -+ } -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+/* -+ * final procedure for deleting a entry. -+ * maintain dentry and iattr. -+ */ -+static void epilog(struct inode *dir, struct dentry *dentry, -+ aufs_bindex_t bindex) -+{ -+ struct inode *inode; -+ -+ inode = d_inode(dentry); -+ d_drop(dentry); -+ inode->i_ctime = dir->i_ctime; -+ -+ au_dir_ts(dir, bindex); -+ inode_inc_iversion(dir); -+} -+ -+/* -+ * when an error happened, remove the created whiteout and revert everything. -+ */ -+static int do_revert(int err, struct inode *dir, aufs_bindex_t bindex, -+ aufs_bindex_t bwh, struct dentry *wh_dentry, -+ struct dentry *dentry, struct au_dtime *dt) -+{ -+ int rerr; -+ struct path h_path = { -+ .dentry = wh_dentry, -+ .mnt = au_sbr_mnt(dir->i_sb, bindex) -+ }; -+ -+ rerr = au_wh_unlink_dentry(au_h_iptr(dir, bindex), &h_path, dentry); -+ if (!rerr) { -+ au_set_dbwh(dentry, bwh); -+ au_dtime_revert(dt); -+ return 0; -+ } -+ -+ AuIOErr("%pd reverting whiteout failed(%d, %d)\n", dentry, err, rerr); -+ return -EIO; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+int aufs_unlink(struct inode *dir, struct dentry *dentry) -+{ -+ int err; -+ aufs_bindex_t bwh, bindex, btop; -+ struct inode *inode, *h_dir, *delegated; -+ struct dentry *parent, *wh_dentry; -+ /* to reduce stack size */ -+ struct { -+ struct au_dtime dt; -+ struct au_pin pin; -+ struct path h_path; -+ } *a; -+ -+ IMustLock(dir); -+ -+ err = -ENOMEM; -+ a = kmalloc(sizeof(*a), GFP_NOFS); -+ if (unlikely(!a)) -+ goto out; -+ -+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN); -+ if (unlikely(err)) -+ goto out_free; -+ err = au_d_hashed_positive(dentry); -+ if (unlikely(err)) -+ goto out_unlock; -+ inode = d_inode(dentry); -+ IMustLock(inode); -+ err = -EISDIR; -+ if (unlikely(d_is_dir(dentry))) -+ goto out_unlock; /* possible? */ -+ -+ btop = au_dbtop(dentry); -+ bwh = au_dbwh(dentry); -+ bindex = -1; -+ parent = dentry->d_parent; /* dir inode is locked */ -+ di_write_lock_parent(parent); -+ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/0, &bindex, &a->dt, -+ &a->pin); -+ err = PTR_ERR(wh_dentry); -+ if (IS_ERR(wh_dentry)) -+ goto out_parent; -+ -+ a->h_path.mnt = au_sbr_mnt(dentry->d_sb, btop); -+ a->h_path.dentry = au_h_dptr(dentry, btop); -+ dget(a->h_path.dentry); -+ if (bindex == btop) { -+ h_dir = au_pinned_h_dir(&a->pin); -+ delegated = NULL; -+ err = vfsub_unlink(h_dir, &a->h_path, &delegated, /*force*/0); -+ if (unlikely(err == -EWOULDBLOCK)) { -+ pr_warn("cannot retry for NFSv4 delegation" -+ " for an internal unlink\n"); -+ iput(delegated); -+ } -+ } else { -+ /* dir inode is locked */ -+ h_dir = d_inode(wh_dentry->d_parent); -+ IMustLock(h_dir); -+ err = 0; -+ } -+ -+ if (!err) { -+ vfsub_drop_nlink(inode); -+ epilog(dir, dentry, bindex); -+ -+ /* update target timestamps */ -+ if (bindex == btop) { -+ vfsub_update_h_iattr(&a->h_path, /*did*/NULL); -+ /*ignore*/ -+ inode->i_ctime = d_inode(a->h_path.dentry)->i_ctime; -+ } else -+ /* todo: this timestamp may be reverted later */ -+ inode->i_ctime = h_dir->i_ctime; -+ goto out_unpin; /* success */ -+ } -+ -+ /* revert */ -+ if (wh_dentry) { -+ int rerr; -+ -+ rerr = do_revert(err, dir, bindex, bwh, wh_dentry, dentry, -+ &a->dt); -+ if (rerr) -+ err = rerr; -+ } -+ -+out_unpin: -+ au_unpin(&a->pin); -+ dput(wh_dentry); -+ dput(a->h_path.dentry); -+out_parent: -+ di_write_unlock(parent); -+out_unlock: -+ aufs_read_unlock(dentry, AuLock_DW); -+out_free: -+ au_kfree_rcu(a); -+out: -+ return err; -+} -+ -+int aufs_rmdir(struct inode *dir, struct dentry *dentry) -+{ -+ int err, rmdir_later; -+ aufs_bindex_t bwh, bindex, btop; -+ struct inode *inode; -+ struct dentry *parent, *wh_dentry, *h_dentry; -+ struct au_whtmp_rmdir *args; -+ /* to reduce stack size */ -+ struct { -+ struct au_dtime dt; -+ struct au_pin pin; -+ } *a; -+ -+ IMustLock(dir); -+ -+ err = -ENOMEM; -+ a = kmalloc(sizeof(*a), GFP_NOFS); -+ if (unlikely(!a)) -+ goto out; -+ -+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH | AuLock_GEN); -+ if (unlikely(err)) -+ goto out_free; -+ err = au_alive_dir(dentry); -+ if (unlikely(err)) -+ goto out_unlock; -+ inode = d_inode(dentry); -+ IMustLock(inode); -+ err = -ENOTDIR; -+ if (unlikely(!d_is_dir(dentry))) -+ goto out_unlock; /* possible? */ -+ -+ err = -ENOMEM; -+ args = au_whtmp_rmdir_alloc(dir->i_sb, GFP_NOFS); -+ if (unlikely(!args)) -+ goto out_unlock; -+ -+ parent = dentry->d_parent; /* dir inode is locked */ -+ di_write_lock_parent(parent); -+ err = au_test_empty(dentry, &args->whlist); -+ if (unlikely(err)) -+ goto out_parent; -+ -+ btop = au_dbtop(dentry); -+ bwh = au_dbwh(dentry); -+ bindex = -1; -+ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/1, &bindex, &a->dt, -+ &a->pin); -+ err = PTR_ERR(wh_dentry); -+ if (IS_ERR(wh_dentry)) -+ goto out_parent; -+ -+ h_dentry = au_h_dptr(dentry, btop); -+ dget(h_dentry); -+ rmdir_later = 0; -+ if (bindex == btop) { -+ err = renwh_and_rmdir(dentry, btop, &args->whlist, dir); -+ if (err > 0) { -+ rmdir_later = err; -+ err = 0; -+ } -+ } else { -+ /* stop monitoring */ -+ au_hn_free(au_hi(inode, btop)); -+ -+ /* dir inode is locked */ -+ IMustLock(d_inode(wh_dentry->d_parent)); -+ err = 0; -+ } -+ -+ if (!err) { -+ vfsub_dead_dir(inode); -+ au_set_dbdiropq(dentry, -1); -+ epilog(dir, dentry, bindex); -+ -+ if (rmdir_later) { -+ au_whtmp_kick_rmdir(dir, btop, h_dentry, args); -+ args = NULL; -+ } -+ -+ goto out_unpin; /* success */ -+ } -+ -+ /* revert */ -+ AuLabel(revert); -+ if (wh_dentry) { -+ int rerr; -+ -+ rerr = do_revert(err, dir, bindex, bwh, wh_dentry, dentry, -+ &a->dt); -+ if (rerr) -+ err = rerr; -+ } -+ -+out_unpin: -+ au_unpin(&a->pin); -+ dput(wh_dentry); -+ dput(h_dentry); -+out_parent: -+ di_write_unlock(parent); -+ if (args) -+ au_whtmp_rmdir_free(args); -+out_unlock: -+ aufs_read_unlock(dentry, AuLock_DW); -+out_free: -+ au_kfree_rcu(a); -+out: -+ AuTraceErr(err); -+ return err; -+} -diff -Nurp linux-5.6.3/fs/aufs/i_op_ren.c linux-5.6.3-aufs/fs/aufs/i_op_ren.c ---- linux-5.6.3/fs/aufs/i_op_ren.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/i_op_ren.c 2020-04-10 12:40:52.191049456 +0300 -@@ -0,0 +1,1237 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * inode operation (rename entry) -+ * todo: this is crazy monster -+ */ -+ -+#include -+#include "aufs.h" -+ -+enum { AuSRC, AuDST, AuSrcDst }; -+enum { AuPARENT, AuCHILD, AuParentChild }; -+ -+#define AuRen_ISDIR_SRC 1 -+#define AuRen_ISDIR_DST (1 << 1) -+#define AuRen_ISSAMEDIR (1 << 2) -+#define AuRen_WHSRC (1 << 3) -+#define AuRen_WHDST (1 << 4) -+#define AuRen_MNT_WRITE (1 << 5) -+#define AuRen_DT_DSTDIR (1 << 6) -+#define AuRen_DIROPQ_SRC (1 << 7) -+#define AuRen_DIROPQ_DST (1 << 8) -+#define AuRen_DIRREN (1 << 9) -+#define AuRen_DROPPED_SRC (1 << 10) -+#define AuRen_DROPPED_DST (1 << 11) -+#define au_ftest_ren(flags, name) ((flags) & AuRen_##name) -+#define au_fset_ren(flags, name) \ -+ do { (flags) |= AuRen_##name; } while (0) -+#define au_fclr_ren(flags, name) \ -+ do { (flags) &= ~AuRen_##name; } while (0) -+ -+#ifndef CONFIG_AUFS_DIRREN -+#undef AuRen_DIRREN -+#define AuRen_DIRREN 0 -+#endif -+ -+struct au_ren_args { -+ struct { -+ struct dentry *dentry, *h_dentry, *parent, *h_parent, -+ *wh_dentry; -+ struct inode *dir, *inode; -+ struct au_hinode *hdir, *hinode; -+ struct au_dtime dt[AuParentChild]; -+ aufs_bindex_t btop, bdiropq; -+ } sd[AuSrcDst]; -+ -+#define src_dentry sd[AuSRC].dentry -+#define src_dir sd[AuSRC].dir -+#define src_inode sd[AuSRC].inode -+#define src_h_dentry sd[AuSRC].h_dentry -+#define src_parent sd[AuSRC].parent -+#define src_h_parent sd[AuSRC].h_parent -+#define src_wh_dentry sd[AuSRC].wh_dentry -+#define src_hdir sd[AuSRC].hdir -+#define src_hinode sd[AuSRC].hinode -+#define src_h_dir sd[AuSRC].hdir->hi_inode -+#define src_dt sd[AuSRC].dt -+#define src_btop sd[AuSRC].btop -+#define src_bdiropq sd[AuSRC].bdiropq -+ -+#define dst_dentry sd[AuDST].dentry -+#define dst_dir sd[AuDST].dir -+#define dst_inode sd[AuDST].inode -+#define dst_h_dentry sd[AuDST].h_dentry -+#define dst_parent sd[AuDST].parent -+#define dst_h_parent sd[AuDST].h_parent -+#define dst_wh_dentry sd[AuDST].wh_dentry -+#define dst_hdir sd[AuDST].hdir -+#define dst_hinode sd[AuDST].hinode -+#define dst_h_dir sd[AuDST].hdir->hi_inode -+#define dst_dt sd[AuDST].dt -+#define dst_btop sd[AuDST].btop -+#define dst_bdiropq sd[AuDST].bdiropq -+ -+ struct dentry *h_trap; -+ struct au_branch *br; -+ struct path h_path; -+ struct au_nhash whlist; -+ aufs_bindex_t btgt, src_bwh; -+ -+ struct { -+ unsigned short auren_flags; -+ unsigned char flags; /* syscall parameter */ -+ unsigned char exchange; -+ } __packed; -+ -+ struct au_whtmp_rmdir *thargs; -+ struct dentry *h_dst; -+ struct au_hinode *h_root; -+}; -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * functions for reverting. -+ * when an error happened in a single rename systemcall, we should revert -+ * everything as if nothing happened. -+ * we don't need to revert the copied-up/down the parent dir since they are -+ * harmless. -+ */ -+ -+#define RevertFailure(fmt, ...) do { \ -+ AuIOErr("revert failure: " fmt " (%d, %d)\n", \ -+ ##__VA_ARGS__, err, rerr); \ -+ err = -EIO; \ -+} while (0) -+ -+static void au_ren_do_rev_diropq(int err, struct au_ren_args *a, int idx) -+{ -+ int rerr; -+ struct dentry *d; -+#define src_or_dst(member) a->sd[idx].member -+ -+ d = src_or_dst(dentry); /* {src,dst}_dentry */ -+ au_hn_inode_lock_nested(src_or_dst(hinode), AuLsc_I_CHILD); -+ rerr = au_diropq_remove(d, a->btgt); -+ au_hn_inode_unlock(src_or_dst(hinode)); -+ au_set_dbdiropq(d, src_or_dst(bdiropq)); -+ if (rerr) -+ RevertFailure("remove diropq %pd", d); -+ -+#undef src_or_dst_ -+} -+ -+static void au_ren_rev_diropq(int err, struct au_ren_args *a) -+{ -+ if (au_ftest_ren(a->auren_flags, DIROPQ_SRC)) -+ au_ren_do_rev_diropq(err, a, AuSRC); -+ if (au_ftest_ren(a->auren_flags, DIROPQ_DST)) -+ au_ren_do_rev_diropq(err, a, AuDST); -+} -+ -+static void au_ren_rev_rename(int err, struct au_ren_args *a) -+{ -+ int rerr; -+ struct inode *delegated; -+ -+ a->h_path.dentry = vfsub_lkup_one(&a->src_dentry->d_name, -+ a->src_h_parent); -+ rerr = PTR_ERR(a->h_path.dentry); -+ if (IS_ERR(a->h_path.dentry)) { -+ RevertFailure("lkup one %pd", a->src_dentry); -+ return; -+ } -+ -+ delegated = NULL; -+ rerr = vfsub_rename(a->dst_h_dir, -+ au_h_dptr(a->src_dentry, a->btgt), -+ a->src_h_dir, &a->h_path, &delegated, a->flags); -+ if (unlikely(rerr == -EWOULDBLOCK)) { -+ pr_warn("cannot retry for NFSv4 delegation" -+ " for an internal rename\n"); -+ iput(delegated); -+ } -+ d_drop(a->h_path.dentry); -+ dput(a->h_path.dentry); -+ /* au_set_h_dptr(a->src_dentry, a->btgt, NULL); */ -+ if (rerr) -+ RevertFailure("rename %pd", a->src_dentry); -+} -+ -+static void au_ren_rev_whtmp(int err, struct au_ren_args *a) -+{ -+ int rerr; -+ struct inode *delegated; -+ -+ a->h_path.dentry = vfsub_lkup_one(&a->dst_dentry->d_name, -+ a->dst_h_parent); -+ rerr = PTR_ERR(a->h_path.dentry); -+ if (IS_ERR(a->h_path.dentry)) { -+ RevertFailure("lkup one %pd", a->dst_dentry); -+ return; -+ } -+ if (d_is_positive(a->h_path.dentry)) { -+ d_drop(a->h_path.dentry); -+ dput(a->h_path.dentry); -+ return; -+ } -+ -+ delegated = NULL; -+ rerr = vfsub_rename(a->dst_h_dir, a->h_dst, a->dst_h_dir, &a->h_path, -+ &delegated, a->flags); -+ if (unlikely(rerr == -EWOULDBLOCK)) { -+ pr_warn("cannot retry for NFSv4 delegation" -+ " for an internal rename\n"); -+ iput(delegated); -+ } -+ d_drop(a->h_path.dentry); -+ dput(a->h_path.dentry); -+ if (!rerr) -+ au_set_h_dptr(a->dst_dentry, a->btgt, dget(a->h_dst)); -+ else -+ RevertFailure("rename %pd", a->h_dst); -+} -+ -+static void au_ren_rev_whsrc(int err, struct au_ren_args *a) -+{ -+ int rerr; -+ -+ a->h_path.dentry = a->src_wh_dentry; -+ rerr = au_wh_unlink_dentry(a->src_h_dir, &a->h_path, a->src_dentry); -+ au_set_dbwh(a->src_dentry, a->src_bwh); -+ if (rerr) -+ RevertFailure("unlink %pd", a->src_wh_dentry); -+} -+#undef RevertFailure -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * when we have to copyup the renaming entry, do it with the rename-target name -+ * in order to minimize the cost (the later actual rename is unnecessary). -+ * otherwise rename it on the target branch. -+ */ -+static int au_ren_or_cpup(struct au_ren_args *a) -+{ -+ int err; -+ struct dentry *d; -+ struct inode *delegated; -+ -+ d = a->src_dentry; -+ if (au_dbtop(d) == a->btgt) { -+ a->h_path.dentry = a->dst_h_dentry; -+ AuDebugOn(au_dbtop(d) != a->btgt); -+ delegated = NULL; -+ err = vfsub_rename(a->src_h_dir, au_h_dptr(d, a->btgt), -+ a->dst_h_dir, &a->h_path, &delegated, -+ a->flags); -+ if (unlikely(err == -EWOULDBLOCK)) { -+ pr_warn("cannot retry for NFSv4 delegation" -+ " for an internal rename\n"); -+ iput(delegated); -+ } -+ } else -+ BUG(); -+ -+ if (!err && a->h_dst) -+ /* it will be set to dinfo later */ -+ dget(a->h_dst); -+ -+ return err; -+} -+ -+/* cf. aufs_rmdir() */ -+static int au_ren_del_whtmp(struct au_ren_args *a) -+{ -+ int err; -+ struct inode *dir; -+ -+ dir = a->dst_dir; -+ SiMustAnyLock(dir->i_sb); -+ if (!au_nhash_test_longer_wh(&a->whlist, a->btgt, -+ au_sbi(dir->i_sb)->si_dirwh) -+ || au_test_fs_remote(a->h_dst->d_sb)) { -+ err = au_whtmp_rmdir(dir, a->btgt, a->h_dst, &a->whlist); -+ if (unlikely(err)) -+ pr_warn("failed removing whtmp dir %pd (%d), " -+ "ignored.\n", a->h_dst, err); -+ } else { -+ au_nhash_wh_free(&a->thargs->whlist); -+ a->thargs->whlist = a->whlist; -+ a->whlist.nh_num = 0; -+ au_whtmp_kick_rmdir(dir, a->btgt, a->h_dst, a->thargs); -+ dput(a->h_dst); -+ a->thargs = NULL; -+ } -+ -+ return 0; -+} -+ -+/* make it 'opaque' dir. */ -+static int au_ren_do_diropq(struct au_ren_args *a, int idx) -+{ -+ int err; -+ struct dentry *d, *diropq; -+#define src_or_dst(member) a->sd[idx].member -+ -+ err = 0; -+ d = src_or_dst(dentry); /* {src,dst}_dentry */ -+ src_or_dst(bdiropq) = au_dbdiropq(d); -+ src_or_dst(hinode) = au_hi(src_or_dst(inode), a->btgt); -+ au_hn_inode_lock_nested(src_or_dst(hinode), AuLsc_I_CHILD); -+ diropq = au_diropq_create(d, a->btgt); -+ au_hn_inode_unlock(src_or_dst(hinode)); -+ if (IS_ERR(diropq)) -+ err = PTR_ERR(diropq); -+ else -+ dput(diropq); -+ -+#undef src_or_dst_ -+ return err; -+} -+ -+static int au_ren_diropq(struct au_ren_args *a) -+{ -+ int err; -+ unsigned char always; -+ struct dentry *d; -+ -+ err = 0; -+ d = a->dst_dentry; /* already renamed on the branch */ -+ always = !!au_opt_test(au_mntflags(d->d_sb), ALWAYS_DIROPQ); -+ if (au_ftest_ren(a->auren_flags, ISDIR_SRC) -+ && !au_ftest_ren(a->auren_flags, DIRREN) -+ && a->btgt != au_dbdiropq(a->src_dentry) -+ && (a->dst_wh_dentry -+ || a->btgt <= au_dbdiropq(d) -+ /* hide the lower to keep xino */ -+ /* the lowers may not be a dir, but we hide them anyway */ -+ || a->btgt < au_dbbot(d) -+ || always)) { -+ AuDbg("here\n"); -+ err = au_ren_do_diropq(a, AuSRC); -+ if (unlikely(err)) -+ goto out; -+ au_fset_ren(a->auren_flags, DIROPQ_SRC); -+ } -+ if (!a->exchange) -+ goto out; /* success */ -+ -+ d = a->src_dentry; /* already renamed on the branch */ -+ if (au_ftest_ren(a->auren_flags, ISDIR_DST) -+ && a->btgt != au_dbdiropq(a->dst_dentry) -+ && (a->btgt < au_dbdiropq(d) -+ || a->btgt < au_dbbot(d) -+ || always)) { -+ AuDbgDentry(a->src_dentry); -+ AuDbgDentry(a->dst_dentry); -+ err = au_ren_do_diropq(a, AuDST); -+ if (unlikely(err)) -+ goto out_rev_src; -+ au_fset_ren(a->auren_flags, DIROPQ_DST); -+ } -+ goto out; /* success */ -+ -+out_rev_src: -+ AuDbg("err %d, reverting src\n", err); -+ au_ren_rev_diropq(err, a); -+out: -+ return err; -+} -+ -+static int do_rename(struct au_ren_args *a) -+{ -+ int err; -+ struct dentry *d, *h_d; -+ -+ if (!a->exchange) { -+ /* prepare workqueue args for asynchronous rmdir */ -+ h_d = a->dst_h_dentry; -+ if (au_ftest_ren(a->auren_flags, ISDIR_DST) -+ /* && !au_ftest_ren(a->auren_flags, DIRREN) */ -+ && d_is_positive(h_d)) { -+ err = -ENOMEM; -+ a->thargs = au_whtmp_rmdir_alloc(a->src_dentry->d_sb, -+ GFP_NOFS); -+ if (unlikely(!a->thargs)) -+ goto out; -+ a->h_dst = dget(h_d); -+ } -+ -+ /* create whiteout for src_dentry */ -+ if (au_ftest_ren(a->auren_flags, WHSRC)) { -+ a->src_bwh = au_dbwh(a->src_dentry); -+ AuDebugOn(a->src_bwh >= 0); -+ a->src_wh_dentry = au_wh_create(a->src_dentry, a->btgt, -+ a->src_h_parent); -+ err = PTR_ERR(a->src_wh_dentry); -+ if (IS_ERR(a->src_wh_dentry)) -+ goto out_thargs; -+ } -+ -+ /* lookup whiteout for dentry */ -+ if (au_ftest_ren(a->auren_flags, WHDST)) { -+ h_d = au_wh_lkup(a->dst_h_parent, -+ &a->dst_dentry->d_name, a->br); -+ err = PTR_ERR(h_d); -+ if (IS_ERR(h_d)) -+ goto out_whsrc; -+ if (d_is_negative(h_d)) -+ dput(h_d); -+ else -+ a->dst_wh_dentry = h_d; -+ } -+ -+ /* rename dentry to tmpwh */ -+ if (a->thargs) { -+ err = au_whtmp_ren(a->dst_h_dentry, a->br); -+ if (unlikely(err)) -+ goto out_whdst; -+ -+ d = a->dst_dentry; -+ au_set_h_dptr(d, a->btgt, NULL); -+ err = au_lkup_neg(d, a->btgt, /*wh*/0); -+ if (unlikely(err)) -+ goto out_whtmp; -+ a->dst_h_dentry = au_h_dptr(d, a->btgt); -+ } -+ } -+ -+ BUG_ON(d_is_positive(a->dst_h_dentry) && a->src_btop != a->btgt); -+#if 0 /* debugging */ -+ BUG_ON(!au_ftest_ren(a->auren_flags, DIRREN) -+ && d_is_positive(a->dst_h_dentry) -+ && a->src_btop != a->btgt); -+#endif -+ -+ /* rename by vfs_rename or cpup */ -+ err = au_ren_or_cpup(a); -+ if (unlikely(err)) -+ /* leave the copied-up one */ -+ goto out_whtmp; -+ -+ /* make dir opaque */ -+ err = au_ren_diropq(a); -+ if (unlikely(err)) -+ goto out_rename; -+ -+ /* update target timestamps */ -+ if (a->exchange) { -+ AuDebugOn(au_dbtop(a->dst_dentry) != a->btgt); -+ a->h_path.dentry = au_h_dptr(a->dst_dentry, a->btgt); -+ vfsub_update_h_iattr(&a->h_path, /*did*/NULL); /*ignore*/ -+ a->dst_inode->i_ctime = d_inode(a->h_path.dentry)->i_ctime; -+ } -+ AuDebugOn(au_dbtop(a->src_dentry) != a->btgt); -+ a->h_path.dentry = au_h_dptr(a->src_dentry, a->btgt); -+ vfsub_update_h_iattr(&a->h_path, /*did*/NULL); /*ignore*/ -+ a->src_inode->i_ctime = d_inode(a->h_path.dentry)->i_ctime; -+ -+ if (!a->exchange) { -+ /* remove whiteout for dentry */ -+ if (a->dst_wh_dentry) { -+ a->h_path.dentry = a->dst_wh_dentry; -+ err = au_wh_unlink_dentry(a->dst_h_dir, &a->h_path, -+ a->dst_dentry); -+ if (unlikely(err)) -+ goto out_diropq; -+ } -+ -+ /* remove whtmp */ -+ if (a->thargs) -+ au_ren_del_whtmp(a); /* ignore this error */ -+ -+ au_fhsm_wrote(a->src_dentry->d_sb, a->btgt, /*force*/0); -+ } -+ err = 0; -+ goto out_success; -+ -+out_diropq: -+ au_ren_rev_diropq(err, a); -+out_rename: -+ au_ren_rev_rename(err, a); -+ dput(a->h_dst); -+out_whtmp: -+ if (a->thargs) -+ au_ren_rev_whtmp(err, a); -+out_whdst: -+ dput(a->dst_wh_dentry); -+ a->dst_wh_dentry = NULL; -+out_whsrc: -+ if (a->src_wh_dentry) -+ au_ren_rev_whsrc(err, a); -+out_success: -+ dput(a->src_wh_dentry); -+ dput(a->dst_wh_dentry); -+out_thargs: -+ if (a->thargs) { -+ dput(a->h_dst); -+ au_whtmp_rmdir_free(a->thargs); -+ a->thargs = NULL; -+ } -+out: -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * test if @dentry dir can be rename destination or not. -+ * success means, it is a logically empty dir. -+ */ -+static int may_rename_dstdir(struct dentry *dentry, struct au_nhash *whlist) -+{ -+ return au_test_empty(dentry, whlist); -+} -+ -+/* -+ * test if @a->src_dentry dir can be rename source or not. -+ * if it can, return 0. -+ * success means, -+ * - it is a logically empty dir. -+ * - or, it exists on writable branch and has no children including whiteouts -+ * on the lower branch unless DIRREN is on. -+ */ -+static int may_rename_srcdir(struct au_ren_args *a) -+{ -+ int err; -+ unsigned int rdhash; -+ aufs_bindex_t btop, btgt; -+ struct dentry *dentry; -+ struct super_block *sb; -+ struct au_sbinfo *sbinfo; -+ -+ dentry = a->src_dentry; -+ sb = dentry->d_sb; -+ sbinfo = au_sbi(sb); -+ if (au_opt_test(sbinfo->si_mntflags, DIRREN)) -+ au_fset_ren(a->auren_flags, DIRREN); -+ -+ btgt = a->btgt; -+ btop = au_dbtop(dentry); -+ if (btop != btgt) { -+ struct au_nhash whlist; -+ -+ SiMustAnyLock(sb); -+ rdhash = sbinfo->si_rdhash; -+ if (!rdhash) -+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, -+ dentry)); -+ err = au_nhash_alloc(&whlist, rdhash, GFP_NOFS); -+ if (unlikely(err)) -+ goto out; -+ err = au_test_empty(dentry, &whlist); -+ au_nhash_wh_free(&whlist); -+ goto out; -+ } -+ -+ if (btop == au_dbtaildir(dentry)) -+ return 0; /* success */ -+ -+ err = au_test_empty_lower(dentry); -+ -+out: -+ if (err == -ENOTEMPTY) { -+ if (au_ftest_ren(a->auren_flags, DIRREN)) { -+ err = 0; -+ } else { -+ AuWarn1("renaming dir who has child(ren) on multiple " -+ "branches, is not supported\n"); -+ err = -EXDEV; -+ } -+ } -+ return err; -+} -+ -+/* side effect: sets whlist and h_dentry */ -+static int au_ren_may_dir(struct au_ren_args *a) -+{ -+ int err; -+ unsigned int rdhash; -+ struct dentry *d; -+ -+ d = a->dst_dentry; -+ SiMustAnyLock(d->d_sb); -+ -+ err = 0; -+ if (au_ftest_ren(a->auren_flags, ISDIR_DST) && a->dst_inode) { -+ rdhash = au_sbi(d->d_sb)->si_rdhash; -+ if (!rdhash) -+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, d)); -+ err = au_nhash_alloc(&a->whlist, rdhash, GFP_NOFS); -+ if (unlikely(err)) -+ goto out; -+ -+ if (!a->exchange) { -+ au_set_dbtop(d, a->dst_btop); -+ err = may_rename_dstdir(d, &a->whlist); -+ au_set_dbtop(d, a->btgt); -+ } else -+ err = may_rename_srcdir(a); -+ } -+ a->dst_h_dentry = au_h_dptr(d, au_dbtop(d)); -+ if (unlikely(err)) -+ goto out; -+ -+ d = a->src_dentry; -+ a->src_h_dentry = au_h_dptr(d, au_dbtop(d)); -+ if (au_ftest_ren(a->auren_flags, ISDIR_SRC)) { -+ err = may_rename_srcdir(a); -+ if (unlikely(err)) { -+ au_nhash_wh_free(&a->whlist); -+ a->whlist.nh_num = 0; -+ } -+ } -+out: -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * simple tests for rename. -+ * following the checks in vfs, plus the parent-child relationship. -+ */ -+static int au_may_ren(struct au_ren_args *a) -+{ -+ int err, isdir; -+ struct inode *h_inode; -+ -+ if (a->src_btop == a->btgt) { -+ err = au_may_del(a->src_dentry, a->btgt, a->src_h_parent, -+ au_ftest_ren(a->auren_flags, ISDIR_SRC)); -+ if (unlikely(err)) -+ goto out; -+ err = -EINVAL; -+ if (unlikely(a->src_h_dentry == a->h_trap)) -+ goto out; -+ } -+ -+ err = 0; -+ if (a->dst_btop != a->btgt) -+ goto out; -+ -+ err = -ENOTEMPTY; -+ if (unlikely(a->dst_h_dentry == a->h_trap)) -+ goto out; -+ -+ err = -EIO; -+ isdir = !!au_ftest_ren(a->auren_flags, ISDIR_DST); -+ if (d_really_is_negative(a->dst_dentry)) { -+ if (d_is_negative(a->dst_h_dentry)) -+ err = au_may_add(a->dst_dentry, a->btgt, -+ a->dst_h_parent, isdir); -+ } else { -+ if (unlikely(d_is_negative(a->dst_h_dentry))) -+ goto out; -+ h_inode = d_inode(a->dst_h_dentry); -+ if (h_inode->i_nlink) -+ err = au_may_del(a->dst_dentry, a->btgt, -+ a->dst_h_parent, isdir); -+ } -+ -+out: -+ if (unlikely(err == -ENOENT || err == -EEXIST)) -+ err = -EIO; -+ AuTraceErr(err); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * locking order -+ * (VFS) -+ * - src_dir and dir by lock_rename() -+ * - inode if exists -+ * (aufs) -+ * - lock all -+ * + src_dentry and dentry by aufs_read_and_write_lock2() which calls, -+ * + si_read_lock -+ * + di_write_lock2_child() -+ * + di_write_lock_child() -+ * + ii_write_lock_child() -+ * + di_write_lock_child2() -+ * + ii_write_lock_child2() -+ * + src_parent and parent -+ * + di_write_lock_parent() -+ * + ii_write_lock_parent() -+ * + di_write_lock_parent2() -+ * + ii_write_lock_parent2() -+ * + lower src_dir and dir by vfsub_lock_rename() -+ * + verify the every relationships between child and parent. if any -+ * of them failed, unlock all and return -EBUSY. -+ */ -+static void au_ren_unlock(struct au_ren_args *a) -+{ -+ vfsub_unlock_rename(a->src_h_parent, a->src_hdir, -+ a->dst_h_parent, a->dst_hdir); -+ if (au_ftest_ren(a->auren_flags, DIRREN) -+ && a->h_root) -+ au_hn_inode_unlock(a->h_root); -+ if (au_ftest_ren(a->auren_flags, MNT_WRITE)) -+ vfsub_mnt_drop_write(au_br_mnt(a->br)); -+} -+ -+static int au_ren_lock(struct au_ren_args *a) -+{ -+ int err; -+ unsigned int udba; -+ -+ err = 0; -+ a->src_h_parent = au_h_dptr(a->src_parent, a->btgt); -+ a->src_hdir = au_hi(a->src_dir, a->btgt); -+ a->dst_h_parent = au_h_dptr(a->dst_parent, a->btgt); -+ a->dst_hdir = au_hi(a->dst_dir, a->btgt); -+ -+ err = vfsub_mnt_want_write(au_br_mnt(a->br)); -+ if (unlikely(err)) -+ goto out; -+ au_fset_ren(a->auren_flags, MNT_WRITE); -+ if (au_ftest_ren(a->auren_flags, DIRREN)) { -+ struct dentry *root; -+ struct inode *dir; -+ -+ /* -+ * sbinfo is already locked, so this ii_read_lock is -+ * unnecessary. but our debugging feature checks it. -+ */ -+ root = a->src_inode->i_sb->s_root; -+ if (root != a->src_parent && root != a->dst_parent) { -+ dir = d_inode(root); -+ ii_read_lock_parent3(dir); -+ a->h_root = au_hi(dir, a->btgt); -+ ii_read_unlock(dir); -+ au_hn_inode_lock_nested(a->h_root, AuLsc_I_PARENT3); -+ } -+ } -+ a->h_trap = vfsub_lock_rename(a->src_h_parent, a->src_hdir, -+ a->dst_h_parent, a->dst_hdir); -+ udba = au_opt_udba(a->src_dentry->d_sb); -+ if (unlikely(a->src_hdir->hi_inode != d_inode(a->src_h_parent) -+ || a->dst_hdir->hi_inode != d_inode(a->dst_h_parent))) -+ err = au_busy_or_stale(); -+ if (!err && au_dbtop(a->src_dentry) == a->btgt) -+ err = au_h_verify(a->src_h_dentry, udba, -+ d_inode(a->src_h_parent), a->src_h_parent, -+ a->br); -+ if (!err && au_dbtop(a->dst_dentry) == a->btgt) -+ err = au_h_verify(a->dst_h_dentry, udba, -+ d_inode(a->dst_h_parent), a->dst_h_parent, -+ a->br); -+ if (!err) -+ goto out; /* success */ -+ -+ err = au_busy_or_stale(); -+ au_ren_unlock(a); -+ -+out: -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static void au_ren_refresh_dir(struct au_ren_args *a) -+{ -+ struct inode *dir; -+ -+ dir = a->dst_dir; -+ inode_inc_iversion(dir); -+ if (au_ftest_ren(a->auren_flags, ISDIR_SRC)) { -+ /* is this updating defined in POSIX? */ -+ au_cpup_attr_timesizes(a->src_inode); -+ au_cpup_attr_nlink(dir, /*force*/1); -+ } -+ au_dir_ts(dir, a->btgt); -+ -+ if (a->exchange) { -+ dir = a->src_dir; -+ inode_inc_iversion(dir); -+ if (au_ftest_ren(a->auren_flags, ISDIR_DST)) { -+ /* is this updating defined in POSIX? */ -+ au_cpup_attr_timesizes(a->dst_inode); -+ au_cpup_attr_nlink(dir, /*force*/1); -+ } -+ au_dir_ts(dir, a->btgt); -+ } -+ -+ if (au_ftest_ren(a->auren_flags, ISSAMEDIR)) -+ return; -+ -+ dir = a->src_dir; -+ inode_inc_iversion(dir); -+ if (au_ftest_ren(a->auren_flags, ISDIR_SRC)) -+ au_cpup_attr_nlink(dir, /*force*/1); -+ au_dir_ts(dir, a->btgt); -+} -+ -+static void au_ren_refresh(struct au_ren_args *a) -+{ -+ aufs_bindex_t bbot, bindex; -+ struct dentry *d, *h_d; -+ struct inode *i, *h_i; -+ struct super_block *sb; -+ -+ d = a->dst_dentry; -+ d_drop(d); -+ if (a->h_dst) -+ /* already dget-ed by au_ren_or_cpup() */ -+ au_set_h_dptr(d, a->btgt, a->h_dst); -+ -+ i = a->dst_inode; -+ if (i) { -+ if (!a->exchange) { -+ if (!au_ftest_ren(a->auren_flags, ISDIR_DST)) -+ vfsub_drop_nlink(i); -+ else { -+ vfsub_dead_dir(i); -+ au_cpup_attr_timesizes(i); -+ } -+ au_update_dbrange(d, /*do_put_zero*/1); -+ } else -+ au_cpup_attr_nlink(i, /*force*/1); -+ } else { -+ bbot = a->btgt; -+ for (bindex = au_dbtop(d); bindex < bbot; bindex++) -+ au_set_h_dptr(d, bindex, NULL); -+ bbot = au_dbbot(d); -+ for (bindex = a->btgt + 1; bindex <= bbot; bindex++) -+ au_set_h_dptr(d, bindex, NULL); -+ au_update_dbrange(d, /*do_put_zero*/0); -+ } -+ -+ if (a->exchange -+ || au_ftest_ren(a->auren_flags, DIRREN)) { -+ d_drop(a->src_dentry); -+ if (au_ftest_ren(a->auren_flags, DIRREN)) -+ au_set_dbwh(a->src_dentry, -1); -+ return; -+ } -+ -+ d = a->src_dentry; -+ au_set_dbwh(d, -1); -+ bbot = au_dbbot(d); -+ for (bindex = a->btgt + 1; bindex <= bbot; bindex++) { -+ h_d = au_h_dptr(d, bindex); -+ if (h_d) -+ au_set_h_dptr(d, bindex, NULL); -+ } -+ au_set_dbbot(d, a->btgt); -+ -+ sb = d->d_sb; -+ i = a->src_inode; -+ if (au_opt_test(au_mntflags(sb), PLINK) && au_plink_test(i)) -+ return; /* success */ -+ -+ bbot = au_ibbot(i); -+ for (bindex = a->btgt + 1; bindex <= bbot; bindex++) { -+ h_i = au_h_iptr(i, bindex); -+ if (h_i) { -+ au_xino_write(sb, bindex, h_i->i_ino, /*ino*/0); -+ /* ignore this error */ -+ au_set_h_iptr(i, bindex, NULL, 0); -+ } -+ } -+ au_set_ibbot(i, a->btgt); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* mainly for link(2) and rename(2) */ -+int au_wbr(struct dentry *dentry, aufs_bindex_t btgt) -+{ -+ aufs_bindex_t bdiropq, bwh; -+ struct dentry *parent; -+ struct au_branch *br; -+ -+ parent = dentry->d_parent; -+ IMustLock(d_inode(parent)); /* dir is locked */ -+ -+ bdiropq = au_dbdiropq(parent); -+ bwh = au_dbwh(dentry); -+ br = au_sbr(dentry->d_sb, btgt); -+ if (au_br_rdonly(br) -+ || (0 <= bdiropq && bdiropq < btgt) -+ || (0 <= bwh && bwh < btgt)) -+ btgt = -1; -+ -+ AuDbg("btgt %d\n", btgt); -+ return btgt; -+} -+ -+/* sets src_btop, dst_btop and btgt */ -+static int au_ren_wbr(struct au_ren_args *a) -+{ -+ int err; -+ struct au_wr_dir_args wr_dir_args = { -+ /* .force_btgt = -1, */ -+ .flags = AuWrDir_ADD_ENTRY -+ }; -+ -+ a->src_btop = au_dbtop(a->src_dentry); -+ a->dst_btop = au_dbtop(a->dst_dentry); -+ if (au_ftest_ren(a->auren_flags, ISDIR_SRC) -+ || au_ftest_ren(a->auren_flags, ISDIR_DST)) -+ au_fset_wrdir(wr_dir_args.flags, ISDIR); -+ wr_dir_args.force_btgt = a->src_btop; -+ if (a->dst_inode && a->dst_btop < a->src_btop) -+ wr_dir_args.force_btgt = a->dst_btop; -+ wr_dir_args.force_btgt = au_wbr(a->dst_dentry, wr_dir_args.force_btgt); -+ err = au_wr_dir(a->dst_dentry, a->src_dentry, &wr_dir_args); -+ a->btgt = err; -+ if (a->exchange) -+ au_update_dbtop(a->dst_dentry); -+ -+ return err; -+} -+ -+static void au_ren_dt(struct au_ren_args *a) -+{ -+ a->h_path.dentry = a->src_h_parent; -+ au_dtime_store(a->src_dt + AuPARENT, a->src_parent, &a->h_path); -+ if (!au_ftest_ren(a->auren_flags, ISSAMEDIR)) { -+ a->h_path.dentry = a->dst_h_parent; -+ au_dtime_store(a->dst_dt + AuPARENT, a->dst_parent, &a->h_path); -+ } -+ -+ au_fclr_ren(a->auren_flags, DT_DSTDIR); -+ if (!au_ftest_ren(a->auren_flags, ISDIR_SRC) -+ && !a->exchange) -+ return; -+ -+ a->h_path.dentry = a->src_h_dentry; -+ au_dtime_store(a->src_dt + AuCHILD, a->src_dentry, &a->h_path); -+ if (d_is_positive(a->dst_h_dentry)) { -+ au_fset_ren(a->auren_flags, DT_DSTDIR); -+ a->h_path.dentry = a->dst_h_dentry; -+ au_dtime_store(a->dst_dt + AuCHILD, a->dst_dentry, &a->h_path); -+ } -+} -+ -+static void au_ren_rev_dt(int err, struct au_ren_args *a) -+{ -+ struct dentry *h_d; -+ struct inode *h_inode; -+ -+ au_dtime_revert(a->src_dt + AuPARENT); -+ if (!au_ftest_ren(a->auren_flags, ISSAMEDIR)) -+ au_dtime_revert(a->dst_dt + AuPARENT); -+ -+ if (au_ftest_ren(a->auren_flags, ISDIR_SRC) && err != -EIO) { -+ h_d = a->src_dt[AuCHILD].dt_h_path.dentry; -+ h_inode = d_inode(h_d); -+ inode_lock_nested(h_inode, AuLsc_I_CHILD); -+ au_dtime_revert(a->src_dt + AuCHILD); -+ inode_unlock(h_inode); -+ -+ if (au_ftest_ren(a->auren_flags, DT_DSTDIR)) { -+ h_d = a->dst_dt[AuCHILD].dt_h_path.dentry; -+ h_inode = d_inode(h_d); -+ inode_lock_nested(h_inode, AuLsc_I_CHILD); -+ au_dtime_revert(a->dst_dt + AuCHILD); -+ inode_unlock(h_inode); -+ } -+ } -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+int aufs_rename(struct inode *_src_dir, struct dentry *_src_dentry, -+ struct inode *_dst_dir, struct dentry *_dst_dentry, -+ unsigned int _flags) -+{ -+ int err, lock_flags; -+ void *rev; -+ /* reduce stack space */ -+ struct au_ren_args *a; -+ struct au_pin pin; -+ -+ AuDbg("%pd, %pd, 0x%x\n", _src_dentry, _dst_dentry, _flags); -+ IMustLock(_src_dir); -+ IMustLock(_dst_dir); -+ -+ err = -EINVAL; -+ if (unlikely(_flags & RENAME_WHITEOUT)) -+ goto out; -+ -+ err = -ENOMEM; -+ BUILD_BUG_ON(sizeof(*a) > PAGE_SIZE); -+ a = kzalloc(sizeof(*a), GFP_NOFS); -+ if (unlikely(!a)) -+ goto out; -+ -+ a->flags = _flags; -+ BUILD_BUG_ON(sizeof(a->exchange) == sizeof(u8) -+ && RENAME_EXCHANGE > U8_MAX); -+ a->exchange = _flags & RENAME_EXCHANGE; -+ a->src_dir = _src_dir; -+ a->src_dentry = _src_dentry; -+ a->src_inode = NULL; -+ if (d_really_is_positive(a->src_dentry)) -+ a->src_inode = d_inode(a->src_dentry); -+ a->src_parent = a->src_dentry->d_parent; /* dir inode is locked */ -+ a->dst_dir = _dst_dir; -+ a->dst_dentry = _dst_dentry; -+ a->dst_inode = NULL; -+ if (d_really_is_positive(a->dst_dentry)) -+ a->dst_inode = d_inode(a->dst_dentry); -+ a->dst_parent = a->dst_dentry->d_parent; /* dir inode is locked */ -+ if (a->dst_inode) { -+ /* -+ * if EXCHANGE && src is non-dir && dst is dir, -+ * dst is not locked. -+ */ -+ /* IMustLock(a->dst_inode); */ -+ au_igrab(a->dst_inode); -+ } -+ -+ err = -ENOTDIR; -+ lock_flags = AuLock_FLUSH | AuLock_NOPLM | AuLock_GEN; -+ if (d_is_dir(a->src_dentry)) { -+ au_fset_ren(a->auren_flags, ISDIR_SRC); -+ if (unlikely(!a->exchange -+ && d_really_is_positive(a->dst_dentry) -+ && !d_is_dir(a->dst_dentry))) -+ goto out_free; -+ lock_flags |= AuLock_DIRS; -+ } -+ if (a->dst_inode && d_is_dir(a->dst_dentry)) { -+ au_fset_ren(a->auren_flags, ISDIR_DST); -+ if (unlikely(!a->exchange -+ && d_really_is_positive(a->src_dentry) -+ && !d_is_dir(a->src_dentry))) -+ goto out_free; -+ lock_flags |= AuLock_DIRS; -+ } -+ err = aufs_read_and_write_lock2(a->dst_dentry, a->src_dentry, -+ lock_flags); -+ if (unlikely(err)) -+ goto out_free; -+ -+ err = au_d_hashed_positive(a->src_dentry); -+ if (unlikely(err)) -+ goto out_unlock; -+ err = -ENOENT; -+ if (a->dst_inode) { -+ /* -+ * If it is a dir, VFS unhash it before this -+ * function. It means we cannot rely upon d_unhashed(). -+ */ -+ if (unlikely(!a->dst_inode->i_nlink)) -+ goto out_unlock; -+ if (!au_ftest_ren(a->auren_flags, ISDIR_DST)) { -+ err = au_d_hashed_positive(a->dst_dentry); -+ if (unlikely(err && !a->exchange)) -+ goto out_unlock; -+ } else if (unlikely(IS_DEADDIR(a->dst_inode))) -+ goto out_unlock; -+ } else if (unlikely(d_unhashed(a->dst_dentry))) -+ goto out_unlock; -+ -+ /* -+ * is it possible? -+ * yes, it happened (in linux-3.3-rcN) but I don't know why. -+ * there may exist a problem somewhere else. -+ */ -+ err = -EINVAL; -+ if (unlikely(d_inode(a->dst_parent) == d_inode(a->src_dentry))) -+ goto out_unlock; -+ -+ au_fset_ren(a->auren_flags, ISSAMEDIR); /* temporary */ -+ di_write_lock_parent(a->dst_parent); -+ -+ /* which branch we process */ -+ err = au_ren_wbr(a); -+ if (unlikely(err < 0)) -+ goto out_parent; -+ a->br = au_sbr(a->dst_dentry->d_sb, a->btgt); -+ a->h_path.mnt = au_br_mnt(a->br); -+ -+ /* are they available to be renamed */ -+ err = au_ren_may_dir(a); -+ if (unlikely(err)) -+ goto out_children; -+ -+ /* prepare the writable parent dir on the same branch */ -+ if (a->dst_btop == a->btgt) { -+ au_fset_ren(a->auren_flags, WHDST); -+ } else { -+ err = au_cpup_dirs(a->dst_dentry, a->btgt); -+ if (unlikely(err)) -+ goto out_children; -+ } -+ -+ err = 0; -+ if (!a->exchange) { -+ if (a->src_dir != a->dst_dir) { -+ /* -+ * this temporary unlock is safe, -+ * because both dir->i_mutex are locked. -+ */ -+ di_write_unlock(a->dst_parent); -+ di_write_lock_parent(a->src_parent); -+ err = au_wr_dir_need_wh(a->src_dentry, -+ au_ftest_ren(a->auren_flags, -+ ISDIR_SRC), -+ &a->btgt); -+ di_write_unlock(a->src_parent); -+ di_write_lock2_parent(a->src_parent, a->dst_parent, -+ /*isdir*/1); -+ au_fclr_ren(a->auren_flags, ISSAMEDIR); -+ } else -+ err = au_wr_dir_need_wh(a->src_dentry, -+ au_ftest_ren(a->auren_flags, -+ ISDIR_SRC), -+ &a->btgt); -+ } -+ if (unlikely(err < 0)) -+ goto out_children; -+ if (err) -+ au_fset_ren(a->auren_flags, WHSRC); -+ -+ /* cpup src */ -+ if (a->src_btop != a->btgt) { -+ err = au_pin(&pin, a->src_dentry, a->btgt, -+ au_opt_udba(a->src_dentry->d_sb), -+ AuPin_DI_LOCKED | AuPin_MNT_WRITE); -+ if (!err) { -+ struct au_cp_generic cpg = { -+ .dentry = a->src_dentry, -+ .bdst = a->btgt, -+ .bsrc = a->src_btop, -+ .len = -1, -+ .pin = &pin, -+ .flags = AuCpup_DTIME | AuCpup_HOPEN -+ }; -+ AuDebugOn(au_dbtop(a->src_dentry) != a->src_btop); -+ err = au_sio_cpup_simple(&cpg); -+ au_unpin(&pin); -+ } -+ if (unlikely(err)) -+ goto out_children; -+ a->src_btop = a->btgt; -+ a->src_h_dentry = au_h_dptr(a->src_dentry, a->btgt); -+ if (!a->exchange) -+ au_fset_ren(a->auren_flags, WHSRC); -+ } -+ -+ /* cpup dst */ -+ if (a->exchange && a->dst_inode -+ && a->dst_btop != a->btgt) { -+ err = au_pin(&pin, a->dst_dentry, a->btgt, -+ au_opt_udba(a->dst_dentry->d_sb), -+ AuPin_DI_LOCKED | AuPin_MNT_WRITE); -+ if (!err) { -+ struct au_cp_generic cpg = { -+ .dentry = a->dst_dentry, -+ .bdst = a->btgt, -+ .bsrc = a->dst_btop, -+ .len = -1, -+ .pin = &pin, -+ .flags = AuCpup_DTIME | AuCpup_HOPEN -+ }; -+ err = au_sio_cpup_simple(&cpg); -+ au_unpin(&pin); -+ } -+ if (unlikely(err)) -+ goto out_children; -+ a->dst_btop = a->btgt; -+ a->dst_h_dentry = au_h_dptr(a->dst_dentry, a->btgt); -+ } -+ -+ /* lock them all */ -+ err = au_ren_lock(a); -+ if (unlikely(err)) -+ /* leave the copied-up one */ -+ goto out_children; -+ -+ if (!a->exchange) { -+ if (!au_opt_test(au_mntflags(a->dst_dir->i_sb), UDBA_NONE)) -+ err = au_may_ren(a); -+ else if (unlikely(a->dst_dentry->d_name.len > AUFS_MAX_NAMELEN)) -+ err = -ENAMETOOLONG; -+ if (unlikely(err)) -+ goto out_hdir; -+ } -+ -+ /* store timestamps to be revertible */ -+ au_ren_dt(a); -+ -+ /* store dirren info */ -+ if (au_ftest_ren(a->auren_flags, DIRREN)) { -+ err = au_dr_rename(a->src_dentry, a->btgt, -+ &a->dst_dentry->d_name, &rev); -+ AuTraceErr(err); -+ if (unlikely(err)) -+ goto out_dt; -+ } -+ -+ /* here we go */ -+ err = do_rename(a); -+ if (unlikely(err)) -+ goto out_dirren; -+ -+ if (au_ftest_ren(a->auren_flags, DIRREN)) -+ au_dr_rename_fin(a->src_dentry, a->btgt, rev); -+ -+ /* update dir attributes */ -+ au_ren_refresh_dir(a); -+ -+ /* dput/iput all lower dentries */ -+ au_ren_refresh(a); -+ -+ goto out_hdir; /* success */ -+ -+out_dirren: -+ if (au_ftest_ren(a->auren_flags, DIRREN)) -+ au_dr_rename_rev(a->src_dentry, a->btgt, rev); -+out_dt: -+ au_ren_rev_dt(err, a); -+out_hdir: -+ au_ren_unlock(a); -+out_children: -+ au_nhash_wh_free(&a->whlist); -+ if (err && a->dst_inode && a->dst_btop != a->btgt) { -+ AuDbg("btop %d, btgt %d\n", a->dst_btop, a->btgt); -+ au_set_h_dptr(a->dst_dentry, a->btgt, NULL); -+ au_set_dbtop(a->dst_dentry, a->dst_btop); -+ } -+out_parent: -+ if (!err) { -+ if (d_unhashed(a->src_dentry)) -+ au_fset_ren(a->auren_flags, DROPPED_SRC); -+ if (d_unhashed(a->dst_dentry)) -+ au_fset_ren(a->auren_flags, DROPPED_DST); -+ if (!a->exchange) -+ d_move(a->src_dentry, a->dst_dentry); -+ else { -+ d_exchange(a->src_dentry, a->dst_dentry); -+ if (au_ftest_ren(a->auren_flags, DROPPED_DST)) -+ d_drop(a->dst_dentry); -+ } -+ if (au_ftest_ren(a->auren_flags, DROPPED_SRC)) -+ d_drop(a->src_dentry); -+ } else { -+ au_update_dbtop(a->dst_dentry); -+ if (!a->dst_inode) -+ d_drop(a->dst_dentry); -+ } -+ if (au_ftest_ren(a->auren_flags, ISSAMEDIR)) -+ di_write_unlock(a->dst_parent); -+ else -+ di_write_unlock2(a->src_parent, a->dst_parent); -+out_unlock: -+ aufs_read_and_write_unlock2(a->dst_dentry, a->src_dentry); -+out_free: -+ iput(a->dst_inode); -+ if (a->thargs) -+ au_whtmp_rmdir_free(a->thargs); -+ au_kfree_rcu(a); -+out: -+ AuTraceErr(err); -+ return err; -+} -diff -Nurp linux-5.6.3/fs/aufs/Kconfig linux-5.6.3-aufs/fs/aufs/Kconfig ---- linux-5.6.3/fs/aufs/Kconfig 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/Kconfig 2020-04-10 12:40:52.187049268 +0300 -@@ -0,0 +1,199 @@ -+# SPDX-License-Identifier: GPL-2.0 -+config AUFS_FS -+ bool "Aufs (Advanced multi layered unification filesystem) support" -+ help -+ Aufs is a stackable unification filesystem such as Unionfs, -+ which unifies several directories and provides a merged single -+ directory. -+ In the early days, aufs was entirely re-designed and -+ re-implemented Unionfs Version 1.x series. Introducing many -+ original ideas, approaches and improvements, it becomes totally -+ different from Unionfs while keeping the basic features. -+ -+if AUFS_FS -+choice -+ prompt "Maximum number of branches" -+ default AUFS_BRANCH_MAX_127 -+ help -+ Specifies the maximum number of branches (or member directories) -+ in a single aufs. The larger value consumes more system -+ resources and has a minor impact to performance. -+config AUFS_BRANCH_MAX_127 -+ bool "127" -+ help -+ Specifies the maximum number of branches (or member directories) -+ in a single aufs. The larger value consumes more system -+ resources and has a minor impact to performance. -+config AUFS_BRANCH_MAX_511 -+ bool "511" -+ help -+ Specifies the maximum number of branches (or member directories) -+ in a single aufs. The larger value consumes more system -+ resources and has a minor impact to performance. -+config AUFS_BRANCH_MAX_1023 -+ bool "1023" -+ help -+ Specifies the maximum number of branches (or member directories) -+ in a single aufs. The larger value consumes more system -+ resources and has a minor impact to performance. -+config AUFS_BRANCH_MAX_32767 -+ bool "32767" -+ help -+ Specifies the maximum number of branches (or member directories) -+ in a single aufs. The larger value consumes more system -+ resources and has a minor impact to performance. -+endchoice -+ -+config AUFS_SBILIST -+ bool -+ depends on AUFS_MAGIC_SYSRQ || PROC_FS -+ default y -+ help -+ Automatic configuration for internal use. -+ When aufs supports Magic SysRq or /proc, enabled automatically. -+ -+config AUFS_HNOTIFY -+ bool "Detect direct branch access (bypassing aufs)" -+ help -+ If you want to modify files on branches directly, eg. bypassing aufs, -+ and want aufs to detect the changes of them fully, then enable this -+ option and use 'udba=notify' mount option. -+ Currently there is only one available configuration, "fsnotify". -+ It will have a negative impact to the performance. -+ See detail in aufs.5. -+ -+choice -+ prompt "method" if AUFS_HNOTIFY -+ default AUFS_HFSNOTIFY -+config AUFS_HFSNOTIFY -+ bool "fsnotify" -+ select FSNOTIFY -+endchoice -+ -+config AUFS_EXPORT -+ bool "NFS-exportable aufs" -+ depends on EXPORTFS = y -+ help -+ If you want to export your mounted aufs via NFS, then enable this -+ option. There are several requirements for this configuration. -+ See detail in aufs.5. -+ -+config AUFS_INO_T_64 -+ bool -+ depends on AUFS_EXPORT -+ depends on 64BIT && !(ALPHA || S390) -+ default y -+ help -+ Automatic configuration for internal use. -+ /* typedef unsigned long/int __kernel_ino_t */ -+ /* alpha and s390x are int */ -+ -+config AUFS_XATTR -+ bool "support for XATTR/EA (including Security Labels)" -+ help -+ If your branch fs supports XATTR/EA and you want to make them -+ available in aufs too, then enable this opsion and specify the -+ branch attributes for EA. -+ See detail in aufs.5. -+ -+config AUFS_FHSM -+ bool "File-based Hierarchical Storage Management" -+ help -+ Hierarchical Storage Management (or HSM) is a well-known feature -+ in the storage world. Aufs provides this feature as file-based. -+ with multiple branches. -+ These multiple branches are prioritized, ie. the topmost one -+ should be the fastest drive and be used heavily. -+ -+config AUFS_RDU -+ bool "Readdir in userspace" -+ help -+ Aufs has two methods to provide a merged view for a directory, -+ by a user-space library and by kernel-space natively. The latter -+ is always enabled but sometimes large and slow. -+ If you enable this option, install the library in aufs2-util -+ package, and set some environment variables for your readdir(3), -+ then the work will be handled in user-space which generally -+ shows better performance in most cases. -+ See detail in aufs.5. -+ -+config AUFS_DIRREN -+ bool "Workaround for rename(2)-ing a directory" -+ help -+ By default, aufs returns EXDEV error in renameing a dir who has -+ his child on the lower branch, since it is a bad idea to issue -+ rename(2) internally for every lower branch. But user may not -+ accept this behaviour. So here is a workaround to allow such -+ rename(2) and store some extra infromation on the writable -+ branch. Obviously this costs high (and I don't like it). -+ To use this feature, you need to enable this configuration AND -+ to specify the mount option `dirren.' -+ See details in aufs.5 and the design documents. -+ -+config AUFS_SHWH -+ bool "Show whiteouts" -+ help -+ If you want to make the whiteouts in aufs visible, then enable -+ this option and specify 'shwh' mount option. Although it may -+ sounds like philosophy or something, but in technically it -+ simply shows the name of whiteout with keeping its behaviour. -+ -+config AUFS_BR_RAMFS -+ bool "Ramfs (initramfs/rootfs) as an aufs branch" -+ help -+ If you want to use ramfs as an aufs branch fs, then enable this -+ option. Generally tmpfs is recommended. -+ Aufs prohibited them to be a branch fs by default, because -+ initramfs becomes unusable after switch_root or something -+ generally. If you sets initramfs as an aufs branch and boot your -+ system by switch_root, you will meet a problem easily since the -+ files in initramfs may be inaccessible. -+ Unless you are going to use ramfs as an aufs branch fs without -+ switch_root or something, leave it N. -+ -+config AUFS_BR_FUSE -+ bool "Fuse fs as an aufs branch" -+ depends on FUSE_FS -+ select AUFS_POLL -+ help -+ If you want to use fuse-based userspace filesystem as an aufs -+ branch fs, then enable this option. -+ It implements the internal poll(2) operation which is -+ implemented by fuse only (curretnly). -+ -+config AUFS_POLL -+ bool -+ help -+ Automatic configuration for internal use. -+ -+config AUFS_BR_HFSPLUS -+ bool "Hfsplus as an aufs branch" -+ depends on HFSPLUS_FS -+ default y -+ help -+ If you want to use hfsplus fs as an aufs branch fs, then enable -+ this option. This option introduces a small overhead at -+ copying-up a file on hfsplus. -+ -+config AUFS_BDEV_LOOP -+ bool -+ depends on BLK_DEV_LOOP -+ default y -+ help -+ Automatic configuration for internal use. -+ Convert =[ym] into =y. -+ -+config AUFS_DEBUG -+ bool "Debug aufs" -+ help -+ Enable this to compile aufs internal debug code. -+ It will have a negative impact to the performance. -+ -+config AUFS_MAGIC_SYSRQ -+ bool -+ depends on AUFS_DEBUG && MAGIC_SYSRQ -+ default y -+ help -+ Automatic configuration for internal use. -+ When aufs supports Magic SysRq, enabled automatically. -+endif -diff -Nurp linux-5.6.3/fs/aufs/lcnt.h linux-5.6.3-aufs/fs/aufs/lcnt.h ---- linux-5.6.3/fs/aufs/lcnt.h 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/lcnt.h 2020-04-10 12:40:52.191049456 +0300 -@@ -0,0 +1,173 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2018-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * simple long counter wrapper -+ */ -+ -+#ifndef __AUFS_LCNT_H__ -+#define __AUFS_LCNT_H__ -+ -+#ifdef __KERNEL__ -+ -+#include "debug.h" -+ -+#define AuLCntATOMIC 1 -+#define AuLCntPCPUCNT 2 -+/* -+ * why does percpu_refcount require extra synchronize_rcu()s in -+ * au_br_do_free() -+ */ -+#define AuLCntPCPUREF 3 -+ -+/* #define AuLCntChosen AuLCntATOMIC */ -+#define AuLCntChosen AuLCntPCPUCNT -+/* #define AuLCntChosen AuLCntPCPUREF */ -+ -+#if AuLCntChosen == AuLCntATOMIC -+#include -+ -+typedef atomic_long_t au_lcnt_t; -+ -+static inline int au_lcnt_init(au_lcnt_t *cnt, void *release __maybe_unused) -+{ -+ atomic_long_set(cnt, 0); -+ return 0; -+} -+ -+static inline void au_lcnt_wait_for_fin(au_lcnt_t *cnt __maybe_unused) -+{ -+ /* empty */ -+} -+ -+static inline void au_lcnt_fin(au_lcnt_t *cnt __maybe_unused, -+ int do_sync __maybe_unused) -+{ -+ /* empty */ -+} -+ -+static inline void au_lcnt_inc(au_lcnt_t *cnt) -+{ -+ atomic_long_inc(cnt); -+} -+ -+static inline void au_lcnt_dec(au_lcnt_t *cnt) -+{ -+ atomic_long_dec(cnt); -+} -+ -+static inline long au_lcnt_read(au_lcnt_t *cnt, int do_rev __maybe_unused) -+{ -+ return atomic_long_read(cnt); -+} -+#endif -+ -+#if AuLCntChosen == AuLCntPCPUCNT -+#include -+ -+typedef struct percpu_counter au_lcnt_t; -+ -+static inline int au_lcnt_init(au_lcnt_t *cnt, void *release __maybe_unused) -+{ -+ return percpu_counter_init(cnt, 0, GFP_NOFS); -+} -+ -+static inline void au_lcnt_wait_for_fin(au_lcnt_t *cnt __maybe_unused) -+{ -+ /* empty */ -+} -+ -+static inline void au_lcnt_fin(au_lcnt_t *cnt, int do_sync __maybe_unused) -+{ -+ percpu_counter_destroy(cnt); -+} -+ -+static inline void au_lcnt_inc(au_lcnt_t *cnt) -+{ -+ percpu_counter_inc(cnt); -+} -+ -+static inline void au_lcnt_dec(au_lcnt_t *cnt) -+{ -+ percpu_counter_dec(cnt); -+} -+ -+static inline long au_lcnt_read(au_lcnt_t *cnt, int do_rev __maybe_unused) -+{ -+ s64 n; -+ -+ n = percpu_counter_sum(cnt); -+ BUG_ON(n < 0); -+ if (LONG_MAX != LLONG_MAX -+ && n > LONG_MAX) -+ AuWarn1("%s\n", "wrap-around"); -+ -+ return n; -+} -+#endif -+ -+#if AuLCntChosen == AuLCntPCPUREF -+#include -+ -+typedef struct percpu_ref au_lcnt_t; -+ -+static inline int au_lcnt_init(au_lcnt_t *cnt, percpu_ref_func_t *release) -+{ -+ if (!release) -+ release = percpu_ref_exit; -+ return percpu_ref_init(cnt, release, /*percpu mode*/0, GFP_NOFS); -+} -+ -+static inline void au_lcnt_wait_for_fin(au_lcnt_t *cnt __maybe_unused) -+{ -+ synchronize_rcu(); -+} -+ -+static inline void au_lcnt_fin(au_lcnt_t *cnt, int do_sync) -+{ -+ percpu_ref_kill(cnt); -+ if (do_sync) -+ au_lcnt_wait_for_fin(cnt); -+} -+ -+static inline void au_lcnt_inc(au_lcnt_t *cnt) -+{ -+ percpu_ref_get(cnt); -+} -+ -+static inline void au_lcnt_dec(au_lcnt_t *cnt) -+{ -+ percpu_ref_put(cnt); -+} -+ -+/* -+ * avoid calling this func as possible. -+ */ -+static inline long au_lcnt_read(au_lcnt_t *cnt, int do_rev) -+{ -+ long l; -+ -+ percpu_ref_switch_to_atomic_sync(cnt); -+ l = atomic_long_read(&cnt->count); -+ if (do_rev) -+ percpu_ref_switch_to_percpu(cnt); -+ -+ /* percpu_ref is initialized by 1 instead of 0 */ -+ return l - 1; -+} -+#endif -+ -+#ifdef CONFIG_AUFS_DEBUG -+#define AuLCntZero(val) do { \ -+ long l = val; \ -+ if (l) \ -+ AuDbg("%s = %ld\n", #val, l); \ -+} while (0) -+#else -+#define AuLCntZero(val) do {} while (0) -+#endif -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_LCNT_H__ */ -diff -Nurp linux-5.6.3/fs/aufs/loop.c linux-5.6.3-aufs/fs/aufs/loop.c ---- linux-5.6.3/fs/aufs/loop.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/loop.c 2020-04-10 12:40:52.191049456 +0300 -@@ -0,0 +1,135 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * support for loopback block device as a branch -+ */ -+ -+#include "aufs.h" -+ -+/* added into drivers/block/loop.c */ -+static struct file *(*backing_file_func)(struct super_block *sb); -+ -+/* -+ * test if two lower dentries have overlapping branches. -+ */ -+int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_adding) -+{ -+ struct super_block *h_sb; -+ struct file *backing_file; -+ -+ if (unlikely(!backing_file_func)) { -+ /* don't load "loop" module here */ -+ backing_file_func = symbol_get(loop_backing_file); -+ if (unlikely(!backing_file_func)) -+ /* "loop" module is not loaded */ -+ return 0; -+ } -+ -+ h_sb = h_adding->d_sb; -+ backing_file = backing_file_func(h_sb); -+ if (!backing_file) -+ return 0; -+ -+ h_adding = backing_file->f_path.dentry; -+ /* -+ * h_adding can be local NFS. -+ * in this case aufs cannot detect the loop. -+ */ -+ if (unlikely(h_adding->d_sb == sb)) -+ return 1; -+ return !!au_test_subdir(h_adding, sb->s_root); -+} -+ -+/* true if a kernel thread named 'loop[0-9].*' accesses a file */ -+int au_test_loopback_kthread(void) -+{ -+ int ret; -+ struct task_struct *tsk = current; -+ char c, comm[sizeof(tsk->comm)]; -+ -+ ret = 0; -+ if (tsk->flags & PF_KTHREAD) { -+ get_task_comm(comm, tsk); -+ c = comm[4]; -+ ret = ('0' <= c && c <= '9' -+ && !strncmp(comm, "loop", 4)); -+ } -+ -+ return ret; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+#define au_warn_loopback_step 16 -+static int au_warn_loopback_nelem = au_warn_loopback_step; -+static unsigned long *au_warn_loopback_array; -+ -+void au_warn_loopback(struct super_block *h_sb) -+{ -+ int i, new_nelem; -+ unsigned long *a, magic; -+ static DEFINE_SPINLOCK(spin); -+ -+ magic = h_sb->s_magic; -+ spin_lock(&spin); -+ a = au_warn_loopback_array; -+ for (i = 0; i < au_warn_loopback_nelem && *a; i++) -+ if (a[i] == magic) { -+ spin_unlock(&spin); -+ return; -+ } -+ -+ /* h_sb is new to us, print it */ -+ if (i < au_warn_loopback_nelem) { -+ a[i] = magic; -+ goto pr; -+ } -+ -+ /* expand the array */ -+ new_nelem = au_warn_loopback_nelem + au_warn_loopback_step; -+ a = au_kzrealloc(au_warn_loopback_array, -+ au_warn_loopback_nelem * sizeof(unsigned long), -+ new_nelem * sizeof(unsigned long), GFP_ATOMIC, -+ /*may_shrink*/0); -+ if (a) { -+ au_warn_loopback_nelem = new_nelem; -+ au_warn_loopback_array = a; -+ a[i] = magic; -+ goto pr; -+ } -+ -+ spin_unlock(&spin); -+ AuWarn1("realloc failed, ignored\n"); -+ return; -+ -+pr: -+ spin_unlock(&spin); -+ pr_warn("you may want to try another patch for loopback file " -+ "on %s(0x%lx) branch\n", au_sbtype(h_sb), magic); -+} -+ -+int au_loopback_init(void) -+{ -+ int err; -+ struct super_block *sb __maybe_unused; -+ -+ BUILD_BUG_ON(sizeof(sb->s_magic) != sizeof(*au_warn_loopback_array)); -+ -+ err = 0; -+ au_warn_loopback_array = kcalloc(au_warn_loopback_step, -+ sizeof(unsigned long), GFP_NOFS); -+ if (unlikely(!au_warn_loopback_array)) -+ err = -ENOMEM; -+ -+ return err; -+} -+ -+void au_loopback_fin(void) -+{ -+ if (backing_file_func) -+ symbol_put(loop_backing_file); -+ au_kfree_try_rcu(au_warn_loopback_array); -+} -diff -Nurp linux-5.6.3/fs/aufs/loop.h linux-5.6.3-aufs/fs/aufs/loop.h ---- linux-5.6.3/fs/aufs/loop.h 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/loop.h 2020-04-10 12:40:52.191049456 +0300 -@@ -0,0 +1,42 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * support for loopback mount as a branch -+ */ -+ -+#ifndef __AUFS_LOOP_H__ -+#define __AUFS_LOOP_H__ -+ -+#ifdef __KERNEL__ -+ -+struct dentry; -+struct super_block; -+ -+#ifdef CONFIG_AUFS_BDEV_LOOP -+/* drivers/block/loop.c */ -+struct file *loop_backing_file(struct super_block *sb); -+ -+/* loop.c */ -+int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_adding); -+int au_test_loopback_kthread(void); -+void au_warn_loopback(struct super_block *h_sb); -+ -+int au_loopback_init(void); -+void au_loopback_fin(void); -+#else -+AuStub(struct file *, loop_backing_file, return NULL, struct super_block *sb) -+ -+AuStubInt0(au_test_loopback_overlap, struct super_block *sb, -+ struct dentry *h_adding) -+AuStubInt0(au_test_loopback_kthread, void) -+AuStubVoid(au_warn_loopback, struct super_block *h_sb) -+ -+AuStubInt0(au_loopback_init, void) -+AuStubVoid(au_loopback_fin, void) -+#endif /* BLK_DEV_LOOP */ -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_LOOP_H__ */ -diff -Nurp linux-5.6.3/fs/aufs/magic.mk linux-5.6.3-aufs/fs/aufs/magic.mk ---- linux-5.6.3/fs/aufs/magic.mk 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/magic.mk 2020-04-10 12:40:52.191049456 +0300 -@@ -0,0 +1,31 @@ -+# SPDX-License-Identifier: GPL-2.0 -+ -+# defined in ${srctree}/fs/fuse/inode.c -+# tristate -+ifdef CONFIG_FUSE_FS -+ccflags-y += -DFUSE_SUPER_MAGIC=0x65735546 -+endif -+ -+# defined in ${srctree}/fs/xfs/xfs_sb.h -+# tristate -+ifdef CONFIG_XFS_FS -+ccflags-y += -DXFS_SB_MAGIC=0x58465342 -+endif -+ -+# defined in ${srctree}/fs/configfs/mount.c -+# tristate -+ifdef CONFIG_CONFIGFS_FS -+ccflags-y += -DCONFIGFS_MAGIC=0x62656570 -+endif -+ -+# defined in ${srctree}/fs/ubifs/ubifs.h -+# tristate -+ifdef CONFIG_UBIFS_FS -+ccflags-y += -DUBIFS_SUPER_MAGIC=0x24051905 -+endif -+ -+# defined in ${srctree}/fs/hfsplus/hfsplus_raw.h -+# tristate -+ifdef CONFIG_HFSPLUS_FS -+ccflags-y += -DHFSPLUS_SUPER_MAGIC=0x482b -+endif -diff -Nurp linux-5.6.3/fs/aufs/Makefile linux-5.6.3-aufs/fs/aufs/Makefile ---- linux-5.6.3/fs/aufs/Makefile 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/Makefile 2020-04-10 12:40:52.187049268 +0300 -@@ -0,0 +1,39 @@ -+# SPDX-License-Identifier: GPL-2.0 -+ -+include ${srctree}/${src}/magic.mk -+-include ${srctree}/${src}/priv_def.mk -+ -+# cf. include/linux/kernel.h -+# enable pr_debug -+ccflags-y += -DDEBUG -+# sparse requires the full pathname -+ccflags-y += -include ${srctree}/include/uapi/linux/aufs_type.h -+ -+obj-$(CONFIG_AUFS_FS) += aufs.o -+aufs-y := module.o sbinfo.o super.o branch.o xino.o sysaufs.o opts.o \ -+ wkq.o vfsub.o dcsub.o \ -+ cpup.o whout.o wbr_policy.o \ -+ dinfo.o dentry.o \ -+ dynop.o \ -+ finfo.o file.o f_op.o \ -+ dir.o vdir.o \ -+ iinfo.o inode.o i_op.o i_op_add.o i_op_del.o i_op_ren.o \ -+ mvdown.o ioctl.o -+ -+# all are boolean -+aufs-$(CONFIG_PROC_FS) += procfs.o plink.o -+aufs-$(CONFIG_SYSFS) += sysfs.o -+aufs-$(CONFIG_DEBUG_FS) += dbgaufs.o -+aufs-$(CONFIG_AUFS_BDEV_LOOP) += loop.o -+aufs-$(CONFIG_AUFS_HNOTIFY) += hnotify.o -+aufs-$(CONFIG_AUFS_HFSNOTIFY) += hfsnotify.o -+aufs-$(CONFIG_AUFS_EXPORT) += export.o -+aufs-$(CONFIG_AUFS_XATTR) += xattr.o -+aufs-$(CONFIG_FS_POSIX_ACL) += posix_acl.o -+aufs-$(CONFIG_AUFS_DIRREN) += dirren.o -+aufs-$(CONFIG_AUFS_FHSM) += fhsm.o -+aufs-$(CONFIG_AUFS_POLL) += poll.o -+aufs-$(CONFIG_AUFS_RDU) += rdu.o -+aufs-$(CONFIG_AUFS_BR_HFSPLUS) += hfsplus.o -+aufs-$(CONFIG_AUFS_DEBUG) += debug.o -+aufs-$(CONFIG_AUFS_MAGIC_SYSRQ) += sysrq.o -diff -Nurp linux-5.6.3/fs/aufs/module.c linux-5.6.3-aufs/fs/aufs/module.c ---- linux-5.6.3/fs/aufs/module.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/module.c 2020-04-10 12:40:52.191049456 +0300 -@@ -0,0 +1,259 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * module global variables and operations -+ */ -+ -+#include -+#include -+#include "aufs.h" -+ -+/* shrinkable realloc */ -+void *au_krealloc(void *p, unsigned int new_sz, gfp_t gfp, int may_shrink) -+{ -+ size_t sz; -+ int diff; -+ -+ sz = 0; -+ diff = -1; -+ if (p) { -+#if 0 /* unused */ -+ if (!new_sz) { -+ au_kfree_rcu(p); -+ p = NULL; -+ goto out; -+ } -+#else -+ AuDebugOn(!new_sz); -+#endif -+ sz = ksize(p); -+ diff = au_kmidx_sub(sz, new_sz); -+ } -+ if (sz && !diff) -+ goto out; -+ -+ if (sz < new_sz) -+ /* expand or SLOB */ -+ p = krealloc(p, new_sz, gfp); -+ else if (new_sz < sz && may_shrink) { -+ /* shrink */ -+ void *q; -+ -+ q = kmalloc(new_sz, gfp); -+ if (q) { -+ if (p) { -+ memcpy(q, p, new_sz); -+ au_kfree_try_rcu(p); -+ } -+ p = q; -+ } else -+ p = NULL; -+ } -+ -+out: -+ return p; -+} -+ -+void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp, -+ int may_shrink) -+{ -+ p = au_krealloc(p, new_sz, gfp, may_shrink); -+ if (p && new_sz > nused) -+ memset(p + nused, 0, new_sz - nused); -+ return p; -+} -+ -+/* ---------------------------------------------------------------------- */ -+/* -+ * aufs caches -+ */ -+struct kmem_cache *au_cache[AuCache_Last]; -+ -+static void au_cache_fin(void) -+{ -+ int i; -+ -+ /* -+ * Make sure all delayed rcu free inodes are flushed before we -+ * destroy cache. -+ */ -+ rcu_barrier(); -+ -+ /* excluding AuCache_HNOTIFY */ -+ BUILD_BUG_ON(AuCache_HNOTIFY + 1 != AuCache_Last); -+ for (i = 0; i < AuCache_HNOTIFY; i++) { -+ kmem_cache_destroy(au_cache[i]); -+ au_cache[i] = NULL; -+ } -+} -+ -+static int __init au_cache_init(void) -+{ -+ au_cache[AuCache_DINFO] = AuCacheCtor(au_dinfo, au_di_init_once); -+ if (au_cache[AuCache_DINFO]) -+ /* SLAB_DESTROY_BY_RCU */ -+ au_cache[AuCache_ICNTNR] = AuCacheCtor(au_icntnr, -+ au_icntnr_init_once); -+ if (au_cache[AuCache_ICNTNR]) -+ au_cache[AuCache_FINFO] = AuCacheCtor(au_finfo, -+ au_fi_init_once); -+ if (au_cache[AuCache_FINFO]) -+ au_cache[AuCache_VDIR] = AuCache(au_vdir); -+ if (au_cache[AuCache_VDIR]) -+ au_cache[AuCache_DEHSTR] = AuCache(au_vdir_dehstr); -+ if (au_cache[AuCache_DEHSTR]) -+ return 0; -+ -+ au_cache_fin(); -+ return -ENOMEM; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+int au_dir_roflags; -+ -+#ifdef CONFIG_AUFS_SBILIST -+/* -+ * iterate_supers_type() doesn't protect us from -+ * remounting (branch management) -+ */ -+struct hlist_bl_head au_sbilist; -+#endif -+ -+/* -+ * functions for module interface. -+ */ -+MODULE_LICENSE("GPL"); -+/* MODULE_LICENSE("GPL v2"); */ -+MODULE_AUTHOR("Junjiro R. Okajima "); -+MODULE_DESCRIPTION(AUFS_NAME -+ " -- Advanced multi layered unification filesystem"); -+MODULE_VERSION(AUFS_VERSION); -+ -+/* this module parameter has no meaning when SYSFS is disabled */ -+int sysaufs_brs = 1; -+MODULE_PARM_DESC(brs, "use /fs/aufs/si_*/brN"); -+module_param_named(brs, sysaufs_brs, int, 0444); -+ -+/* this module parameter has no meaning when USER_NS is disabled */ -+bool au_userns; -+MODULE_PARM_DESC(allow_userns, "allow unprivileged to mount under userns"); -+module_param_named(allow_userns, au_userns, bool, 0444); -+ -+/* ---------------------------------------------------------------------- */ -+ -+static char au_esc_chars[0x20 + 3]; /* 0x01-0x20, backslash, del, and NULL */ -+ -+int au_seq_path(struct seq_file *seq, struct path *path) -+{ -+ int err; -+ -+ err = seq_path(seq, path, au_esc_chars); -+ if (err >= 0) -+ err = 0; -+ else -+ err = -ENOMEM; -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int __init aufs_init(void) -+{ -+ int err, i; -+ char *p; -+ -+ p = au_esc_chars; -+ for (i = 1; i <= ' '; i++) -+ *p++ = i; -+ *p++ = '\\'; -+ *p++ = '\x7f'; -+ *p = 0; -+ -+ au_dir_roflags = au_file_roflags(O_DIRECTORY | O_LARGEFILE); -+ -+ memcpy(aufs_iop_nogetattr, aufs_iop, sizeof(aufs_iop)); -+ for (i = 0; i < AuIop_Last; i++) -+ aufs_iop_nogetattr[i].getattr = NULL; -+ -+ memset(au_cache, 0, sizeof(au_cache)); /* including hnotify */ -+ -+ au_sbilist_init(); -+ sysaufs_brs_init(); -+ au_debug_init(); -+ au_dy_init(); -+ err = sysaufs_init(); -+ if (unlikely(err)) -+ goto out; -+ err = dbgaufs_init(); -+ if (unlikely(err)) -+ goto out_sysaufs; -+ err = au_procfs_init(); -+ if (unlikely(err)) -+ goto out_dbgaufs; -+ err = au_wkq_init(); -+ if (unlikely(err)) -+ goto out_procfs; -+ err = au_loopback_init(); -+ if (unlikely(err)) -+ goto out_wkq; -+ err = au_hnotify_init(); -+ if (unlikely(err)) -+ goto out_loopback; -+ err = au_sysrq_init(); -+ if (unlikely(err)) -+ goto out_hin; -+ err = au_cache_init(); -+ if (unlikely(err)) -+ goto out_sysrq; -+ -+ aufs_fs_type.fs_flags |= au_userns ? FS_USERNS_MOUNT : 0; -+ err = register_filesystem(&aufs_fs_type); -+ if (unlikely(err)) -+ goto out_cache; -+ -+ /* since we define pr_fmt, call printk directly */ -+ printk(KERN_INFO AUFS_NAME " " AUFS_VERSION "\n"); -+ goto out; /* success */ -+ -+out_cache: -+ au_cache_fin(); -+out_sysrq: -+ au_sysrq_fin(); -+out_hin: -+ au_hnotify_fin(); -+out_loopback: -+ au_loopback_fin(); -+out_wkq: -+ au_wkq_fin(); -+out_procfs: -+ au_procfs_fin(); -+out_dbgaufs: -+ dbgaufs_fin(); -+out_sysaufs: -+ sysaufs_fin(); -+ au_dy_fin(); -+out: -+ return err; -+} -+ -+static void __exit aufs_exit(void) -+{ -+ unregister_filesystem(&aufs_fs_type); -+ au_cache_fin(); -+ au_sysrq_fin(); -+ au_hnotify_fin(); -+ au_loopback_fin(); -+ au_wkq_fin(); -+ au_procfs_fin(); -+ dbgaufs_fin(); -+ sysaufs_fin(); -+ au_dy_fin(); -+} -+ -+module_init(aufs_init); -+module_exit(aufs_exit); -diff -Nurp linux-5.6.3/fs/aufs/module.h linux-5.6.3-aufs/fs/aufs/module.h ---- linux-5.6.3/fs/aufs/module.h 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/module.h 2020-04-10 12:40:52.191049456 +0300 -@@ -0,0 +1,153 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * module initialization and module-global -+ */ -+ -+#ifndef __AUFS_MODULE_H__ -+#define __AUFS_MODULE_H__ -+ -+#ifdef __KERNEL__ -+ -+#include -+#include "debug.h" -+#include "dentry.h" -+#include "dir.h" -+#include "file.h" -+#include "inode.h" -+ -+struct path; -+struct seq_file; -+ -+/* module parameters */ -+extern int sysaufs_brs; -+extern bool au_userns; -+ -+/* ---------------------------------------------------------------------- */ -+ -+extern int au_dir_roflags; -+ -+void *au_krealloc(void *p, unsigned int new_sz, gfp_t gfp, int may_shrink); -+void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp, -+ int may_shrink); -+ -+/* -+ * Comparing the size of the object with sizeof(struct rcu_head) -+ * case 1: object is always larger -+ * --> au_kfree_rcu() or au_kfree_do_rcu() -+ * case 2: object is always smaller -+ * --> au_kfree_small() -+ * case 3: object can be any size -+ * --> au_kfree_try_rcu() -+ */ -+ -+static inline void au_kfree_do_rcu(const void *p) -+{ -+ struct { -+ struct rcu_head rcu; -+ } *a = (void *)p; -+ -+ kfree_rcu(a, rcu); -+} -+ -+#define au_kfree_rcu(_p) do { \ -+ typeof(_p) p = (_p); \ -+ BUILD_BUG_ON(sizeof(*p) < sizeof(struct rcu_head)); \ -+ if (p) \ -+ au_kfree_do_rcu(p); \ -+ } while (0) -+ -+#define au_kfree_do_sz_test(sz) (sz >= sizeof(struct rcu_head)) -+#define au_kfree_sz_test(p) (p && au_kfree_do_sz_test(ksize(p))) -+ -+static inline void au_kfree_try_rcu(const void *p) -+{ -+ if (!p) -+ return; -+ if (au_kfree_sz_test(p)) -+ au_kfree_do_rcu(p); -+ else -+ kfree(p); -+} -+ -+static inline void au_kfree_small(const void *p) -+{ -+ if (!p) -+ return; -+ AuDebugOn(au_kfree_sz_test(p)); -+ kfree(p); -+} -+ -+static inline int au_kmidx_sub(size_t sz, size_t new_sz) -+{ -+#ifndef CONFIG_SLOB -+ return kmalloc_index(sz) - kmalloc_index(new_sz); -+#else -+ return -1; /* SLOB is untested */ -+#endif -+} -+ -+int au_seq_path(struct seq_file *seq, struct path *path); -+ -+#ifdef CONFIG_PROC_FS -+/* procfs.c */ -+int __init au_procfs_init(void); -+void au_procfs_fin(void); -+#else -+AuStubInt0(au_procfs_init, void); -+AuStubVoid(au_procfs_fin, void); -+#endif -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* kmem cache */ -+enum { -+ AuCache_DINFO, -+ AuCache_ICNTNR, -+ AuCache_FINFO, -+ AuCache_VDIR, -+ AuCache_DEHSTR, -+ AuCache_HNOTIFY, /* must be last */ -+ AuCache_Last -+}; -+ -+extern struct kmem_cache *au_cache[AuCache_Last]; -+ -+#define AuCacheFlags (SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD) -+#define AuCache(type) KMEM_CACHE(type, AuCacheFlags) -+#define AuCacheCtor(type, ctor) \ -+ kmem_cache_create(#type, sizeof(struct type), \ -+ __alignof__(struct type), AuCacheFlags, ctor) -+ -+#define AuCacheFuncs(name, index) \ -+ static inline struct au_##name *au_cache_alloc_##name(void) \ -+ { return kmem_cache_alloc(au_cache[AuCache_##index], GFP_NOFS); } \ -+ static inline void au_cache_free_##name##_norcu(struct au_##name *p) \ -+ { kmem_cache_free(au_cache[AuCache_##index], p); } \ -+ \ -+ static inline void au_cache_free_##name##_rcu_cb(struct rcu_head *rcu) \ -+ { void *p = rcu; \ -+ p -= offsetof(struct au_##name, rcu); \ -+ kmem_cache_free(au_cache[AuCache_##index], p); } \ -+ static inline void au_cache_free_##name##_rcu(struct au_##name *p) \ -+ { BUILD_BUG_ON(sizeof(struct au_##name) < sizeof(struct rcu_head)); \ -+ call_rcu(&p->rcu, au_cache_free_##name##_rcu_cb); } \ -+ \ -+ static inline void au_cache_free_##name(struct au_##name *p) \ -+ { /* au_cache_free_##name##_norcu(p); */ \ -+ au_cache_free_##name##_rcu(p); } -+ -+AuCacheFuncs(dinfo, DINFO); -+AuCacheFuncs(icntnr, ICNTNR); -+AuCacheFuncs(finfo, FINFO); -+AuCacheFuncs(vdir, VDIR); -+AuCacheFuncs(vdir_dehstr, DEHSTR); -+#ifdef CONFIG_AUFS_HNOTIFY -+AuCacheFuncs(hnotify, HNOTIFY); -+#endif -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_MODULE_H__ */ -diff -Nurp linux-5.6.3/fs/aufs/mvdown.c linux-5.6.3-aufs/fs/aufs/mvdown.c ---- linux-5.6.3/fs/aufs/mvdown.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/mvdown.c 2020-04-10 12:40:52.192049502 +0300 -@@ -0,0 +1,693 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2011-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * move-down, opposite of copy-up -+ */ -+ -+#include "aufs.h" -+ -+struct au_mvd_args { -+ struct { -+ struct super_block *h_sb; -+ struct dentry *h_parent; -+ struct au_hinode *hdir; -+ struct inode *h_dir, *h_inode; -+ struct au_pin pin; -+ } info[AUFS_MVDOWN_NARRAY]; -+ -+ struct aufs_mvdown mvdown; -+ struct dentry *dentry, *parent; -+ struct inode *inode, *dir; -+ struct super_block *sb; -+ aufs_bindex_t bopq, bwh, bfound; -+ unsigned char rename_lock; -+}; -+ -+#define mvd_errno mvdown.au_errno -+#define mvd_bsrc mvdown.stbr[AUFS_MVDOWN_UPPER].bindex -+#define mvd_src_brid mvdown.stbr[AUFS_MVDOWN_UPPER].brid -+#define mvd_bdst mvdown.stbr[AUFS_MVDOWN_LOWER].bindex -+#define mvd_dst_brid mvdown.stbr[AUFS_MVDOWN_LOWER].brid -+ -+#define mvd_h_src_sb info[AUFS_MVDOWN_UPPER].h_sb -+#define mvd_h_src_parent info[AUFS_MVDOWN_UPPER].h_parent -+#define mvd_hdir_src info[AUFS_MVDOWN_UPPER].hdir -+#define mvd_h_src_dir info[AUFS_MVDOWN_UPPER].h_dir -+#define mvd_h_src_inode info[AUFS_MVDOWN_UPPER].h_inode -+#define mvd_pin_src info[AUFS_MVDOWN_UPPER].pin -+ -+#define mvd_h_dst_sb info[AUFS_MVDOWN_LOWER].h_sb -+#define mvd_h_dst_parent info[AUFS_MVDOWN_LOWER].h_parent -+#define mvd_hdir_dst info[AUFS_MVDOWN_LOWER].hdir -+#define mvd_h_dst_dir info[AUFS_MVDOWN_LOWER].h_dir -+#define mvd_h_dst_inode info[AUFS_MVDOWN_LOWER].h_inode -+#define mvd_pin_dst info[AUFS_MVDOWN_LOWER].pin -+ -+#define AU_MVD_PR(flag, ...) do { \ -+ if (flag) \ -+ pr_err(__VA_ARGS__); \ -+ } while (0) -+ -+static int find_lower_writable(struct au_mvd_args *a) -+{ -+ struct super_block *sb; -+ aufs_bindex_t bindex, bbot; -+ struct au_branch *br; -+ -+ sb = a->sb; -+ bindex = a->mvd_bsrc; -+ bbot = au_sbbot(sb); -+ if (a->mvdown.flags & AUFS_MVDOWN_FHSM_LOWER) -+ for (bindex++; bindex <= bbot; bindex++) { -+ br = au_sbr(sb, bindex); -+ if (au_br_fhsm(br->br_perm) -+ && !sb_rdonly(au_br_sb(br))) -+ return bindex; -+ } -+ else if (!(a->mvdown.flags & AUFS_MVDOWN_ROLOWER)) -+ for (bindex++; bindex <= bbot; bindex++) { -+ br = au_sbr(sb, bindex); -+ if (!au_br_rdonly(br)) -+ return bindex; -+ } -+ else -+ for (bindex++; bindex <= bbot; bindex++) { -+ br = au_sbr(sb, bindex); -+ if (!sb_rdonly(au_br_sb(br))) { -+ if (au_br_rdonly(br)) -+ a->mvdown.flags -+ |= AUFS_MVDOWN_ROLOWER_R; -+ return bindex; -+ } -+ } -+ -+ return -1; -+} -+ -+/* make the parent dir on bdst */ -+static int au_do_mkdir(const unsigned char dmsg, struct au_mvd_args *a) -+{ -+ int err; -+ -+ err = 0; -+ a->mvd_hdir_src = au_hi(a->dir, a->mvd_bsrc); -+ a->mvd_hdir_dst = au_hi(a->dir, a->mvd_bdst); -+ a->mvd_h_src_parent = au_h_dptr(a->parent, a->mvd_bsrc); -+ a->mvd_h_dst_parent = NULL; -+ if (au_dbbot(a->parent) >= a->mvd_bdst) -+ a->mvd_h_dst_parent = au_h_dptr(a->parent, a->mvd_bdst); -+ if (!a->mvd_h_dst_parent) { -+ err = au_cpdown_dirs(a->dentry, a->mvd_bdst); -+ if (unlikely(err)) { -+ AU_MVD_PR(dmsg, "cpdown_dirs failed\n"); -+ goto out; -+ } -+ a->mvd_h_dst_parent = au_h_dptr(a->parent, a->mvd_bdst); -+ } -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+/* lock them all */ -+static int au_do_lock(const unsigned char dmsg, struct au_mvd_args *a) -+{ -+ int err; -+ struct dentry *h_trap; -+ -+ a->mvd_h_src_sb = au_sbr_sb(a->sb, a->mvd_bsrc); -+ a->mvd_h_dst_sb = au_sbr_sb(a->sb, a->mvd_bdst); -+ err = au_pin(&a->mvd_pin_dst, a->dentry, a->mvd_bdst, -+ au_opt_udba(a->sb), -+ AuPin_MNT_WRITE | AuPin_DI_LOCKED); -+ AuTraceErr(err); -+ if (unlikely(err)) { -+ AU_MVD_PR(dmsg, "pin_dst failed\n"); -+ goto out; -+ } -+ -+ if (a->mvd_h_src_sb != a->mvd_h_dst_sb) { -+ a->rename_lock = 0; -+ au_pin_init(&a->mvd_pin_src, a->dentry, a->mvd_bsrc, -+ AuLsc_DI_PARENT, AuLsc_I_PARENT3, -+ au_opt_udba(a->sb), -+ AuPin_MNT_WRITE | AuPin_DI_LOCKED); -+ err = au_do_pin(&a->mvd_pin_src); -+ AuTraceErr(err); -+ a->mvd_h_src_dir = d_inode(a->mvd_h_src_parent); -+ if (unlikely(err)) { -+ AU_MVD_PR(dmsg, "pin_src failed\n"); -+ goto out_dst; -+ } -+ goto out; /* success */ -+ } -+ -+ a->rename_lock = 1; -+ au_pin_hdir_unlock(&a->mvd_pin_dst); -+ err = au_pin(&a->mvd_pin_src, a->dentry, a->mvd_bsrc, -+ au_opt_udba(a->sb), -+ AuPin_MNT_WRITE | AuPin_DI_LOCKED); -+ AuTraceErr(err); -+ a->mvd_h_src_dir = d_inode(a->mvd_h_src_parent); -+ if (unlikely(err)) { -+ AU_MVD_PR(dmsg, "pin_src failed\n"); -+ au_pin_hdir_lock(&a->mvd_pin_dst); -+ goto out_dst; -+ } -+ au_pin_hdir_unlock(&a->mvd_pin_src); -+ h_trap = vfsub_lock_rename(a->mvd_h_src_parent, a->mvd_hdir_src, -+ a->mvd_h_dst_parent, a->mvd_hdir_dst); -+ if (h_trap) { -+ err = (h_trap != a->mvd_h_src_parent); -+ if (err) -+ err = (h_trap != a->mvd_h_dst_parent); -+ } -+ BUG_ON(err); /* it should never happen */ -+ if (unlikely(a->mvd_h_src_dir != au_pinned_h_dir(&a->mvd_pin_src))) { -+ err = -EBUSY; -+ AuTraceErr(err); -+ vfsub_unlock_rename(a->mvd_h_src_parent, a->mvd_hdir_src, -+ a->mvd_h_dst_parent, a->mvd_hdir_dst); -+ au_pin_hdir_lock(&a->mvd_pin_src); -+ au_unpin(&a->mvd_pin_src); -+ au_pin_hdir_lock(&a->mvd_pin_dst); -+ goto out_dst; -+ } -+ goto out; /* success */ -+ -+out_dst: -+ au_unpin(&a->mvd_pin_dst); -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+static void au_do_unlock(const unsigned char dmsg, struct au_mvd_args *a) -+{ -+ if (!a->rename_lock) -+ au_unpin(&a->mvd_pin_src); -+ else { -+ vfsub_unlock_rename(a->mvd_h_src_parent, a->mvd_hdir_src, -+ a->mvd_h_dst_parent, a->mvd_hdir_dst); -+ au_pin_hdir_lock(&a->mvd_pin_src); -+ au_unpin(&a->mvd_pin_src); -+ au_pin_hdir_lock(&a->mvd_pin_dst); -+ } -+ au_unpin(&a->mvd_pin_dst); -+} -+ -+/* copy-down the file */ -+static int au_do_cpdown(const unsigned char dmsg, struct au_mvd_args *a) -+{ -+ int err; -+ struct au_cp_generic cpg = { -+ .dentry = a->dentry, -+ .bdst = a->mvd_bdst, -+ .bsrc = a->mvd_bsrc, -+ .len = -1, -+ .pin = &a->mvd_pin_dst, -+ .flags = AuCpup_DTIME | AuCpup_HOPEN -+ }; -+ -+ AuDbg("b%d, b%d\n", cpg.bsrc, cpg.bdst); -+ if (a->mvdown.flags & AUFS_MVDOWN_OWLOWER) -+ au_fset_cpup(cpg.flags, OVERWRITE); -+ if (a->mvdown.flags & AUFS_MVDOWN_ROLOWER) -+ au_fset_cpup(cpg.flags, RWDST); -+ err = au_sio_cpdown_simple(&cpg); -+ if (unlikely(err)) -+ AU_MVD_PR(dmsg, "cpdown failed\n"); -+ -+ AuTraceErr(err); -+ return err; -+} -+ -+/* -+ * unlink the whiteout on bdst if exist which may be created by UDBA while we -+ * were sleeping -+ */ -+static int au_do_unlink_wh(const unsigned char dmsg, struct au_mvd_args *a) -+{ -+ int err; -+ struct path h_path; -+ struct au_branch *br; -+ struct inode *delegated; -+ -+ br = au_sbr(a->sb, a->mvd_bdst); -+ h_path.dentry = au_wh_lkup(a->mvd_h_dst_parent, &a->dentry->d_name, br); -+ err = PTR_ERR(h_path.dentry); -+ if (IS_ERR(h_path.dentry)) { -+ AU_MVD_PR(dmsg, "wh_lkup failed\n"); -+ goto out; -+ } -+ -+ err = 0; -+ if (d_is_positive(h_path.dentry)) { -+ h_path.mnt = au_br_mnt(br); -+ delegated = NULL; -+ err = vfsub_unlink(d_inode(a->mvd_h_dst_parent), &h_path, -+ &delegated, /*force*/0); -+ if (unlikely(err == -EWOULDBLOCK)) { -+ pr_warn("cannot retry for NFSv4 delegation" -+ " for an internal unlink\n"); -+ iput(delegated); -+ } -+ if (unlikely(err)) -+ AU_MVD_PR(dmsg, "wh_unlink failed\n"); -+ } -+ dput(h_path.dentry); -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+/* -+ * unlink the topmost h_dentry -+ */ -+static int au_do_unlink(const unsigned char dmsg, struct au_mvd_args *a) -+{ -+ int err; -+ struct path h_path; -+ struct inode *delegated; -+ -+ h_path.mnt = au_sbr_mnt(a->sb, a->mvd_bsrc); -+ h_path.dentry = au_h_dptr(a->dentry, a->mvd_bsrc); -+ delegated = NULL; -+ err = vfsub_unlink(a->mvd_h_src_dir, &h_path, &delegated, /*force*/0); -+ if (unlikely(err == -EWOULDBLOCK)) { -+ pr_warn("cannot retry for NFSv4 delegation" -+ " for an internal unlink\n"); -+ iput(delegated); -+ } -+ if (unlikely(err)) -+ AU_MVD_PR(dmsg, "unlink failed\n"); -+ -+ AuTraceErr(err); -+ return err; -+} -+ -+/* Since mvdown succeeded, we ignore an error of this function */ -+static void au_do_stfs(const unsigned char dmsg, struct au_mvd_args *a) -+{ -+ int err; -+ struct au_branch *br; -+ -+ a->mvdown.flags |= AUFS_MVDOWN_STFS_FAILED; -+ br = au_sbr(a->sb, a->mvd_bsrc); -+ err = au_br_stfs(br, &a->mvdown.stbr[AUFS_MVDOWN_UPPER].stfs); -+ if (!err) { -+ br = au_sbr(a->sb, a->mvd_bdst); -+ a->mvdown.stbr[AUFS_MVDOWN_LOWER].brid = br->br_id; -+ err = au_br_stfs(br, &a->mvdown.stbr[AUFS_MVDOWN_LOWER].stfs); -+ } -+ if (!err) -+ a->mvdown.flags &= ~AUFS_MVDOWN_STFS_FAILED; -+ else -+ AU_MVD_PR(dmsg, "statfs failed (%d), ignored\n", err); -+} -+ -+/* -+ * copy-down the file and unlink the bsrc file. -+ * - unlink the bdst whout if exist -+ * - copy-down the file (with whtmp name and rename) -+ * - unlink the bsrc file -+ */ -+static int au_do_mvdown(const unsigned char dmsg, struct au_mvd_args *a) -+{ -+ int err; -+ -+ err = au_do_mkdir(dmsg, a); -+ if (!err) -+ err = au_do_lock(dmsg, a); -+ if (unlikely(err)) -+ goto out; -+ -+ /* -+ * do not revert the activities we made on bdst since they should be -+ * harmless in aufs. -+ */ -+ -+ err = au_do_cpdown(dmsg, a); -+ if (!err) -+ err = au_do_unlink_wh(dmsg, a); -+ if (!err && !(a->mvdown.flags & AUFS_MVDOWN_KUPPER)) -+ err = au_do_unlink(dmsg, a); -+ if (unlikely(err)) -+ goto out_unlock; -+ -+ AuDbg("%pd2, 0x%x, %d --> %d\n", -+ a->dentry, a->mvdown.flags, a->mvd_bsrc, a->mvd_bdst); -+ if (find_lower_writable(a) < 0) -+ a->mvdown.flags |= AUFS_MVDOWN_BOTTOM; -+ -+ if (a->mvdown.flags & AUFS_MVDOWN_STFS) -+ au_do_stfs(dmsg, a); -+ -+ /* maintain internal array */ -+ if (!(a->mvdown.flags & AUFS_MVDOWN_KUPPER)) { -+ au_set_h_dptr(a->dentry, a->mvd_bsrc, NULL); -+ au_set_dbtop(a->dentry, a->mvd_bdst); -+ au_set_h_iptr(a->inode, a->mvd_bsrc, NULL, /*flags*/0); -+ au_set_ibtop(a->inode, a->mvd_bdst); -+ } else { -+ /* hide the lower */ -+ au_set_h_dptr(a->dentry, a->mvd_bdst, NULL); -+ au_set_dbbot(a->dentry, a->mvd_bsrc); -+ au_set_h_iptr(a->inode, a->mvd_bdst, NULL, /*flags*/0); -+ au_set_ibbot(a->inode, a->mvd_bsrc); -+ } -+ if (au_dbbot(a->dentry) < a->mvd_bdst) -+ au_set_dbbot(a->dentry, a->mvd_bdst); -+ if (au_ibbot(a->inode) < a->mvd_bdst) -+ au_set_ibbot(a->inode, a->mvd_bdst); -+ -+out_unlock: -+ au_do_unlock(dmsg, a); -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* make sure the file is idle */ -+static int au_mvd_args_busy(const unsigned char dmsg, struct au_mvd_args *a) -+{ -+ int err, plinked; -+ -+ err = 0; -+ plinked = !!au_opt_test(au_mntflags(a->sb), PLINK); -+ if (au_dbtop(a->dentry) == a->mvd_bsrc -+ && au_dcount(a->dentry) == 1 -+ && atomic_read(&a->inode->i_count) == 1 -+ /* && a->mvd_h_src_inode->i_nlink == 1 */ -+ && (!plinked || !au_plink_test(a->inode)) -+ && a->inode->i_nlink == 1) -+ goto out; -+ -+ err = -EBUSY; -+ AU_MVD_PR(dmsg, -+ "b%d, d{b%d, c%d?}, i{c%d?, l%u}, hi{l%u}, p{%d, %d}\n", -+ a->mvd_bsrc, au_dbtop(a->dentry), au_dcount(a->dentry), -+ atomic_read(&a->inode->i_count), a->inode->i_nlink, -+ a->mvd_h_src_inode->i_nlink, -+ plinked, plinked ? au_plink_test(a->inode) : 0); -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+/* make sure the parent dir is fine */ -+static int au_mvd_args_parent(const unsigned char dmsg, -+ struct au_mvd_args *a) -+{ -+ int err; -+ aufs_bindex_t bindex; -+ -+ err = 0; -+ if (unlikely(au_alive_dir(a->parent))) { -+ err = -ENOENT; -+ AU_MVD_PR(dmsg, "parent dir is dead\n"); -+ goto out; -+ } -+ -+ a->bopq = au_dbdiropq(a->parent); -+ bindex = au_wbr_nonopq(a->dentry, a->mvd_bdst); -+ AuDbg("b%d\n", bindex); -+ if (unlikely((bindex >= 0 && bindex < a->mvd_bdst) -+ || (a->bopq != -1 && a->bopq < a->mvd_bdst))) { -+ err = -EINVAL; -+ a->mvd_errno = EAU_MVDOWN_OPAQUE; -+ AU_MVD_PR(dmsg, "ancestor is opaque b%d, b%d\n", -+ a->bopq, a->mvd_bdst); -+ } -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+static int au_mvd_args_intermediate(const unsigned char dmsg, -+ struct au_mvd_args *a) -+{ -+ int err; -+ struct au_dinfo *dinfo, *tmp; -+ -+ /* lookup the next lower positive entry */ -+ err = -ENOMEM; -+ tmp = au_di_alloc(a->sb, AuLsc_DI_TMP); -+ if (unlikely(!tmp)) -+ goto out; -+ -+ a->bfound = -1; -+ a->bwh = -1; -+ dinfo = au_di(a->dentry); -+ au_di_cp(tmp, dinfo); -+ au_di_swap(tmp, dinfo); -+ -+ /* returns the number of positive dentries */ -+ err = au_lkup_dentry(a->dentry, a->mvd_bsrc + 1, -+ /* AuLkup_IGNORE_PERM */ 0); -+ if (!err) -+ a->bwh = au_dbwh(a->dentry); -+ else if (err > 0) -+ a->bfound = au_dbtop(a->dentry); -+ -+ au_di_swap(tmp, dinfo); -+ au_rw_write_unlock(&tmp->di_rwsem); -+ au_di_free(tmp); -+ if (unlikely(err < 0)) -+ AU_MVD_PR(dmsg, "failed look-up lower\n"); -+ -+ /* -+ * here, we have these cases. -+ * bfound == -1 -+ * no positive dentry under bsrc. there are more sub-cases. -+ * bwh < 0 -+ * there no whiteout, we can safely move-down. -+ * bwh <= bsrc -+ * impossible -+ * bsrc < bwh && bwh < bdst -+ * there is a whiteout on RO branch. cannot proceed. -+ * bwh == bdst -+ * there is a whiteout on the RW target branch. it should -+ * be removed. -+ * bdst < bwh -+ * there is a whiteout somewhere unrelated branch. -+ * -1 < bfound && bfound <= bsrc -+ * impossible. -+ * bfound < bdst -+ * found, but it is on RO branch between bsrc and bdst. cannot -+ * proceed. -+ * bfound == bdst -+ * found, replace it if AUFS_MVDOWN_FORCE is set. otherwise return -+ * error. -+ * bdst < bfound -+ * found, after we create the file on bdst, it will be hidden. -+ */ -+ -+ AuDebugOn(a->bfound == -1 -+ && a->bwh != -1 -+ && a->bwh <= a->mvd_bsrc); -+ AuDebugOn(-1 < a->bfound -+ && a->bfound <= a->mvd_bsrc); -+ -+ err = -EINVAL; -+ if (a->bfound == -1 -+ && a->mvd_bsrc < a->bwh -+ && a->bwh != -1 -+ && a->bwh < a->mvd_bdst) { -+ a->mvd_errno = EAU_MVDOWN_WHITEOUT; -+ AU_MVD_PR(dmsg, "bsrc %d, bdst %d, bfound %d, bwh %d\n", -+ a->mvd_bsrc, a->mvd_bdst, a->bfound, a->bwh); -+ goto out; -+ } else if (a->bfound != -1 && a->bfound < a->mvd_bdst) { -+ a->mvd_errno = EAU_MVDOWN_UPPER; -+ AU_MVD_PR(dmsg, "bdst %d, bfound %d\n", -+ a->mvd_bdst, a->bfound); -+ goto out; -+ } -+ -+ err = 0; /* success */ -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+static int au_mvd_args_exist(const unsigned char dmsg, struct au_mvd_args *a) -+{ -+ int err; -+ -+ err = 0; -+ if (!(a->mvdown.flags & AUFS_MVDOWN_OWLOWER) -+ && a->bfound == a->mvd_bdst) -+ err = -EEXIST; -+ AuTraceErr(err); -+ return err; -+} -+ -+static int au_mvd_args(const unsigned char dmsg, struct au_mvd_args *a) -+{ -+ int err; -+ struct au_branch *br; -+ -+ err = -EISDIR; -+ if (unlikely(S_ISDIR(a->inode->i_mode))) -+ goto out; -+ -+ err = -EINVAL; -+ if (!(a->mvdown.flags & AUFS_MVDOWN_BRID_UPPER)) -+ a->mvd_bsrc = au_ibtop(a->inode); -+ else { -+ a->mvd_bsrc = au_br_index(a->sb, a->mvd_src_brid); -+ if (unlikely(a->mvd_bsrc < 0 -+ || (a->mvd_bsrc < au_dbtop(a->dentry) -+ || au_dbbot(a->dentry) < a->mvd_bsrc -+ || !au_h_dptr(a->dentry, a->mvd_bsrc)) -+ || (a->mvd_bsrc < au_ibtop(a->inode) -+ || au_ibbot(a->inode) < a->mvd_bsrc -+ || !au_h_iptr(a->inode, a->mvd_bsrc)))) { -+ a->mvd_errno = EAU_MVDOWN_NOUPPER; -+ AU_MVD_PR(dmsg, "no upper\n"); -+ goto out; -+ } -+ } -+ if (unlikely(a->mvd_bsrc == au_sbbot(a->sb))) { -+ a->mvd_errno = EAU_MVDOWN_BOTTOM; -+ AU_MVD_PR(dmsg, "on the bottom\n"); -+ goto out; -+ } -+ a->mvd_h_src_inode = au_h_iptr(a->inode, a->mvd_bsrc); -+ br = au_sbr(a->sb, a->mvd_bsrc); -+ err = au_br_rdonly(br); -+ if (!(a->mvdown.flags & AUFS_MVDOWN_ROUPPER)) { -+ if (unlikely(err)) -+ goto out; -+ } else if (!(vfsub_native_ro(a->mvd_h_src_inode) -+ || IS_APPEND(a->mvd_h_src_inode))) { -+ if (err) -+ a->mvdown.flags |= AUFS_MVDOWN_ROUPPER_R; -+ /* go on */ -+ } else -+ goto out; -+ -+ err = -EINVAL; -+ if (!(a->mvdown.flags & AUFS_MVDOWN_BRID_LOWER)) { -+ a->mvd_bdst = find_lower_writable(a); -+ if (unlikely(a->mvd_bdst < 0)) { -+ a->mvd_errno = EAU_MVDOWN_BOTTOM; -+ AU_MVD_PR(dmsg, "no writable lower branch\n"); -+ goto out; -+ } -+ } else { -+ a->mvd_bdst = au_br_index(a->sb, a->mvd_dst_brid); -+ if (unlikely(a->mvd_bdst < 0 -+ || au_sbbot(a->sb) < a->mvd_bdst)) { -+ a->mvd_errno = EAU_MVDOWN_NOLOWERBR; -+ AU_MVD_PR(dmsg, "no lower brid\n"); -+ goto out; -+ } -+ } -+ -+ err = au_mvd_args_busy(dmsg, a); -+ if (!err) -+ err = au_mvd_args_parent(dmsg, a); -+ if (!err) -+ err = au_mvd_args_intermediate(dmsg, a); -+ if (!err) -+ err = au_mvd_args_exist(dmsg, a); -+ if (!err) -+ AuDbg("b%d, b%d\n", a->mvd_bsrc, a->mvd_bdst); -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+int au_mvdown(struct dentry *dentry, struct aufs_mvdown __user *uarg) -+{ -+ int err, e; -+ unsigned char dmsg; -+ struct au_mvd_args *args; -+ struct inode *inode; -+ -+ inode = d_inode(dentry); -+ err = -EPERM; -+ if (unlikely(!capable(CAP_SYS_ADMIN))) -+ goto out; -+ -+ err = -ENOMEM; -+ args = kmalloc(sizeof(*args), GFP_NOFS); -+ if (unlikely(!args)) -+ goto out; -+ -+ err = copy_from_user(&args->mvdown, uarg, sizeof(args->mvdown)); -+ if (!err) -+ /* VERIFY_WRITE */ -+ err = !access_ok(uarg, sizeof(*uarg)); -+ if (unlikely(err)) { -+ err = -EFAULT; -+ AuTraceErr(err); -+ goto out_free; -+ } -+ AuDbg("flags 0x%x\n", args->mvdown.flags); -+ args->mvdown.flags &= ~(AUFS_MVDOWN_ROLOWER_R | AUFS_MVDOWN_ROUPPER_R); -+ args->mvdown.au_errno = 0; -+ args->dentry = dentry; -+ args->inode = inode; -+ args->sb = dentry->d_sb; -+ -+ err = -ENOENT; -+ dmsg = !!(args->mvdown.flags & AUFS_MVDOWN_DMSG); -+ args->parent = dget_parent(dentry); -+ args->dir = d_inode(args->parent); -+ inode_lock_nested(args->dir, I_MUTEX_PARENT); -+ dput(args->parent); -+ if (unlikely(args->parent != dentry->d_parent)) { -+ AU_MVD_PR(dmsg, "parent dir is moved\n"); -+ goto out_dir; -+ } -+ -+ inode_lock_nested(inode, I_MUTEX_CHILD); -+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH | AuLock_NOPLMW); -+ if (unlikely(err)) -+ goto out_inode; -+ -+ di_write_lock_parent(args->parent); -+ err = au_mvd_args(dmsg, args); -+ if (unlikely(err)) -+ goto out_parent; -+ -+ err = au_do_mvdown(dmsg, args); -+ if (unlikely(err)) -+ goto out_parent; -+ -+ au_cpup_attr_timesizes(args->dir); -+ au_cpup_attr_timesizes(inode); -+ if (!(args->mvdown.flags & AUFS_MVDOWN_KUPPER)) -+ au_cpup_igen(inode, au_h_iptr(inode, args->mvd_bdst)); -+ /* au_digen_dec(dentry); */ -+ -+out_parent: -+ di_write_unlock(args->parent); -+ aufs_read_unlock(dentry, AuLock_DW); -+out_inode: -+ inode_unlock(inode); -+out_dir: -+ inode_unlock(args->dir); -+out_free: -+ e = copy_to_user(uarg, &args->mvdown, sizeof(args->mvdown)); -+ if (unlikely(e)) -+ err = -EFAULT; -+ au_kfree_rcu(args); -+out: -+ AuTraceErr(err); -+ return err; -+} -diff -Nurp linux-5.6.3/fs/aufs/opts.c linux-5.6.3-aufs/fs/aufs/opts.c ---- linux-5.6.3/fs/aufs/opts.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/opts.c 2020-04-10 12:40:52.192049502 +0300 -@@ -0,0 +1,1867 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * mount options/flags -+ */ -+ -+#include -+#include /* a distribution requires */ -+#include -+#include "aufs.h" -+ -+/* ---------------------------------------------------------------------- */ -+ -+enum { -+ Opt_br, -+ Opt_add, Opt_del, Opt_mod, Opt_append, Opt_prepend, -+ Opt_idel, Opt_imod, -+ Opt_dirwh, Opt_rdcache, Opt_rdblk, Opt_rdhash, -+ Opt_rdblk_def, Opt_rdhash_def, -+ Opt_xino, Opt_noxino, -+ Opt_trunc_xino, Opt_trunc_xino_v, Opt_notrunc_xino, -+ Opt_trunc_xino_path, Opt_itrunc_xino, -+ Opt_trunc_xib, Opt_notrunc_xib, -+ Opt_shwh, Opt_noshwh, -+ Opt_plink, Opt_noplink, Opt_list_plink, -+ Opt_udba, -+ Opt_dio, Opt_nodio, -+ Opt_diropq_a, Opt_diropq_w, -+ Opt_warn_perm, Opt_nowarn_perm, -+ Opt_wbr_copyup, Opt_wbr_create, -+ Opt_fhsm_sec, -+ Opt_verbose, Opt_noverbose, -+ Opt_sum, Opt_nosum, Opt_wsum, -+ Opt_dirperm1, Opt_nodirperm1, -+ Opt_dirren, Opt_nodirren, -+ Opt_acl, Opt_noacl, -+ Opt_tail, Opt_ignore, Opt_ignore_silent, Opt_err -+}; -+ -+static match_table_t options = { -+ {Opt_br, "br=%s"}, -+ {Opt_br, "br:%s"}, -+ -+ {Opt_add, "add=%d:%s"}, -+ {Opt_add, "add:%d:%s"}, -+ {Opt_add, "ins=%d:%s"}, -+ {Opt_add, "ins:%d:%s"}, -+ {Opt_append, "append=%s"}, -+ {Opt_append, "append:%s"}, -+ {Opt_prepend, "prepend=%s"}, -+ {Opt_prepend, "prepend:%s"}, -+ -+ {Opt_del, "del=%s"}, -+ {Opt_del, "del:%s"}, -+ /* {Opt_idel, "idel:%d"}, */ -+ {Opt_mod, "mod=%s"}, -+ {Opt_mod, "mod:%s"}, -+ /* {Opt_imod, "imod:%d:%s"}, */ -+ -+ {Opt_dirwh, "dirwh=%d"}, -+ -+ {Opt_xino, "xino=%s"}, -+ {Opt_noxino, "noxino"}, -+ {Opt_trunc_xino, "trunc_xino"}, -+ {Opt_trunc_xino_v, "trunc_xino_v=%d:%d"}, -+ {Opt_notrunc_xino, "notrunc_xino"}, -+ {Opt_trunc_xino_path, "trunc_xino=%s"}, -+ {Opt_itrunc_xino, "itrunc_xino=%d"}, -+ /* {Opt_zxino, "zxino=%s"}, */ -+ {Opt_trunc_xib, "trunc_xib"}, -+ {Opt_notrunc_xib, "notrunc_xib"}, -+ -+#ifdef CONFIG_PROC_FS -+ {Opt_plink, "plink"}, -+#else -+ {Opt_ignore_silent, "plink"}, -+#endif -+ -+ {Opt_noplink, "noplink"}, -+ -+#ifdef CONFIG_AUFS_DEBUG -+ {Opt_list_plink, "list_plink"}, -+#endif -+ -+ {Opt_udba, "udba=%s"}, -+ -+ {Opt_dio, "dio"}, -+ {Opt_nodio, "nodio"}, -+ -+#ifdef CONFIG_AUFS_DIRREN -+ {Opt_dirren, "dirren"}, -+ {Opt_nodirren, "nodirren"}, -+#else -+ {Opt_ignore, "dirren"}, -+ {Opt_ignore_silent, "nodirren"}, -+#endif -+ -+#ifdef CONFIG_AUFS_FHSM -+ {Opt_fhsm_sec, "fhsm_sec=%d"}, -+#else -+ {Opt_ignore, "fhsm_sec=%d"}, -+#endif -+ -+ {Opt_diropq_a, "diropq=always"}, -+ {Opt_diropq_a, "diropq=a"}, -+ {Opt_diropq_w, "diropq=whiteouted"}, -+ {Opt_diropq_w, "diropq=w"}, -+ -+ {Opt_warn_perm, "warn_perm"}, -+ {Opt_nowarn_perm, "nowarn_perm"}, -+ -+ /* keep them temporary */ -+ {Opt_ignore_silent, "nodlgt"}, -+ {Opt_ignore, "clean_plink"}, -+ -+#ifdef CONFIG_AUFS_SHWH -+ {Opt_shwh, "shwh"}, -+#endif -+ {Opt_noshwh, "noshwh"}, -+ -+ {Opt_dirperm1, "dirperm1"}, -+ {Opt_nodirperm1, "nodirperm1"}, -+ -+ {Opt_verbose, "verbose"}, -+ {Opt_verbose, "v"}, -+ {Opt_noverbose, "noverbose"}, -+ {Opt_noverbose, "quiet"}, -+ {Opt_noverbose, "q"}, -+ {Opt_noverbose, "silent"}, -+ -+ {Opt_sum, "sum"}, -+ {Opt_nosum, "nosum"}, -+ {Opt_wsum, "wsum"}, -+ -+ {Opt_rdcache, "rdcache=%d"}, -+ {Opt_rdblk, "rdblk=%d"}, -+ {Opt_rdblk_def, "rdblk=def"}, -+ {Opt_rdhash, "rdhash=%d"}, -+ {Opt_rdhash_def, "rdhash=def"}, -+ -+ {Opt_wbr_create, "create=%s"}, -+ {Opt_wbr_create, "create_policy=%s"}, -+ {Opt_wbr_copyup, "cpup=%s"}, -+ {Opt_wbr_copyup, "copyup=%s"}, -+ {Opt_wbr_copyup, "copyup_policy=%s"}, -+ -+ /* generic VFS flag */ -+#ifdef CONFIG_FS_POSIX_ACL -+ {Opt_acl, "acl"}, -+ {Opt_noacl, "noacl"}, -+#else -+ {Opt_ignore, "acl"}, -+ {Opt_ignore_silent, "noacl"}, -+#endif -+ -+ /* internal use for the scripts */ -+ {Opt_ignore_silent, "si=%s"}, -+ -+ {Opt_br, "dirs=%s"}, -+ {Opt_ignore, "debug=%d"}, -+ {Opt_ignore, "delete=whiteout"}, -+ {Opt_ignore, "delete=all"}, -+ {Opt_ignore, "imap=%s"}, -+ -+ /* temporary workaround, due to old mount(8)? */ -+ {Opt_ignore_silent, "relatime"}, -+ -+ {Opt_err, NULL} -+}; -+ -+/* ---------------------------------------------------------------------- */ -+ -+static const char *au_parser_pattern(int val, match_table_t tbl) -+{ -+ struct match_token *p; -+ -+ p = tbl; -+ while (p->pattern) { -+ if (p->token == val) -+ return p->pattern; -+ p++; -+ } -+ BUG(); -+ return "??"; -+} -+ -+static const char *au_optstr(int *val, match_table_t tbl) -+{ -+ struct match_token *p; -+ int v; -+ -+ v = *val; -+ if (!v) -+ goto out; -+ p = tbl; -+ while (p->pattern) { -+ if (p->token -+ && (v & p->token) == p->token) { -+ *val &= ~p->token; -+ return p->pattern; -+ } -+ p++; -+ } -+ -+out: -+ return NULL; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static match_table_t brperm = { -+ {AuBrPerm_RO, AUFS_BRPERM_RO}, -+ {AuBrPerm_RR, AUFS_BRPERM_RR}, -+ {AuBrPerm_RW, AUFS_BRPERM_RW}, -+ {0, NULL} -+}; -+ -+static match_table_t brattr = { -+ /* general */ -+ {AuBrAttr_COO_REG, AUFS_BRATTR_COO_REG}, -+ {AuBrAttr_COO_ALL, AUFS_BRATTR_COO_ALL}, -+ /* 'unpin' attrib is meaningless since linux-3.18-rc1 */ -+ {AuBrAttr_UNPIN, AUFS_BRATTR_UNPIN}, -+#ifdef CONFIG_AUFS_FHSM -+ {AuBrAttr_FHSM, AUFS_BRATTR_FHSM}, -+#endif -+#ifdef CONFIG_AUFS_XATTR -+ {AuBrAttr_ICEX, AUFS_BRATTR_ICEX}, -+ {AuBrAttr_ICEX_SEC, AUFS_BRATTR_ICEX_SEC}, -+ {AuBrAttr_ICEX_SYS, AUFS_BRATTR_ICEX_SYS}, -+ {AuBrAttr_ICEX_TR, AUFS_BRATTR_ICEX_TR}, -+ {AuBrAttr_ICEX_USR, AUFS_BRATTR_ICEX_USR}, -+ {AuBrAttr_ICEX_OTH, AUFS_BRATTR_ICEX_OTH}, -+#endif -+ -+ /* ro/rr branch */ -+ {AuBrRAttr_WH, AUFS_BRRATTR_WH}, -+ -+ /* rw branch */ -+ {AuBrWAttr_MOO, AUFS_BRWATTR_MOO}, -+ {AuBrWAttr_NoLinkWH, AUFS_BRWATTR_NLWH}, -+ -+ {0, NULL} -+}; -+ -+static int br_attr_val(char *str, match_table_t table, substring_t args[]) -+{ -+ int attr, v; -+ char *p; -+ -+ attr = 0; -+ do { -+ p = strchr(str, '+'); -+ if (p) -+ *p = 0; -+ v = match_token(str, table, args); -+ if (v) { -+ if (v & AuBrAttr_CMOO_Mask) -+ attr &= ~AuBrAttr_CMOO_Mask; -+ attr |= v; -+ } else { -+ if (p) -+ *p = '+'; -+ pr_warn("ignored branch attribute %s\n", str); -+ break; -+ } -+ if (p) -+ str = p + 1; -+ } while (p); -+ -+ return attr; -+} -+ -+static int au_do_optstr_br_attr(au_br_perm_str_t *str, int perm) -+{ -+ int sz; -+ const char *p; -+ char *q; -+ -+ q = str->a; -+ *q = 0; -+ p = au_optstr(&perm, brattr); -+ if (p) { -+ sz = strlen(p); -+ memcpy(q, p, sz + 1); -+ q += sz; -+ } else -+ goto out; -+ -+ do { -+ p = au_optstr(&perm, brattr); -+ if (p) { -+ *q++ = '+'; -+ sz = strlen(p); -+ memcpy(q, p, sz + 1); -+ q += sz; -+ } -+ } while (p); -+ -+out: -+ return q - str->a; -+} -+ -+static int noinline_for_stack br_perm_val(char *perm) -+{ -+ int val, bad, sz; -+ char *p; -+ substring_t args[MAX_OPT_ARGS]; -+ au_br_perm_str_t attr; -+ -+ p = strchr(perm, '+'); -+ if (p) -+ *p = 0; -+ val = match_token(perm, brperm, args); -+ if (!val) { -+ if (p) -+ *p = '+'; -+ pr_warn("ignored branch permission %s\n", perm); -+ val = AuBrPerm_RO; -+ goto out; -+ } -+ if (!p) -+ goto out; -+ -+ val |= br_attr_val(p + 1, brattr, args); -+ -+ bad = 0; -+ switch (val & AuBrPerm_Mask) { -+ case AuBrPerm_RO: -+ case AuBrPerm_RR: -+ bad = val & AuBrWAttr_Mask; -+ val &= ~AuBrWAttr_Mask; -+ break; -+ case AuBrPerm_RW: -+ bad = val & AuBrRAttr_Mask; -+ val &= ~AuBrRAttr_Mask; -+ break; -+ } -+ -+ /* -+ * 'unpin' attrib becomes meaningless since linux-3.18-rc1, but aufs -+ * does not treat it as an error, just warning. -+ * this is a tiny guard for the user operation. -+ */ -+ if (val & AuBrAttr_UNPIN) { -+ bad |= AuBrAttr_UNPIN; -+ val &= ~AuBrAttr_UNPIN; -+ } -+ -+ if (unlikely(bad)) { -+ sz = au_do_optstr_br_attr(&attr, bad); -+ AuDebugOn(!sz); -+ pr_warn("ignored branch attribute %s\n", attr.a); -+ } -+ -+out: -+ return val; -+} -+ -+void au_optstr_br_perm(au_br_perm_str_t *str, int perm) -+{ -+ au_br_perm_str_t attr; -+ const char *p; -+ char *q; -+ int sz; -+ -+ q = str->a; -+ p = au_optstr(&perm, brperm); -+ AuDebugOn(!p || !*p); -+ sz = strlen(p); -+ memcpy(q, p, sz + 1); -+ q += sz; -+ -+ sz = au_do_optstr_br_attr(&attr, perm); -+ if (sz) { -+ *q++ = '+'; -+ memcpy(q, attr.a, sz + 1); -+ } -+ -+ AuDebugOn(strlen(str->a) >= sizeof(str->a)); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static match_table_t udbalevel = { -+ {AuOpt_UDBA_REVAL, "reval"}, -+ {AuOpt_UDBA_NONE, "none"}, -+#ifdef CONFIG_AUFS_HNOTIFY -+ {AuOpt_UDBA_HNOTIFY, "notify"}, /* abstraction */ -+#ifdef CONFIG_AUFS_HFSNOTIFY -+ {AuOpt_UDBA_HNOTIFY, "fsnotify"}, -+#endif -+#endif -+ {-1, NULL} -+}; -+ -+static int noinline_for_stack udba_val(char *str) -+{ -+ substring_t args[MAX_OPT_ARGS]; -+ -+ return match_token(str, udbalevel, args); -+} -+ -+const char *au_optstr_udba(int udba) -+{ -+ return au_parser_pattern(udba, udbalevel); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static match_table_t au_wbr_create_policy = { -+ {AuWbrCreate_TDP, "tdp"}, -+ {AuWbrCreate_TDP, "top-down-parent"}, -+ {AuWbrCreate_RR, "rr"}, -+ {AuWbrCreate_RR, "round-robin"}, -+ {AuWbrCreate_MFS, "mfs"}, -+ {AuWbrCreate_MFS, "most-free-space"}, -+ {AuWbrCreate_MFSV, "mfs:%d"}, -+ {AuWbrCreate_MFSV, "most-free-space:%d"}, -+ -+ /* top-down regardless the parent, and then mfs */ -+ {AuWbrCreate_TDMFS, "tdmfs:%d"}, -+ {AuWbrCreate_TDMFSV, "tdmfs:%d:%d"}, -+ -+ {AuWbrCreate_MFSRR, "mfsrr:%d"}, -+ {AuWbrCreate_MFSRRV, "mfsrr:%d:%d"}, -+ {AuWbrCreate_PMFS, "pmfs"}, -+ {AuWbrCreate_PMFSV, "pmfs:%d"}, -+ {AuWbrCreate_PMFSRR, "pmfsrr:%d"}, -+ {AuWbrCreate_PMFSRRV, "pmfsrr:%d:%d"}, -+ -+ {-1, NULL} -+}; -+ -+static int au_wbr_mfs_wmark(substring_t *arg, char *str, -+ struct au_opt_wbr_create *create) -+{ -+ int err; -+ unsigned long long ull; -+ -+ err = 0; -+ if (!match_u64(arg, &ull)) -+ create->mfsrr_watermark = ull; -+ else { -+ pr_err("bad integer in %s\n", str); -+ err = -EINVAL; -+ } -+ -+ return err; -+} -+ -+static int au_wbr_mfs_sec(substring_t *arg, char *str, -+ struct au_opt_wbr_create *create) -+{ -+ int n, err; -+ -+ err = 0; -+ if (!match_int(arg, &n) && 0 <= n && n <= AUFS_MFS_MAX_SEC) -+ create->mfs_second = n; -+ else { -+ pr_err("bad integer in %s\n", str); -+ err = -EINVAL; -+ } -+ -+ return err; -+} -+ -+static int noinline_for_stack -+au_wbr_create_val(char *str, struct au_opt_wbr_create *create) -+{ -+ int err, e; -+ substring_t args[MAX_OPT_ARGS]; -+ -+ err = match_token(str, au_wbr_create_policy, args); -+ create->wbr_create = err; -+ switch (err) { -+ case AuWbrCreate_MFSRRV: -+ case AuWbrCreate_TDMFSV: -+ case AuWbrCreate_PMFSRRV: -+ e = au_wbr_mfs_wmark(&args[0], str, create); -+ if (!e) -+ e = au_wbr_mfs_sec(&args[1], str, create); -+ if (unlikely(e)) -+ err = e; -+ break; -+ case AuWbrCreate_MFSRR: -+ case AuWbrCreate_TDMFS: -+ case AuWbrCreate_PMFSRR: -+ e = au_wbr_mfs_wmark(&args[0], str, create); -+ if (unlikely(e)) { -+ err = e; -+ break; -+ } -+ /*FALLTHROUGH*/ -+ case AuWbrCreate_MFS: -+ case AuWbrCreate_PMFS: -+ create->mfs_second = AUFS_MFS_DEF_SEC; -+ break; -+ case AuWbrCreate_MFSV: -+ case AuWbrCreate_PMFSV: -+ e = au_wbr_mfs_sec(&args[0], str, create); -+ if (unlikely(e)) -+ err = e; -+ break; -+ } -+ -+ return err; -+} -+ -+const char *au_optstr_wbr_create(int wbr_create) -+{ -+ return au_parser_pattern(wbr_create, au_wbr_create_policy); -+} -+ -+static match_table_t au_wbr_copyup_policy = { -+ {AuWbrCopyup_TDP, "tdp"}, -+ {AuWbrCopyup_TDP, "top-down-parent"}, -+ {AuWbrCopyup_BUP, "bup"}, -+ {AuWbrCopyup_BUP, "bottom-up-parent"}, -+ {AuWbrCopyup_BU, "bu"}, -+ {AuWbrCopyup_BU, "bottom-up"}, -+ {-1, NULL} -+}; -+ -+static int noinline_for_stack au_wbr_copyup_val(char *str) -+{ -+ substring_t args[MAX_OPT_ARGS]; -+ -+ return match_token(str, au_wbr_copyup_policy, args); -+} -+ -+const char *au_optstr_wbr_copyup(int wbr_copyup) -+{ -+ return au_parser_pattern(wbr_copyup, au_wbr_copyup_policy); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static const int lkup_dirflags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY; -+ -+static void dump_opts(struct au_opts *opts) -+{ -+#ifdef CONFIG_AUFS_DEBUG -+ /* reduce stack space */ -+ union { -+ struct au_opt_add *add; -+ struct au_opt_del *del; -+ struct au_opt_mod *mod; -+ struct au_opt_xino *xino; -+ struct au_opt_xino_itrunc *xino_itrunc; -+ struct au_opt_wbr_create *create; -+ } u; -+ struct au_opt *opt; -+ -+ opt = opts->opt; -+ while (opt->type != Opt_tail) { -+ switch (opt->type) { -+ case Opt_add: -+ u.add = &opt->add; -+ AuDbg("add {b%d, %s, 0x%x, %p}\n", -+ u.add->bindex, u.add->pathname, u.add->perm, -+ u.add->path.dentry); -+ break; -+ case Opt_del: -+ case Opt_idel: -+ u.del = &opt->del; -+ AuDbg("del {%s, %p}\n", -+ u.del->pathname, u.del->h_path.dentry); -+ break; -+ case Opt_mod: -+ case Opt_imod: -+ u.mod = &opt->mod; -+ AuDbg("mod {%s, 0x%x, %p}\n", -+ u.mod->path, u.mod->perm, u.mod->h_root); -+ break; -+ case Opt_append: -+ u.add = &opt->add; -+ AuDbg("append {b%d, %s, 0x%x, %p}\n", -+ u.add->bindex, u.add->pathname, u.add->perm, -+ u.add->path.dentry); -+ break; -+ case Opt_prepend: -+ u.add = &opt->add; -+ AuDbg("prepend {b%d, %s, 0x%x, %p}\n", -+ u.add->bindex, u.add->pathname, u.add->perm, -+ u.add->path.dentry); -+ break; -+ case Opt_dirwh: -+ AuDbg("dirwh %d\n", opt->dirwh); -+ break; -+ case Opt_rdcache: -+ AuDbg("rdcache %d\n", opt->rdcache); -+ break; -+ case Opt_rdblk: -+ AuDbg("rdblk %u\n", opt->rdblk); -+ break; -+ case Opt_rdblk_def: -+ AuDbg("rdblk_def\n"); -+ break; -+ case Opt_rdhash: -+ AuDbg("rdhash %u\n", opt->rdhash); -+ break; -+ case Opt_rdhash_def: -+ AuDbg("rdhash_def\n"); -+ break; -+ case Opt_xino: -+ u.xino = &opt->xino; -+ AuDbg("xino {%s %pD}\n", u.xino->path, u.xino->file); -+ break; -+ case Opt_trunc_xino: -+ AuLabel(trunc_xino); -+ break; -+ case Opt_notrunc_xino: -+ AuLabel(notrunc_xino); -+ break; -+ case Opt_trunc_xino_path: -+ case Opt_itrunc_xino: -+ u.xino_itrunc = &opt->xino_itrunc; -+ AuDbg("trunc_xino %d\n", u.xino_itrunc->bindex); -+ break; -+ case Opt_noxino: -+ AuLabel(noxino); -+ break; -+ case Opt_trunc_xib: -+ AuLabel(trunc_xib); -+ break; -+ case Opt_notrunc_xib: -+ AuLabel(notrunc_xib); -+ break; -+ case Opt_shwh: -+ AuLabel(shwh); -+ break; -+ case Opt_noshwh: -+ AuLabel(noshwh); -+ break; -+ case Opt_dirperm1: -+ AuLabel(dirperm1); -+ break; -+ case Opt_nodirperm1: -+ AuLabel(nodirperm1); -+ break; -+ case Opt_plink: -+ AuLabel(plink); -+ break; -+ case Opt_noplink: -+ AuLabel(noplink); -+ break; -+ case Opt_list_plink: -+ AuLabel(list_plink); -+ break; -+ case Opt_udba: -+ AuDbg("udba %d, %s\n", -+ opt->udba, au_optstr_udba(opt->udba)); -+ break; -+ case Opt_dio: -+ AuLabel(dio); -+ break; -+ case Opt_nodio: -+ AuLabel(nodio); -+ break; -+ case Opt_diropq_a: -+ AuLabel(diropq_a); -+ break; -+ case Opt_diropq_w: -+ AuLabel(diropq_w); -+ break; -+ case Opt_warn_perm: -+ AuLabel(warn_perm); -+ break; -+ case Opt_nowarn_perm: -+ AuLabel(nowarn_perm); -+ break; -+ case Opt_verbose: -+ AuLabel(verbose); -+ break; -+ case Opt_noverbose: -+ AuLabel(noverbose); -+ break; -+ case Opt_sum: -+ AuLabel(sum); -+ break; -+ case Opt_nosum: -+ AuLabel(nosum); -+ break; -+ case Opt_wsum: -+ AuLabel(wsum); -+ break; -+ case Opt_wbr_create: -+ u.create = &opt->wbr_create; -+ AuDbg("create %d, %s\n", u.create->wbr_create, -+ au_optstr_wbr_create(u.create->wbr_create)); -+ switch (u.create->wbr_create) { -+ case AuWbrCreate_MFSV: -+ case AuWbrCreate_PMFSV: -+ AuDbg("%d sec\n", u.create->mfs_second); -+ break; -+ case AuWbrCreate_MFSRR: -+ case AuWbrCreate_TDMFS: -+ AuDbg("%llu watermark\n", -+ u.create->mfsrr_watermark); -+ break; -+ case AuWbrCreate_MFSRRV: -+ case AuWbrCreate_TDMFSV: -+ case AuWbrCreate_PMFSRRV: -+ AuDbg("%llu watermark, %d sec\n", -+ u.create->mfsrr_watermark, -+ u.create->mfs_second); -+ break; -+ } -+ break; -+ case Opt_wbr_copyup: -+ AuDbg("copyup %d, %s\n", opt->wbr_copyup, -+ au_optstr_wbr_copyup(opt->wbr_copyup)); -+ break; -+ case Opt_fhsm_sec: -+ AuDbg("fhsm_sec %u\n", opt->fhsm_second); -+ break; -+ case Opt_dirren: -+ AuLabel(dirren); -+ break; -+ case Opt_nodirren: -+ AuLabel(nodirren); -+ break; -+ case Opt_acl: -+ AuLabel(acl); -+ break; -+ case Opt_noacl: -+ AuLabel(noacl); -+ break; -+ default: -+ BUG(); -+ } -+ opt++; -+ } -+#endif -+} -+ -+void au_opts_free(struct au_opts *opts) -+{ -+ struct au_opt *opt; -+ -+ opt = opts->opt; -+ while (opt->type != Opt_tail) { -+ switch (opt->type) { -+ case Opt_add: -+ case Opt_append: -+ case Opt_prepend: -+ path_put(&opt->add.path); -+ break; -+ case Opt_del: -+ case Opt_idel: -+ path_put(&opt->del.h_path); -+ break; -+ case Opt_mod: -+ case Opt_imod: -+ dput(opt->mod.h_root); -+ break; -+ case Opt_xino: -+ fput(opt->xino.file); -+ break; -+ } -+ opt++; -+ } -+} -+ -+static int opt_add(struct au_opt *opt, char *opt_str, unsigned long sb_flags, -+ aufs_bindex_t bindex) -+{ -+ int err; -+ struct au_opt_add *add = &opt->add; -+ char *p; -+ -+ add->bindex = bindex; -+ add->perm = AuBrPerm_RO; -+ add->pathname = opt_str; -+ p = strchr(opt_str, '='); -+ if (p) { -+ *p++ = 0; -+ if (*p) -+ add->perm = br_perm_val(p); -+ } -+ -+ err = vfsub_kern_path(add->pathname, lkup_dirflags, &add->path); -+ if (!err) { -+ if (!p) { -+ add->perm = AuBrPerm_RO; -+ if (au_test_fs_rr(add->path.dentry->d_sb)) -+ add->perm = AuBrPerm_RR; -+ else if (!bindex && !(sb_flags & SB_RDONLY)) -+ add->perm = AuBrPerm_RW; -+ } -+ opt->type = Opt_add; -+ goto out; -+ } -+ pr_err("lookup failed %s (%d)\n", add->pathname, err); -+ err = -EINVAL; -+ -+out: -+ return err; -+} -+ -+static int au_opts_parse_del(struct au_opt_del *del, substring_t args[]) -+{ -+ int err; -+ -+ del->pathname = args[0].from; -+ AuDbg("del path %s\n", del->pathname); -+ -+ err = vfsub_kern_path(del->pathname, lkup_dirflags, &del->h_path); -+ if (unlikely(err)) -+ pr_err("lookup failed %s (%d)\n", del->pathname, err); -+ -+ return err; -+} -+ -+#if 0 /* reserved for future use */ -+static int au_opts_parse_idel(struct super_block *sb, aufs_bindex_t bindex, -+ struct au_opt_del *del, substring_t args[]) -+{ -+ int err; -+ struct dentry *root; -+ -+ err = -EINVAL; -+ root = sb->s_root; -+ aufs_read_lock(root, AuLock_FLUSH); -+ if (bindex < 0 || au_sbbot(sb) < bindex) { -+ pr_err("out of bounds, %d\n", bindex); -+ goto out; -+ } -+ -+ err = 0; -+ del->h_path.dentry = dget(au_h_dptr(root, bindex)); -+ del->h_path.mnt = mntget(au_sbr_mnt(sb, bindex)); -+ -+out: -+ aufs_read_unlock(root, !AuLock_IR); -+ return err; -+} -+#endif -+ -+static int noinline_for_stack -+au_opts_parse_mod(struct au_opt_mod *mod, substring_t args[]) -+{ -+ int err; -+ struct path path; -+ char *p; -+ -+ err = -EINVAL; -+ mod->path = args[0].from; -+ p = strchr(mod->path, '='); -+ if (unlikely(!p)) { -+ pr_err("no permission %s\n", args[0].from); -+ goto out; -+ } -+ -+ *p++ = 0; -+ err = vfsub_kern_path(mod->path, lkup_dirflags, &path); -+ if (unlikely(err)) { -+ pr_err("lookup failed %s (%d)\n", mod->path, err); -+ goto out; -+ } -+ -+ mod->perm = br_perm_val(p); -+ AuDbg("mod path %s, perm 0x%x, %s\n", mod->path, mod->perm, p); -+ mod->h_root = dget(path.dentry); -+ path_put(&path); -+ -+out: -+ return err; -+} -+ -+#if 0 /* reserved for future use */ -+static int au_opts_parse_imod(struct super_block *sb, aufs_bindex_t bindex, -+ struct au_opt_mod *mod, substring_t args[]) -+{ -+ int err; -+ struct dentry *root; -+ -+ err = -EINVAL; -+ root = sb->s_root; -+ aufs_read_lock(root, AuLock_FLUSH); -+ if (bindex < 0 || au_sbbot(sb) < bindex) { -+ pr_err("out of bounds, %d\n", bindex); -+ goto out; -+ } -+ -+ err = 0; -+ mod->perm = br_perm_val(args[1].from); -+ AuDbg("mod path %s, perm 0x%x, %s\n", -+ mod->path, mod->perm, args[1].from); -+ mod->h_root = dget(au_h_dptr(root, bindex)); -+ -+out: -+ aufs_read_unlock(root, !AuLock_IR); -+ return err; -+} -+#endif -+ -+static int au_opts_parse_xino(struct super_block *sb, struct au_opt_xino *xino, -+ substring_t args[]) -+{ -+ int err; -+ struct file *file; -+ -+ file = au_xino_create(sb, args[0].from, /*silent*/0, /*wbrtop*/0); -+ err = PTR_ERR(file); -+ if (IS_ERR(file)) -+ goto out; -+ -+ err = -EINVAL; -+ if (unlikely(file->f_path.dentry->d_sb == sb)) { -+ fput(file); -+ pr_err("%s must be outside\n", args[0].from); -+ goto out; -+ } -+ -+ err = 0; -+ xino->file = file; -+ xino->path = args[0].from; -+ -+out: -+ return err; -+} -+ -+static int noinline_for_stack -+au_opts_parse_xino_itrunc_path(struct super_block *sb, -+ struct au_opt_xino_itrunc *xino_itrunc, -+ substring_t args[]) -+{ -+ int err; -+ aufs_bindex_t bbot, bindex; -+ struct path path; -+ struct dentry *root; -+ -+ err = vfsub_kern_path(args[0].from, lkup_dirflags, &path); -+ if (unlikely(err)) { -+ pr_err("lookup failed %s (%d)\n", args[0].from, err); -+ goto out; -+ } -+ -+ xino_itrunc->bindex = -1; -+ root = sb->s_root; -+ aufs_read_lock(root, AuLock_FLUSH); -+ bbot = au_sbbot(sb); -+ for (bindex = 0; bindex <= bbot; bindex++) { -+ if (au_h_dptr(root, bindex) == path.dentry) { -+ xino_itrunc->bindex = bindex; -+ break; -+ } -+ } -+ aufs_read_unlock(root, !AuLock_IR); -+ path_put(&path); -+ -+ if (unlikely(xino_itrunc->bindex < 0)) { -+ pr_err("no such branch %s\n", args[0].from); -+ err = -EINVAL; -+ } -+ -+out: -+ return err; -+} -+ -+/* called without aufs lock */ -+int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts) -+{ -+ int err, n, token; -+ aufs_bindex_t bindex; -+ unsigned char skipped; -+ struct dentry *root; -+ struct au_opt *opt, *opt_tail; -+ char *opt_str; -+ /* reduce the stack space */ -+ union { -+ struct au_opt_xino_itrunc *xino_itrunc; -+ struct au_opt_wbr_create *create; -+ } u; -+ struct { -+ substring_t args[MAX_OPT_ARGS]; -+ } *a; -+ -+ err = -ENOMEM; -+ a = kmalloc(sizeof(*a), GFP_NOFS); -+ if (unlikely(!a)) -+ goto out; -+ -+ root = sb->s_root; -+ err = 0; -+ bindex = 0; -+ opt = opts->opt; -+ opt_tail = opt + opts->max_opt - 1; -+ opt->type = Opt_tail; -+ while (!err && (opt_str = strsep(&str, ",")) && *opt_str) { -+ err = -EINVAL; -+ skipped = 0; -+ token = match_token(opt_str, options, a->args); -+ switch (token) { -+ case Opt_br: -+ err = 0; -+ while (!err && (opt_str = strsep(&a->args[0].from, ":")) -+ && *opt_str) { -+ err = opt_add(opt, opt_str, opts->sb_flags, -+ bindex++); -+ if (unlikely(!err && ++opt > opt_tail)) { -+ err = -E2BIG; -+ break; -+ } -+ opt->type = Opt_tail; -+ skipped = 1; -+ } -+ break; -+ case Opt_add: -+ if (unlikely(match_int(&a->args[0], &n))) { -+ pr_err("bad integer in %s\n", opt_str); -+ break; -+ } -+ bindex = n; -+ err = opt_add(opt, a->args[1].from, opts->sb_flags, -+ bindex); -+ if (!err) -+ opt->type = token; -+ break; -+ case Opt_append: -+ err = opt_add(opt, a->args[0].from, opts->sb_flags, -+ /*dummy bindex*/1); -+ if (!err) -+ opt->type = token; -+ break; -+ case Opt_prepend: -+ err = opt_add(opt, a->args[0].from, opts->sb_flags, -+ /*bindex*/0); -+ if (!err) -+ opt->type = token; -+ break; -+ case Opt_del: -+ err = au_opts_parse_del(&opt->del, a->args); -+ if (!err) -+ opt->type = token; -+ break; -+#if 0 /* reserved for future use */ -+ case Opt_idel: -+ del->pathname = "(indexed)"; -+ if (unlikely(match_int(&args[0], &n))) { -+ pr_err("bad integer in %s\n", opt_str); -+ break; -+ } -+ err = au_opts_parse_idel(sb, n, &opt->del, a->args); -+ if (!err) -+ opt->type = token; -+ break; -+#endif -+ case Opt_mod: -+ err = au_opts_parse_mod(&opt->mod, a->args); -+ if (!err) -+ opt->type = token; -+ break; -+#ifdef IMOD /* reserved for future use */ -+ case Opt_imod: -+ u.mod->path = "(indexed)"; -+ if (unlikely(match_int(&a->args[0], &n))) { -+ pr_err("bad integer in %s\n", opt_str); -+ break; -+ } -+ err = au_opts_parse_imod(sb, n, &opt->mod, a->args); -+ if (!err) -+ opt->type = token; -+ break; -+#endif -+ case Opt_xino: -+ err = au_opts_parse_xino(sb, &opt->xino, a->args); -+ if (!err) -+ opt->type = token; -+ break; -+ -+ case Opt_trunc_xino_path: -+ err = au_opts_parse_xino_itrunc_path -+ (sb, &opt->xino_itrunc, a->args); -+ if (!err) -+ opt->type = token; -+ break; -+ -+ case Opt_itrunc_xino: -+ u.xino_itrunc = &opt->xino_itrunc; -+ if (unlikely(match_int(&a->args[0], &n))) { -+ pr_err("bad integer in %s\n", opt_str); -+ break; -+ } -+ u.xino_itrunc->bindex = n; -+ aufs_read_lock(root, AuLock_FLUSH); -+ if (n < 0 || au_sbbot(sb) < n) { -+ pr_err("out of bounds, %d\n", n); -+ aufs_read_unlock(root, !AuLock_IR); -+ break; -+ } -+ aufs_read_unlock(root, !AuLock_IR); -+ err = 0; -+ opt->type = token; -+ break; -+ -+ case Opt_dirwh: -+ if (unlikely(match_int(&a->args[0], &opt->dirwh))) -+ break; -+ err = 0; -+ opt->type = token; -+ break; -+ -+ case Opt_rdcache: -+ if (unlikely(match_int(&a->args[0], &n))) { -+ pr_err("bad integer in %s\n", opt_str); -+ break; -+ } -+ if (unlikely(n > AUFS_RDCACHE_MAX)) { -+ pr_err("rdcache must be smaller than %d\n", -+ AUFS_RDCACHE_MAX); -+ break; -+ } -+ opt->rdcache = n; -+ err = 0; -+ opt->type = token; -+ break; -+ case Opt_rdblk: -+ if (unlikely(match_int(&a->args[0], &n) -+ || n < 0 -+ || n > KMALLOC_MAX_SIZE)) { -+ pr_err("bad integer in %s\n", opt_str); -+ break; -+ } -+ if (unlikely(n && n < NAME_MAX)) { -+ pr_err("rdblk must be larger than %d\n", -+ NAME_MAX); -+ break; -+ } -+ opt->rdblk = n; -+ err = 0; -+ opt->type = token; -+ break; -+ case Opt_rdhash: -+ if (unlikely(match_int(&a->args[0], &n) -+ || n < 0 -+ || n * sizeof(struct hlist_head) -+ > KMALLOC_MAX_SIZE)) { -+ pr_err("bad integer in %s\n", opt_str); -+ break; -+ } -+ opt->rdhash = n; -+ err = 0; -+ opt->type = token; -+ break; -+ -+ case Opt_trunc_xino: -+ case Opt_notrunc_xino: -+ case Opt_noxino: -+ case Opt_trunc_xib: -+ case Opt_notrunc_xib: -+ case Opt_shwh: -+ case Opt_noshwh: -+ case Opt_dirperm1: -+ case Opt_nodirperm1: -+ case Opt_plink: -+ case Opt_noplink: -+ case Opt_list_plink: -+ case Opt_dio: -+ case Opt_nodio: -+ case Opt_diropq_a: -+ case Opt_diropq_w: -+ case Opt_warn_perm: -+ case Opt_nowarn_perm: -+ case Opt_verbose: -+ case Opt_noverbose: -+ case Opt_sum: -+ case Opt_nosum: -+ case Opt_wsum: -+ case Opt_rdblk_def: -+ case Opt_rdhash_def: -+ case Opt_dirren: -+ case Opt_nodirren: -+ case Opt_acl: -+ case Opt_noacl: -+ err = 0; -+ opt->type = token; -+ break; -+ -+ case Opt_udba: -+ opt->udba = udba_val(a->args[0].from); -+ if (opt->udba >= 0) { -+ err = 0; -+ opt->type = token; -+ } else -+ pr_err("wrong value, %s\n", opt_str); -+ break; -+ -+ case Opt_wbr_create: -+ u.create = &opt->wbr_create; -+ u.create->wbr_create -+ = au_wbr_create_val(a->args[0].from, u.create); -+ if (u.create->wbr_create >= 0) { -+ err = 0; -+ opt->type = token; -+ } else -+ pr_err("wrong value, %s\n", opt_str); -+ break; -+ case Opt_wbr_copyup: -+ opt->wbr_copyup = au_wbr_copyup_val(a->args[0].from); -+ if (opt->wbr_copyup >= 0) { -+ err = 0; -+ opt->type = token; -+ } else -+ pr_err("wrong value, %s\n", opt_str); -+ break; -+ -+ case Opt_fhsm_sec: -+ if (unlikely(match_int(&a->args[0], &n) -+ || n < 0)) { -+ pr_err("bad integer in %s\n", opt_str); -+ break; -+ } -+ if (sysaufs_brs) { -+ opt->fhsm_second = n; -+ opt->type = token; -+ } else -+ pr_warn("ignored %s\n", opt_str); -+ err = 0; -+ break; -+ -+ case Opt_ignore: -+ pr_warn("ignored %s\n", opt_str); -+ /*FALLTHROUGH*/ -+ case Opt_ignore_silent: -+ skipped = 1; -+ err = 0; -+ break; -+ case Opt_err: -+ pr_err("unknown option %s\n", opt_str); -+ break; -+ } -+ -+ if (!err && !skipped) { -+ if (unlikely(++opt > opt_tail)) { -+ err = -E2BIG; -+ opt--; -+ opt->type = Opt_tail; -+ break; -+ } -+ opt->type = Opt_tail; -+ } -+ } -+ -+ au_kfree_rcu(a); -+ dump_opts(opts); -+ if (unlikely(err)) -+ au_opts_free(opts); -+ -+out: -+ return err; -+} -+ -+static int au_opt_wbr_create(struct super_block *sb, -+ struct au_opt_wbr_create *create) -+{ -+ int err; -+ struct au_sbinfo *sbinfo; -+ -+ SiMustWriteLock(sb); -+ -+ err = 1; /* handled */ -+ sbinfo = au_sbi(sb); -+ if (sbinfo->si_wbr_create_ops->fin) { -+ err = sbinfo->si_wbr_create_ops->fin(sb); -+ if (!err) -+ err = 1; -+ } -+ -+ sbinfo->si_wbr_create = create->wbr_create; -+ sbinfo->si_wbr_create_ops = au_wbr_create_ops + create->wbr_create; -+ switch (create->wbr_create) { -+ case AuWbrCreate_MFSRRV: -+ case AuWbrCreate_MFSRR: -+ case AuWbrCreate_TDMFS: -+ case AuWbrCreate_TDMFSV: -+ case AuWbrCreate_PMFSRR: -+ case AuWbrCreate_PMFSRRV: -+ sbinfo->si_wbr_mfs.mfsrr_watermark = create->mfsrr_watermark; -+ /*FALLTHROUGH*/ -+ case AuWbrCreate_MFS: -+ case AuWbrCreate_MFSV: -+ case AuWbrCreate_PMFS: -+ case AuWbrCreate_PMFSV: -+ sbinfo->si_wbr_mfs.mfs_expire -+ = msecs_to_jiffies(create->mfs_second * MSEC_PER_SEC); -+ break; -+ } -+ -+ if (sbinfo->si_wbr_create_ops->init) -+ sbinfo->si_wbr_create_ops->init(sb); /* ignore */ -+ -+ return err; -+} -+ -+/* -+ * returns, -+ * plus: processed without an error -+ * zero: unprocessed -+ */ -+static int au_opt_simple(struct super_block *sb, struct au_opt *opt, -+ struct au_opts *opts) -+{ -+ int err; -+ struct au_sbinfo *sbinfo; -+ -+ SiMustWriteLock(sb); -+ -+ err = 1; /* handled */ -+ sbinfo = au_sbi(sb); -+ switch (opt->type) { -+ case Opt_udba: -+ sbinfo->si_mntflags &= ~AuOptMask_UDBA; -+ sbinfo->si_mntflags |= opt->udba; -+ opts->given_udba |= opt->udba; -+ break; -+ -+ case Opt_plink: -+ au_opt_set(sbinfo->si_mntflags, PLINK); -+ break; -+ case Opt_noplink: -+ if (au_opt_test(sbinfo->si_mntflags, PLINK)) -+ au_plink_put(sb, /*verbose*/1); -+ au_opt_clr(sbinfo->si_mntflags, PLINK); -+ break; -+ case Opt_list_plink: -+ if (au_opt_test(sbinfo->si_mntflags, PLINK)) -+ au_plink_list(sb); -+ break; -+ -+ case Opt_dio: -+ au_opt_set(sbinfo->si_mntflags, DIO); -+ au_fset_opts(opts->flags, REFRESH_DYAOP); -+ break; -+ case Opt_nodio: -+ au_opt_clr(sbinfo->si_mntflags, DIO); -+ au_fset_opts(opts->flags, REFRESH_DYAOP); -+ break; -+ -+ case Opt_fhsm_sec: -+ au_fhsm_set(sbinfo, opt->fhsm_second); -+ break; -+ -+ case Opt_diropq_a: -+ au_opt_set(sbinfo->si_mntflags, ALWAYS_DIROPQ); -+ break; -+ case Opt_diropq_w: -+ au_opt_clr(sbinfo->si_mntflags, ALWAYS_DIROPQ); -+ break; -+ -+ case Opt_warn_perm: -+ au_opt_set(sbinfo->si_mntflags, WARN_PERM); -+ break; -+ case Opt_nowarn_perm: -+ au_opt_clr(sbinfo->si_mntflags, WARN_PERM); -+ break; -+ -+ case Opt_verbose: -+ au_opt_set(sbinfo->si_mntflags, VERBOSE); -+ break; -+ case Opt_noverbose: -+ au_opt_clr(sbinfo->si_mntflags, VERBOSE); -+ break; -+ -+ case Opt_sum: -+ au_opt_set(sbinfo->si_mntflags, SUM); -+ break; -+ case Opt_wsum: -+ au_opt_clr(sbinfo->si_mntflags, SUM); -+ au_opt_set(sbinfo->si_mntflags, SUM_W); -+ break; -+ case Opt_nosum: -+ au_opt_clr(sbinfo->si_mntflags, SUM); -+ au_opt_clr(sbinfo->si_mntflags, SUM_W); -+ break; -+ -+ case Opt_wbr_create: -+ err = au_opt_wbr_create(sb, &opt->wbr_create); -+ break; -+ case Opt_wbr_copyup: -+ sbinfo->si_wbr_copyup = opt->wbr_copyup; -+ sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + opt->wbr_copyup; -+ break; -+ -+ case Opt_dirwh: -+ sbinfo->si_dirwh = opt->dirwh; -+ break; -+ -+ case Opt_rdcache: -+ sbinfo->si_rdcache -+ = msecs_to_jiffies(opt->rdcache * MSEC_PER_SEC); -+ break; -+ case Opt_rdblk: -+ sbinfo->si_rdblk = opt->rdblk; -+ break; -+ case Opt_rdblk_def: -+ sbinfo->si_rdblk = AUFS_RDBLK_DEF; -+ break; -+ case Opt_rdhash: -+ sbinfo->si_rdhash = opt->rdhash; -+ break; -+ case Opt_rdhash_def: -+ sbinfo->si_rdhash = AUFS_RDHASH_DEF; -+ break; -+ -+ case Opt_shwh: -+ au_opt_set(sbinfo->si_mntflags, SHWH); -+ break; -+ case Opt_noshwh: -+ au_opt_clr(sbinfo->si_mntflags, SHWH); -+ break; -+ -+ case Opt_dirperm1: -+ au_opt_set(sbinfo->si_mntflags, DIRPERM1); -+ break; -+ case Opt_nodirperm1: -+ au_opt_clr(sbinfo->si_mntflags, DIRPERM1); -+ break; -+ -+ case Opt_trunc_xino: -+ au_opt_set(sbinfo->si_mntflags, TRUNC_XINO); -+ break; -+ case Opt_notrunc_xino: -+ au_opt_clr(sbinfo->si_mntflags, TRUNC_XINO); -+ break; -+ -+ case Opt_trunc_xino_path: -+ case Opt_itrunc_xino: -+ err = au_xino_trunc(sb, opt->xino_itrunc.bindex, -+ /*idx_begin*/0); -+ if (!err) -+ err = 1; -+ break; -+ -+ case Opt_trunc_xib: -+ au_fset_opts(opts->flags, TRUNC_XIB); -+ break; -+ case Opt_notrunc_xib: -+ au_fclr_opts(opts->flags, TRUNC_XIB); -+ break; -+ -+ case Opt_dirren: -+ err = 1; -+ if (!au_opt_test(sbinfo->si_mntflags, DIRREN)) { -+ err = au_dr_opt_set(sb); -+ if (!err) -+ err = 1; -+ } -+ if (err == 1) -+ au_opt_set(sbinfo->si_mntflags, DIRREN); -+ break; -+ case Opt_nodirren: -+ err = 1; -+ if (au_opt_test(sbinfo->si_mntflags, DIRREN)) { -+ err = au_dr_opt_clr(sb, au_ftest_opts(opts->flags, -+ DR_FLUSHED)); -+ if (!err) -+ err = 1; -+ } -+ if (err == 1) -+ au_opt_clr(sbinfo->si_mntflags, DIRREN); -+ break; -+ -+ case Opt_acl: -+ sb->s_flags |= SB_POSIXACL; -+ break; -+ case Opt_noacl: -+ sb->s_flags &= ~SB_POSIXACL; -+ break; -+ -+ default: -+ err = 0; -+ break; -+ } -+ -+ return err; -+} -+ -+/* -+ * returns tri-state. -+ * plus: processed without an error -+ * zero: unprocessed -+ * minus: error -+ */ -+static int au_opt_br(struct super_block *sb, struct au_opt *opt, -+ struct au_opts *opts) -+{ -+ int err, do_refresh; -+ -+ err = 0; -+ switch (opt->type) { -+ case Opt_append: -+ opt->add.bindex = au_sbbot(sb) + 1; -+ if (opt->add.bindex < 0) -+ opt->add.bindex = 0; -+ goto add; -+ /* Always goto add, not fallthrough */ -+ case Opt_prepend: -+ opt->add.bindex = 0; -+ /* fallthrough */ -+ add: /* indented label */ -+ case Opt_add: -+ err = au_br_add(sb, &opt->add, -+ au_ftest_opts(opts->flags, REMOUNT)); -+ if (!err) { -+ err = 1; -+ au_fset_opts(opts->flags, REFRESH); -+ } -+ break; -+ -+ case Opt_del: -+ case Opt_idel: -+ err = au_br_del(sb, &opt->del, -+ au_ftest_opts(opts->flags, REMOUNT)); -+ if (!err) { -+ err = 1; -+ au_fset_opts(opts->flags, TRUNC_XIB); -+ au_fset_opts(opts->flags, REFRESH); -+ } -+ break; -+ -+ case Opt_mod: -+ case Opt_imod: -+ err = au_br_mod(sb, &opt->mod, -+ au_ftest_opts(opts->flags, REMOUNT), -+ &do_refresh); -+ if (!err) { -+ err = 1; -+ if (do_refresh) -+ au_fset_opts(opts->flags, REFRESH); -+ } -+ break; -+ } -+ return err; -+} -+ -+static int au_opt_xino(struct super_block *sb, struct au_opt *opt, -+ struct au_opt_xino **opt_xino, -+ struct au_opts *opts) -+{ -+ int err; -+ -+ err = 0; -+ switch (opt->type) { -+ case Opt_xino: -+ err = au_xino_set(sb, &opt->xino, -+ !!au_ftest_opts(opts->flags, REMOUNT)); -+ if (unlikely(err)) -+ break; -+ -+ *opt_xino = &opt->xino; -+ break; -+ -+ case Opt_noxino: -+ au_xino_clr(sb); -+ *opt_xino = (void *)-1; -+ break; -+ } -+ -+ return err; -+} -+ -+int au_opts_verify(struct super_block *sb, unsigned long sb_flags, -+ unsigned int pending) -+{ -+ int err, fhsm; -+ aufs_bindex_t bindex, bbot; -+ unsigned char do_plink, skip, do_free, can_no_dreval; -+ struct au_branch *br; -+ struct au_wbr *wbr; -+ struct dentry *root, *dentry; -+ struct inode *dir, *h_dir; -+ struct au_sbinfo *sbinfo; -+ struct au_hinode *hdir; -+ -+ SiMustAnyLock(sb); -+ -+ sbinfo = au_sbi(sb); -+ AuDebugOn(!(sbinfo->si_mntflags & AuOptMask_UDBA)); -+ -+ if (!(sb_flags & SB_RDONLY)) { -+ if (unlikely(!au_br_writable(au_sbr_perm(sb, 0)))) -+ pr_warn("first branch should be rw\n"); -+ if (unlikely(au_opt_test(sbinfo->si_mntflags, SHWH))) -+ pr_warn_once("shwh should be used with ro\n"); -+ } -+ -+ if (au_opt_test((sbinfo->si_mntflags | pending), UDBA_HNOTIFY) -+ && !au_opt_test(sbinfo->si_mntflags, XINO)) -+ pr_warn_once("udba=*notify requires xino\n"); -+ -+ if (au_opt_test(sbinfo->si_mntflags, DIRPERM1)) -+ pr_warn_once("dirperm1 breaks the protection" -+ " by the permission bits on the lower branch\n"); -+ -+ err = 0; -+ fhsm = 0; -+ root = sb->s_root; -+ dir = d_inode(root); -+ do_plink = !!au_opt_test(sbinfo->si_mntflags, PLINK); -+ can_no_dreval = !!au_opt_test((sbinfo->si_mntflags | pending), -+ UDBA_NONE); -+ bbot = au_sbbot(sb); -+ for (bindex = 0; !err && bindex <= bbot; bindex++) { -+ skip = 0; -+ h_dir = au_h_iptr(dir, bindex); -+ br = au_sbr(sb, bindex); -+ -+ if ((br->br_perm & AuBrAttr_ICEX) -+ && !h_dir->i_op->listxattr) -+ br->br_perm &= ~AuBrAttr_ICEX; -+#if 0 /* untested */ -+ if ((br->br_perm & AuBrAttr_ICEX_SEC) -+ && (au_br_sb(br)->s_flags & SB_NOSEC)) -+ br->br_perm &= ~AuBrAttr_ICEX_SEC; -+#endif -+ -+ do_free = 0; -+ wbr = br->br_wbr; -+ if (wbr) -+ wbr_wh_read_lock(wbr); -+ -+ if (!au_br_writable(br->br_perm)) { -+ do_free = !!wbr; -+ skip = (!wbr -+ || (!wbr->wbr_whbase -+ && !wbr->wbr_plink -+ && !wbr->wbr_orph)); -+ } else if (!au_br_wh_linkable(br->br_perm)) { -+ /* skip = (!br->br_whbase && !br->br_orph); */ -+ skip = (!wbr || !wbr->wbr_whbase); -+ if (skip && wbr) { -+ if (do_plink) -+ skip = !!wbr->wbr_plink; -+ else -+ skip = !wbr->wbr_plink; -+ } -+ } else { -+ /* skip = (br->br_whbase && br->br_ohph); */ -+ skip = (wbr && wbr->wbr_whbase); -+ if (skip) { -+ if (do_plink) -+ skip = !!wbr->wbr_plink; -+ else -+ skip = !wbr->wbr_plink; -+ } -+ } -+ if (wbr) -+ wbr_wh_read_unlock(wbr); -+ -+ if (can_no_dreval) { -+ dentry = br->br_path.dentry; -+ spin_lock(&dentry->d_lock); -+ if (dentry->d_flags & -+ (DCACHE_OP_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE)) -+ can_no_dreval = 0; -+ spin_unlock(&dentry->d_lock); -+ } -+ -+ if (au_br_fhsm(br->br_perm)) { -+ fhsm++; -+ AuDebugOn(!br->br_fhsm); -+ } -+ -+ if (skip) -+ continue; -+ -+ hdir = au_hi(dir, bindex); -+ au_hn_inode_lock_nested(hdir, AuLsc_I_PARENT); -+ if (wbr) -+ wbr_wh_write_lock(wbr); -+ err = au_wh_init(br, sb); -+ if (wbr) -+ wbr_wh_write_unlock(wbr); -+ au_hn_inode_unlock(hdir); -+ -+ if (!err && do_free) { -+ au_kfree_rcu(wbr); -+ br->br_wbr = NULL; -+ } -+ } -+ -+ if (can_no_dreval) -+ au_fset_si(sbinfo, NO_DREVAL); -+ else -+ au_fclr_si(sbinfo, NO_DREVAL); -+ -+ if (fhsm >= 2) { -+ au_fset_si(sbinfo, FHSM); -+ for (bindex = bbot; bindex >= 0; bindex--) { -+ br = au_sbr(sb, bindex); -+ if (au_br_fhsm(br->br_perm)) { -+ au_fhsm_set_bottom(sb, bindex); -+ break; -+ } -+ } -+ } else { -+ au_fclr_si(sbinfo, FHSM); -+ au_fhsm_set_bottom(sb, -1); -+ } -+ -+ return err; -+} -+ -+int au_opts_mount(struct super_block *sb, struct au_opts *opts) -+{ -+ int err; -+ unsigned int tmp; -+ aufs_bindex_t bindex, bbot; -+ struct au_opt *opt; -+ struct au_opt_xino *opt_xino, xino; -+ struct au_sbinfo *sbinfo; -+ struct au_branch *br; -+ struct inode *dir; -+ -+ SiMustWriteLock(sb); -+ -+ err = 0; -+ opt_xino = NULL; -+ opt = opts->opt; -+ while (err >= 0 && opt->type != Opt_tail) -+ err = au_opt_simple(sb, opt++, opts); -+ if (err > 0) -+ err = 0; -+ else if (unlikely(err < 0)) -+ goto out; -+ -+ /* disable xino and udba temporary */ -+ sbinfo = au_sbi(sb); -+ tmp = sbinfo->si_mntflags; -+ au_opt_clr(sbinfo->si_mntflags, XINO); -+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_REVAL); -+ -+ opt = opts->opt; -+ while (err >= 0 && opt->type != Opt_tail) -+ err = au_opt_br(sb, opt++, opts); -+ if (err > 0) -+ err = 0; -+ else if (unlikely(err < 0)) -+ goto out; -+ -+ bbot = au_sbbot(sb); -+ if (unlikely(bbot < 0)) { -+ err = -EINVAL; -+ pr_err("no branches\n"); -+ goto out; -+ } -+ -+ if (au_opt_test(tmp, XINO)) -+ au_opt_set(sbinfo->si_mntflags, XINO); -+ opt = opts->opt; -+ while (!err && opt->type != Opt_tail) -+ err = au_opt_xino(sb, opt++, &opt_xino, opts); -+ if (unlikely(err)) -+ goto out; -+ -+ err = au_opts_verify(sb, sb->s_flags, tmp); -+ if (unlikely(err)) -+ goto out; -+ -+ /* restore xino */ -+ if (au_opt_test(tmp, XINO) && !opt_xino) { -+ xino.file = au_xino_def(sb); -+ err = PTR_ERR(xino.file); -+ if (IS_ERR(xino.file)) -+ goto out; -+ -+ err = au_xino_set(sb, &xino, /*remount*/0); -+ fput(xino.file); -+ if (unlikely(err)) -+ goto out; -+ } -+ -+ /* restore udba */ -+ tmp &= AuOptMask_UDBA; -+ sbinfo->si_mntflags &= ~AuOptMask_UDBA; -+ sbinfo->si_mntflags |= tmp; -+ bbot = au_sbbot(sb); -+ for (bindex = 0; bindex <= bbot; bindex++) { -+ br = au_sbr(sb, bindex); -+ err = au_hnotify_reset_br(tmp, br, br->br_perm); -+ if (unlikely(err)) -+ AuIOErr("hnotify failed on br %d, %d, ignored\n", -+ bindex, err); -+ /* go on even if err */ -+ } -+ if (au_opt_test(tmp, UDBA_HNOTIFY)) { -+ dir = d_inode(sb->s_root); -+ au_hn_reset(dir, au_hi_flags(dir, /*isdir*/1) & ~AuHi_XINO); -+ } -+ -+out: -+ return err; -+} -+ -+int au_opts_remount(struct super_block *sb, struct au_opts *opts) -+{ -+ int err, rerr; -+ unsigned char no_dreval; -+ struct inode *dir; -+ struct au_opt_xino *opt_xino; -+ struct au_opt *opt; -+ struct au_sbinfo *sbinfo; -+ -+ SiMustWriteLock(sb); -+ -+ err = au_dr_opt_flush(sb); -+ if (unlikely(err)) -+ goto out; -+ au_fset_opts(opts->flags, DR_FLUSHED); -+ -+ dir = d_inode(sb->s_root); -+ sbinfo = au_sbi(sb); -+ opt_xino = NULL; -+ opt = opts->opt; -+ while (err >= 0 && opt->type != Opt_tail) { -+ err = au_opt_simple(sb, opt, opts); -+ if (!err) -+ err = au_opt_br(sb, opt, opts); -+ if (!err) -+ err = au_opt_xino(sb, opt, &opt_xino, opts); -+ opt++; -+ } -+ if (err > 0) -+ err = 0; -+ AuTraceErr(err); -+ /* go on even err */ -+ -+ no_dreval = !!au_ftest_si(sbinfo, NO_DREVAL); -+ rerr = au_opts_verify(sb, opts->sb_flags, /*pending*/0); -+ if (unlikely(rerr && !err)) -+ err = rerr; -+ -+ if (no_dreval != !!au_ftest_si(sbinfo, NO_DREVAL)) -+ au_fset_opts(opts->flags, REFRESH_IDOP); -+ -+ if (au_ftest_opts(opts->flags, TRUNC_XIB)) { -+ rerr = au_xib_trunc(sb); -+ if (unlikely(rerr && !err)) -+ err = rerr; -+ } -+ -+ /* will be handled by the caller */ -+ if (!au_ftest_opts(opts->flags, REFRESH) -+ && (opts->given_udba -+ || au_opt_test(sbinfo->si_mntflags, XINO) -+ || au_ftest_opts(opts->flags, REFRESH_IDOP) -+ )) -+ au_fset_opts(opts->flags, REFRESH); -+ -+ AuDbg("status 0x%x\n", opts->flags); -+ -+out: -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+unsigned int au_opt_udba(struct super_block *sb) -+{ -+ return au_mntflags(sb) & AuOptMask_UDBA; -+} -diff -Nurp linux-5.6.3/fs/aufs/opts.h linux-5.6.3-aufs/fs/aufs/opts.h ---- linux-5.6.3/fs/aufs/opts.h 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/opts.h 2020-04-10 12:40:52.192049502 +0300 -@@ -0,0 +1,212 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * mount options/flags -+ */ -+ -+#ifndef __AUFS_OPTS_H__ -+#define __AUFS_OPTS_H__ -+ -+#ifdef __KERNEL__ -+ -+#include -+ -+struct file; -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* mount flags */ -+#define AuOpt_XINO 1 /* external inode number bitmap -+ and translation table */ -+#define AuOpt_TRUNC_XINO (1 << 1) /* truncate xino files */ -+#define AuOpt_UDBA_NONE (1 << 2) /* users direct branch access */ -+#define AuOpt_UDBA_REVAL (1 << 3) -+#define AuOpt_UDBA_HNOTIFY (1 << 4) -+#define AuOpt_SHWH (1 << 5) /* show whiteout */ -+#define AuOpt_PLINK (1 << 6) /* pseudo-link */ -+#define AuOpt_DIRPERM1 (1 << 7) /* ignore the lower dir's perm -+ bits */ -+#define AuOpt_ALWAYS_DIROPQ (1 << 9) /* policy to creating diropq */ -+#define AuOpt_SUM (1 << 10) /* summation for statfs(2) */ -+#define AuOpt_SUM_W (1 << 11) /* unimplemented */ -+#define AuOpt_WARN_PERM (1 << 12) /* warn when add-branch */ -+#define AuOpt_VERBOSE (1 << 13) /* print the cause of error */ -+#define AuOpt_DIO (1 << 14) /* direct io */ -+#define AuOpt_DIRREN (1 << 15) /* directory rename */ -+ -+#ifndef CONFIG_AUFS_HNOTIFY -+#undef AuOpt_UDBA_HNOTIFY -+#define AuOpt_UDBA_HNOTIFY 0 -+#endif -+#ifndef CONFIG_AUFS_DIRREN -+#undef AuOpt_DIRREN -+#define AuOpt_DIRREN 0 -+#endif -+#ifndef CONFIG_AUFS_SHWH -+#undef AuOpt_SHWH -+#define AuOpt_SHWH 0 -+#endif -+ -+#define AuOpt_Def (AuOpt_XINO \ -+ | AuOpt_UDBA_REVAL \ -+ | AuOpt_PLINK \ -+ /* | AuOpt_DIRPERM1 */ \ -+ | AuOpt_WARN_PERM) -+#define AuOptMask_UDBA (AuOpt_UDBA_NONE \ -+ | AuOpt_UDBA_REVAL \ -+ | AuOpt_UDBA_HNOTIFY) -+ -+#define au_opt_test(flags, name) (flags & AuOpt_##name) -+#define au_opt_set(flags, name) do { \ -+ BUILD_BUG_ON(AuOpt_##name & AuOptMask_UDBA); \ -+ ((flags) |= AuOpt_##name); \ -+} while (0) -+#define au_opt_set_udba(flags, name) do { \ -+ (flags) &= ~AuOptMask_UDBA; \ -+ ((flags) |= AuOpt_##name); \ -+} while (0) -+#define au_opt_clr(flags, name) do { \ -+ ((flags) &= ~AuOpt_##name); \ -+} while (0) -+ -+static inline unsigned int au_opts_plink(unsigned int mntflags) -+{ -+#ifdef CONFIG_PROC_FS -+ return mntflags; -+#else -+ return mntflags & ~AuOpt_PLINK; -+#endif -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* policies to select one among multiple writable branches */ -+enum { -+ AuWbrCreate_TDP, /* top down parent */ -+ AuWbrCreate_RR, /* round robin */ -+ AuWbrCreate_MFS, /* most free space */ -+ AuWbrCreate_MFSV, /* mfs with seconds */ -+ AuWbrCreate_MFSRR, /* mfs then rr */ -+ AuWbrCreate_MFSRRV, /* mfs then rr with seconds */ -+ AuWbrCreate_TDMFS, /* top down regardless parent and mfs */ -+ AuWbrCreate_TDMFSV, /* top down regardless parent and mfs */ -+ AuWbrCreate_PMFS, /* parent and mfs */ -+ AuWbrCreate_PMFSV, /* parent and mfs with seconds */ -+ AuWbrCreate_PMFSRR, /* parent, mfs and round-robin */ -+ AuWbrCreate_PMFSRRV, /* plus seconds */ -+ -+ AuWbrCreate_Def = AuWbrCreate_TDP -+}; -+ -+enum { -+ AuWbrCopyup_TDP, /* top down parent */ -+ AuWbrCopyup_BUP, /* bottom up parent */ -+ AuWbrCopyup_BU, /* bottom up */ -+ -+ AuWbrCopyup_Def = AuWbrCopyup_TDP -+}; -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct au_opt_add { -+ aufs_bindex_t bindex; -+ char *pathname; -+ int perm; -+ struct path path; -+}; -+ -+struct au_opt_del { -+ char *pathname; -+ struct path h_path; -+}; -+ -+struct au_opt_mod { -+ char *path; -+ int perm; -+ struct dentry *h_root; -+}; -+ -+struct au_opt_xino { -+ char *path; -+ struct file *file; -+}; -+ -+struct au_opt_xino_itrunc { -+ aufs_bindex_t bindex; -+}; -+ -+struct au_opt_wbr_create { -+ int wbr_create; -+ int mfs_second; -+ unsigned long long mfsrr_watermark; -+}; -+ -+struct au_opt { -+ int type; -+ union { -+ struct au_opt_xino xino; -+ struct au_opt_xino_itrunc xino_itrunc; -+ struct au_opt_add add; -+ struct au_opt_del del; -+ struct au_opt_mod mod; -+ int dirwh; -+ int rdcache; -+ unsigned int rdblk; -+ unsigned int rdhash; -+ int udba; -+ struct au_opt_wbr_create wbr_create; -+ int wbr_copyup; -+ unsigned int fhsm_second; -+ }; -+}; -+ -+/* opts flags */ -+#define AuOpts_REMOUNT 1 -+#define AuOpts_REFRESH (1 << 1) -+#define AuOpts_TRUNC_XIB (1 << 2) -+#define AuOpts_REFRESH_DYAOP (1 << 3) -+#define AuOpts_REFRESH_IDOP (1 << 4) -+#define AuOpts_DR_FLUSHED (1 << 5) -+#define au_ftest_opts(flags, name) ((flags) & AuOpts_##name) -+#define au_fset_opts(flags, name) \ -+ do { (flags) |= AuOpts_##name; } while (0) -+#define au_fclr_opts(flags, name) \ -+ do { (flags) &= ~AuOpts_##name; } while (0) -+ -+#ifndef CONFIG_AUFS_DIRREN -+#undef AuOpts_DR_FLUSHED -+#define AuOpts_DR_FLUSHED 0 -+#endif -+ -+struct au_opts { -+ struct au_opt *opt; -+ int max_opt; -+ -+ unsigned int given_udba; -+ unsigned int flags; -+ unsigned long sb_flags; -+}; -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* opts.c */ -+void au_optstr_br_perm(au_br_perm_str_t *str, int perm); -+const char *au_optstr_udba(int udba); -+const char *au_optstr_wbr_copyup(int wbr_copyup); -+const char *au_optstr_wbr_create(int wbr_create); -+ -+void au_opts_free(struct au_opts *opts); -+struct super_block; -+int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts); -+int au_opts_verify(struct super_block *sb, unsigned long sb_flags, -+ unsigned int pending); -+int au_opts_mount(struct super_block *sb, struct au_opts *opts); -+int au_opts_remount(struct super_block *sb, struct au_opts *opts); -+ -+unsigned int au_opt_udba(struct super_block *sb); -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_OPTS_H__ */ -diff -Nurp linux-5.6.3/fs/aufs/plink.c linux-5.6.3-aufs/fs/aufs/plink.c ---- linux-5.6.3/fs/aufs/plink.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/plink.c 2020-04-10 12:40:52.192049502 +0300 -@@ -0,0 +1,503 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * pseudo-link -+ */ -+ -+#include "aufs.h" -+ -+/* -+ * the pseudo-link maintenance mode. -+ * during a user process maintains the pseudo-links, -+ * prohibit adding a new plink and branch manipulation. -+ * -+ * Flags -+ * NOPLM: -+ * For entry functions which will handle plink, and i_mutex is already held -+ * in VFS. -+ * They cannot wait and should return an error at once. -+ * Callers has to check the error. -+ * NOPLMW: -+ * For entry functions which will handle plink, but i_mutex is not held -+ * in VFS. -+ * They can wait the plink maintenance mode to finish. -+ * -+ * They behave like F_SETLK and F_SETLKW. -+ * If the caller never handle plink, then both flags are unnecessary. -+ */ -+ -+int au_plink_maint(struct super_block *sb, int flags) -+{ -+ int err; -+ pid_t pid, ppid; -+ struct task_struct *parent, *prev; -+ struct au_sbinfo *sbi; -+ -+ SiMustAnyLock(sb); -+ -+ err = 0; -+ if (!au_opt_test(au_mntflags(sb), PLINK)) -+ goto out; -+ -+ sbi = au_sbi(sb); -+ pid = sbi->si_plink_maint_pid; -+ if (!pid || pid == current->pid) -+ goto out; -+ -+ /* todo: it highly depends upon /sbin/mount.aufs */ -+ prev = NULL; -+ parent = current; -+ ppid = 0; -+ rcu_read_lock(); -+ while (1) { -+ parent = rcu_dereference(parent->real_parent); -+ if (parent == prev) -+ break; -+ ppid = task_pid_vnr(parent); -+ if (pid == ppid) { -+ rcu_read_unlock(); -+ goto out; -+ } -+ prev = parent; -+ } -+ rcu_read_unlock(); -+ -+ if (au_ftest_lock(flags, NOPLMW)) { -+ /* if there is no i_mutex lock in VFS, we don't need to wait */ -+ /* AuDebugOn(!lockdep_depth(current)); */ -+ while (sbi->si_plink_maint_pid) { -+ si_read_unlock(sb); -+ /* gave up wake_up_bit() */ -+ wait_event(sbi->si_plink_wq, !sbi->si_plink_maint_pid); -+ -+ if (au_ftest_lock(flags, FLUSH)) -+ au_nwt_flush(&sbi->si_nowait); -+ si_noflush_read_lock(sb); -+ } -+ } else if (au_ftest_lock(flags, NOPLM)) { -+ AuDbg("ppid %d, pid %d\n", ppid, pid); -+ err = -EAGAIN; -+ } -+ -+out: -+ return err; -+} -+ -+void au_plink_maint_leave(struct au_sbinfo *sbinfo) -+{ -+ spin_lock(&sbinfo->si_plink_maint_lock); -+ sbinfo->si_plink_maint_pid = 0; -+ spin_unlock(&sbinfo->si_plink_maint_lock); -+ wake_up_all(&sbinfo->si_plink_wq); -+} -+ -+int au_plink_maint_enter(struct super_block *sb) -+{ -+ int err; -+ struct au_sbinfo *sbinfo; -+ -+ err = 0; -+ sbinfo = au_sbi(sb); -+ /* make sure i am the only one in this fs */ -+ si_write_lock(sb, AuLock_FLUSH); -+ if (au_opt_test(au_mntflags(sb), PLINK)) { -+ spin_lock(&sbinfo->si_plink_maint_lock); -+ if (!sbinfo->si_plink_maint_pid) -+ sbinfo->si_plink_maint_pid = current->pid; -+ else -+ err = -EBUSY; -+ spin_unlock(&sbinfo->si_plink_maint_lock); -+ } -+ si_write_unlock(sb); -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+#ifdef CONFIG_AUFS_DEBUG -+void au_plink_list(struct super_block *sb) -+{ -+ int i; -+ struct au_sbinfo *sbinfo; -+ struct hlist_bl_head *hbl; -+ struct hlist_bl_node *pos; -+ struct au_icntnr *icntnr; -+ -+ SiMustAnyLock(sb); -+ -+ sbinfo = au_sbi(sb); -+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK)); -+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM)); -+ -+ for (i = 0; i < AuPlink_NHASH; i++) { -+ hbl = sbinfo->si_plink + i; -+ hlist_bl_lock(hbl); -+ hlist_bl_for_each_entry(icntnr, pos, hbl, plink) -+ AuDbg("%lu\n", icntnr->vfs_inode.i_ino); -+ hlist_bl_unlock(hbl); -+ } -+} -+#endif -+ -+/* is the inode pseudo-linked? */ -+int au_plink_test(struct inode *inode) -+{ -+ int found, i; -+ struct au_sbinfo *sbinfo; -+ struct hlist_bl_head *hbl; -+ struct hlist_bl_node *pos; -+ struct au_icntnr *icntnr; -+ -+ sbinfo = au_sbi(inode->i_sb); -+ AuRwMustAnyLock(&sbinfo->si_rwsem); -+ AuDebugOn(!au_opt_test(au_mntflags(inode->i_sb), PLINK)); -+ AuDebugOn(au_plink_maint(inode->i_sb, AuLock_NOPLM)); -+ -+ found = 0; -+ i = au_plink_hash(inode->i_ino); -+ hbl = sbinfo->si_plink + i; -+ hlist_bl_lock(hbl); -+ hlist_bl_for_each_entry(icntnr, pos, hbl, plink) -+ if (&icntnr->vfs_inode == inode) { -+ found = 1; -+ break; -+ } -+ hlist_bl_unlock(hbl); -+ return found; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * generate a name for plink. -+ * the file will be stored under AUFS_WH_PLINKDIR. -+ */ -+/* 20 is max digits length of ulong 64 */ -+#define PLINK_NAME_LEN ((20 + 1) * 2) -+ -+static int plink_name(char *name, int len, struct inode *inode, -+ aufs_bindex_t bindex) -+{ -+ int rlen; -+ struct inode *h_inode; -+ -+ h_inode = au_h_iptr(inode, bindex); -+ rlen = snprintf(name, len, "%lu.%lu", inode->i_ino, h_inode->i_ino); -+ return rlen; -+} -+ -+struct au_do_plink_lkup_args { -+ struct dentry **errp; -+ struct qstr *tgtname; -+ struct dentry *h_parent; -+ struct au_branch *br; -+}; -+ -+static struct dentry *au_do_plink_lkup(struct qstr *tgtname, -+ struct dentry *h_parent, -+ struct au_branch *br) -+{ -+ struct dentry *h_dentry; -+ struct inode *h_inode; -+ -+ h_inode = d_inode(h_parent); -+ inode_lock_shared_nested(h_inode, AuLsc_I_CHILD2); -+ h_dentry = vfsub_lkup_one(tgtname, h_parent); -+ inode_unlock_shared(h_inode); -+ return h_dentry; -+} -+ -+static void au_call_do_plink_lkup(void *args) -+{ -+ struct au_do_plink_lkup_args *a = args; -+ *a->errp = au_do_plink_lkup(a->tgtname, a->h_parent, a->br); -+} -+ -+/* lookup the plink-ed @inode under the branch at @bindex */ -+struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex) -+{ -+ struct dentry *h_dentry, *h_parent; -+ struct au_branch *br; -+ int wkq_err; -+ char a[PLINK_NAME_LEN]; -+ struct qstr tgtname = QSTR_INIT(a, 0); -+ -+ AuDebugOn(au_plink_maint(inode->i_sb, AuLock_NOPLM)); -+ -+ br = au_sbr(inode->i_sb, bindex); -+ h_parent = br->br_wbr->wbr_plink; -+ tgtname.len = plink_name(a, sizeof(a), inode, bindex); -+ -+ if (!uid_eq(current_fsuid(), GLOBAL_ROOT_UID)) { -+ struct au_do_plink_lkup_args args = { -+ .errp = &h_dentry, -+ .tgtname = &tgtname, -+ .h_parent = h_parent, -+ .br = br -+ }; -+ -+ wkq_err = au_wkq_wait(au_call_do_plink_lkup, &args); -+ if (unlikely(wkq_err)) -+ h_dentry = ERR_PTR(wkq_err); -+ } else -+ h_dentry = au_do_plink_lkup(&tgtname, h_parent, br); -+ -+ return h_dentry; -+} -+ -+/* create a pseudo-link */ -+static int do_whplink(struct qstr *tgt, struct dentry *h_parent, -+ struct dentry *h_dentry, struct au_branch *br) -+{ -+ int err; -+ struct path h_path = { -+ .mnt = au_br_mnt(br) -+ }; -+ struct inode *h_dir, *delegated; -+ -+ h_dir = d_inode(h_parent); -+ inode_lock_nested(h_dir, AuLsc_I_CHILD2); -+again: -+ h_path.dentry = vfsub_lkup_one(tgt, h_parent); -+ err = PTR_ERR(h_path.dentry); -+ if (IS_ERR(h_path.dentry)) -+ goto out; -+ -+ err = 0; -+ /* wh.plink dir is not monitored */ -+ /* todo: is it really safe? */ -+ if (d_is_positive(h_path.dentry) -+ && d_inode(h_path.dentry) != d_inode(h_dentry)) { -+ delegated = NULL; -+ err = vfsub_unlink(h_dir, &h_path, &delegated, /*force*/0); -+ if (unlikely(err == -EWOULDBLOCK)) { -+ pr_warn("cannot retry for NFSv4 delegation" -+ " for an internal unlink\n"); -+ iput(delegated); -+ } -+ dput(h_path.dentry); -+ h_path.dentry = NULL; -+ if (!err) -+ goto again; -+ } -+ if (!err && d_is_negative(h_path.dentry)) { -+ delegated = NULL; -+ err = vfsub_link(h_dentry, h_dir, &h_path, &delegated); -+ if (unlikely(err == -EWOULDBLOCK)) { -+ pr_warn("cannot retry for NFSv4 delegation" -+ " for an internal link\n"); -+ iput(delegated); -+ } -+ } -+ dput(h_path.dentry); -+ -+out: -+ inode_unlock(h_dir); -+ return err; -+} -+ -+struct do_whplink_args { -+ int *errp; -+ struct qstr *tgt; -+ struct dentry *h_parent; -+ struct dentry *h_dentry; -+ struct au_branch *br; -+}; -+ -+static void call_do_whplink(void *args) -+{ -+ struct do_whplink_args *a = args; -+ *a->errp = do_whplink(a->tgt, a->h_parent, a->h_dentry, a->br); -+} -+ -+static int whplink(struct dentry *h_dentry, struct inode *inode, -+ aufs_bindex_t bindex, struct au_branch *br) -+{ -+ int err, wkq_err; -+ struct au_wbr *wbr; -+ struct dentry *h_parent; -+ char a[PLINK_NAME_LEN]; -+ struct qstr tgtname = QSTR_INIT(a, 0); -+ -+ wbr = au_sbr(inode->i_sb, bindex)->br_wbr; -+ h_parent = wbr->wbr_plink; -+ tgtname.len = plink_name(a, sizeof(a), inode, bindex); -+ -+ /* always superio. */ -+ if (!uid_eq(current_fsuid(), GLOBAL_ROOT_UID)) { -+ struct do_whplink_args args = { -+ .errp = &err, -+ .tgt = &tgtname, -+ .h_parent = h_parent, -+ .h_dentry = h_dentry, -+ .br = br -+ }; -+ wkq_err = au_wkq_wait(call_do_whplink, &args); -+ if (unlikely(wkq_err)) -+ err = wkq_err; -+ } else -+ err = do_whplink(&tgtname, h_parent, h_dentry, br); -+ -+ return err; -+} -+ -+/* -+ * create a new pseudo-link for @h_dentry on @bindex. -+ * the linked inode is held in aufs @inode. -+ */ -+void au_plink_append(struct inode *inode, aufs_bindex_t bindex, -+ struct dentry *h_dentry) -+{ -+ struct super_block *sb; -+ struct au_sbinfo *sbinfo; -+ struct hlist_bl_head *hbl; -+ struct hlist_bl_node *pos; -+ struct au_icntnr *icntnr; -+ int found, err, cnt, i; -+ -+ sb = inode->i_sb; -+ sbinfo = au_sbi(sb); -+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK)); -+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM)); -+ -+ found = au_plink_test(inode); -+ if (found) -+ return; -+ -+ i = au_plink_hash(inode->i_ino); -+ hbl = sbinfo->si_plink + i; -+ au_igrab(inode); -+ -+ hlist_bl_lock(hbl); -+ hlist_bl_for_each_entry(icntnr, pos, hbl, plink) { -+ if (&icntnr->vfs_inode == inode) { -+ found = 1; -+ break; -+ } -+ } -+ if (!found) { -+ icntnr = container_of(inode, struct au_icntnr, vfs_inode); -+ hlist_bl_add_head(&icntnr->plink, hbl); -+ } -+ hlist_bl_unlock(hbl); -+ if (!found) { -+ cnt = au_hbl_count(hbl); -+#define msg "unexpectedly unbalanced or too many pseudo-links" -+ if (cnt > AUFS_PLINK_WARN) -+ AuWarn1(msg ", %d\n", cnt); -+#undef msg -+ err = whplink(h_dentry, inode, bindex, au_sbr(sb, bindex)); -+ if (unlikely(err)) { -+ pr_warn("err %d, damaged pseudo link.\n", err); -+ au_hbl_del(&icntnr->plink, hbl); -+ iput(&icntnr->vfs_inode); -+ } -+ } else -+ iput(&icntnr->vfs_inode); -+} -+ -+/* free all plinks */ -+void au_plink_put(struct super_block *sb, int verbose) -+{ -+ int i, warned; -+ struct au_sbinfo *sbinfo; -+ struct hlist_bl_head *hbl; -+ struct hlist_bl_node *pos, *tmp; -+ struct au_icntnr *icntnr; -+ -+ SiMustWriteLock(sb); -+ -+ sbinfo = au_sbi(sb); -+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK)); -+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM)); -+ -+ /* no spin_lock since sbinfo is write-locked */ -+ warned = 0; -+ for (i = 0; i < AuPlink_NHASH; i++) { -+ hbl = sbinfo->si_plink + i; -+ if (!warned && verbose && !hlist_bl_empty(hbl)) { -+ pr_warn("pseudo-link is not flushed"); -+ warned = 1; -+ } -+ hlist_bl_for_each_entry_safe(icntnr, pos, tmp, hbl, plink) -+ iput(&icntnr->vfs_inode); -+ INIT_HLIST_BL_HEAD(hbl); -+ } -+} -+ -+void au_plink_clean(struct super_block *sb, int verbose) -+{ -+ struct dentry *root; -+ -+ root = sb->s_root; -+ aufs_write_lock(root); -+ if (au_opt_test(au_mntflags(sb), PLINK)) -+ au_plink_put(sb, verbose); -+ aufs_write_unlock(root); -+} -+ -+static int au_plink_do_half_refresh(struct inode *inode, aufs_bindex_t br_id) -+{ -+ int do_put; -+ aufs_bindex_t btop, bbot, bindex; -+ -+ do_put = 0; -+ btop = au_ibtop(inode); -+ bbot = au_ibbot(inode); -+ if (btop >= 0) { -+ for (bindex = btop; bindex <= bbot; bindex++) { -+ if (!au_h_iptr(inode, bindex) -+ || au_ii_br_id(inode, bindex) != br_id) -+ continue; -+ au_set_h_iptr(inode, bindex, NULL, 0); -+ do_put = 1; -+ break; -+ } -+ if (do_put) -+ for (bindex = btop; bindex <= bbot; bindex++) -+ if (au_h_iptr(inode, bindex)) { -+ do_put = 0; -+ break; -+ } -+ } else -+ do_put = 1; -+ -+ return do_put; -+} -+ -+/* free the plinks on a branch specified by @br_id */ -+void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id) -+{ -+ struct au_sbinfo *sbinfo; -+ struct hlist_bl_head *hbl; -+ struct hlist_bl_node *pos, *tmp; -+ struct au_icntnr *icntnr; -+ struct inode *inode; -+ int i, do_put; -+ -+ SiMustWriteLock(sb); -+ -+ sbinfo = au_sbi(sb); -+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK)); -+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM)); -+ -+ /* no bit_lock since sbinfo is write-locked */ -+ for (i = 0; i < AuPlink_NHASH; i++) { -+ hbl = sbinfo->si_plink + i; -+ hlist_bl_for_each_entry_safe(icntnr, pos, tmp, hbl, plink) { -+ inode = au_igrab(&icntnr->vfs_inode); -+ ii_write_lock_child(inode); -+ do_put = au_plink_do_half_refresh(inode, br_id); -+ if (do_put) { -+ hlist_bl_del(&icntnr->plink); -+ iput(inode); -+ } -+ ii_write_unlock(inode); -+ iput(inode); -+ } -+ } -+} -diff -Nurp linux-5.6.3/fs/aufs/poll.c linux-5.6.3-aufs/fs/aufs/poll.c ---- linux-5.6.3/fs/aufs/poll.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/poll.c 2020-04-10 12:40:52.192049502 +0300 -@@ -0,0 +1,38 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * poll operation -+ * There is only one filesystem which implements ->poll operation, currently. -+ */ -+ -+#include "aufs.h" -+ -+__poll_t aufs_poll(struct file *file, struct poll_table_struct *pt) -+{ -+ __poll_t mask; -+ struct file *h_file; -+ struct super_block *sb; -+ -+ /* We should pretend an error happened. */ -+ mask = EPOLLERR /* | EPOLLIN | EPOLLOUT */; -+ sb = file->f_path.dentry->d_sb; -+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW); -+ -+ h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0); -+ if (IS_ERR(h_file)) { -+ AuDbg("h_file %ld\n", PTR_ERR(h_file)); -+ goto out; -+ } -+ -+ mask = vfs_poll(h_file, pt); -+ fput(h_file); /* instead of au_read_post() */ -+ -+out: -+ si_read_unlock(sb); -+ if (mask & EPOLLERR) -+ AuDbg("mask 0x%x\n", mask); -+ return mask; -+} -diff -Nurp linux-5.6.3/fs/aufs/posix_acl.c linux-5.6.3-aufs/fs/aufs/posix_acl.c ---- linux-5.6.3/fs/aufs/posix_acl.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/posix_acl.c 2020-04-10 12:40:52.192049502 +0300 -@@ -0,0 +1,92 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2014-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * posix acl operations -+ */ -+ -+#include -+#include "aufs.h" -+ -+struct posix_acl *aufs_get_acl(struct inode *inode, int type) -+{ -+ struct posix_acl *acl; -+ int err; -+ aufs_bindex_t bindex; -+ struct inode *h_inode; -+ struct super_block *sb; -+ -+ acl = NULL; -+ sb = inode->i_sb; -+ si_read_lock(sb, AuLock_FLUSH); -+ ii_read_lock_child(inode); -+ if (!(sb->s_flags & SB_POSIXACL)) -+ goto out; -+ -+ bindex = au_ibtop(inode); -+ h_inode = au_h_iptr(inode, bindex); -+ if (unlikely(!h_inode -+ || ((h_inode->i_mode & S_IFMT) -+ != (inode->i_mode & S_IFMT)))) { -+ err = au_busy_or_stale(); -+ acl = ERR_PTR(err); -+ goto out; -+ } -+ -+ /* always topmost only */ -+ acl = get_acl(h_inode, type); -+ if (IS_ERR(acl)) -+ forget_cached_acl(inode, type); -+ else -+ set_cached_acl(inode, type, acl); -+ -+out: -+ ii_read_unlock(inode); -+ si_read_unlock(sb); -+ -+ AuTraceErrPtr(acl); -+ return acl; -+} -+ -+int aufs_set_acl(struct inode *inode, struct posix_acl *acl, int type) -+{ -+ int err; -+ ssize_t ssz; -+ struct dentry *dentry; -+ struct au_sxattr arg = { -+ .type = AU_ACL_SET, -+ .u.acl_set = { -+ .acl = acl, -+ .type = type -+ }, -+ }; -+ -+ IMustLock(inode); -+ -+ if (inode->i_ino == AUFS_ROOT_INO) -+ dentry = dget(inode->i_sb->s_root); -+ else { -+ dentry = d_find_alias(inode); -+ if (!dentry) -+ dentry = d_find_any_alias(inode); -+ if (!dentry) { -+ pr_warn("cannot handle this inode, " -+ "please report to aufs-users ML\n"); -+ err = -ENOENT; -+ goto out; -+ } -+ } -+ -+ ssz = au_sxattr(dentry, inode, &arg); -+ /* forget even it if succeeds since the branch might set differently */ -+ forget_cached_acl(inode, type); -+ dput(dentry); -+ err = ssz; -+ if (ssz >= 0) -+ err = 0; -+ -+out: -+ return err; -+} -diff -Nurp linux-5.6.3/fs/aufs/procfs.c linux-5.6.3-aufs/fs/aufs/procfs.c ---- linux-5.6.3/fs/aufs/procfs.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/procfs.c 2020-04-10 12:40:52.192049502 +0300 -@@ -0,0 +1,158 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2010-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * procfs interfaces -+ */ -+ -+#include -+#include "aufs.h" -+ -+static int au_procfs_plm_release(struct inode *inode, struct file *file) -+{ -+ struct au_sbinfo *sbinfo; -+ -+ sbinfo = file->private_data; -+ if (sbinfo) { -+ au_plink_maint_leave(sbinfo); -+ kobject_put(&sbinfo->si_kobj); -+ } -+ -+ return 0; -+} -+ -+static void au_procfs_plm_write_clean(struct file *file) -+{ -+ struct au_sbinfo *sbinfo; -+ -+ sbinfo = file->private_data; -+ if (sbinfo) -+ au_plink_clean(sbinfo->si_sb, /*verbose*/0); -+} -+ -+static int au_procfs_plm_write_si(struct file *file, unsigned long id) -+{ -+ int err; -+ struct super_block *sb; -+ struct au_sbinfo *sbinfo; -+ struct hlist_bl_node *pos; -+ -+ err = -EBUSY; -+ if (unlikely(file->private_data)) -+ goto out; -+ -+ sb = NULL; -+ /* don't use au_sbilist_lock() here */ -+ hlist_bl_lock(&au_sbilist); -+ hlist_bl_for_each_entry(sbinfo, pos, &au_sbilist, si_list) -+ if (id == sysaufs_si_id(sbinfo)) { -+ if (kobject_get_unless_zero(&sbinfo->si_kobj)) -+ sb = sbinfo->si_sb; -+ break; -+ } -+ hlist_bl_unlock(&au_sbilist); -+ -+ err = -EINVAL; -+ if (unlikely(!sb)) -+ goto out; -+ -+ err = au_plink_maint_enter(sb); -+ if (!err) -+ /* keep kobject_get() */ -+ file->private_data = sbinfo; -+ else -+ kobject_put(&sbinfo->si_kobj); -+out: -+ return err; -+} -+ -+/* -+ * Accept a valid "si=xxxx" only. -+ * Once it is accepted successfully, accept "clean" too. -+ */ -+static ssize_t au_procfs_plm_write(struct file *file, const char __user *ubuf, -+ size_t count, loff_t *ppos) -+{ -+ ssize_t err; -+ unsigned long id; -+ /* last newline is allowed */ -+ char buf[3 + sizeof(unsigned long) * 2 + 1]; -+ -+ err = -EACCES; -+ if (unlikely(!capable(CAP_SYS_ADMIN))) -+ goto out; -+ -+ err = -EINVAL; -+ if (unlikely(count > sizeof(buf))) -+ goto out; -+ -+ err = copy_from_user(buf, ubuf, count); -+ if (unlikely(err)) { -+ err = -EFAULT; -+ goto out; -+ } -+ buf[count] = 0; -+ -+ err = -EINVAL; -+ if (!strcmp("clean", buf)) { -+ au_procfs_plm_write_clean(file); -+ goto out_success; -+ } else if (unlikely(strncmp("si=", buf, 3))) -+ goto out; -+ -+ err = kstrtoul(buf + 3, 16, &id); -+ if (unlikely(err)) -+ goto out; -+ -+ err = au_procfs_plm_write_si(file, id); -+ if (unlikely(err)) -+ goto out; -+ -+out_success: -+ err = count; /* success */ -+out: -+ return err; -+} -+ -+static const struct file_operations au_procfs_plm_fop = { -+ .write = au_procfs_plm_write, -+ .release = au_procfs_plm_release, -+ .owner = THIS_MODULE -+}; -+ -+/* ---------------------------------------------------------------------- */ -+ -+static struct proc_dir_entry *au_procfs_dir; -+ -+void au_procfs_fin(void) -+{ -+ remove_proc_entry(AUFS_PLINK_MAINT_NAME, au_procfs_dir); -+ remove_proc_entry(AUFS_PLINK_MAINT_DIR, NULL); -+} -+ -+int __init au_procfs_init(void) -+{ -+ int err; -+ struct proc_dir_entry *entry; -+ -+ err = -ENOMEM; -+ au_procfs_dir = proc_mkdir(AUFS_PLINK_MAINT_DIR, NULL); -+ if (unlikely(!au_procfs_dir)) -+ goto out; -+ -+ entry = proc_create(AUFS_PLINK_MAINT_NAME, S_IFREG | 0200, -+ au_procfs_dir, &au_procfs_plm_fop); -+ if (unlikely(!entry)) -+ goto out_dir; -+ -+ err = 0; -+ goto out; /* success */ -+ -+ -+out_dir: -+ remove_proc_entry(AUFS_PLINK_MAINT_DIR, NULL); -+out: -+ return err; -+} -diff -Nurp linux-5.6.3/fs/aufs/rdu.c linux-5.6.3-aufs/fs/aufs/rdu.c ---- linux-5.6.3/fs/aufs/rdu.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/rdu.c 2020-04-10 12:40:52.192049502 +0300 -@@ -0,0 +1,371 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * readdir in userspace. -+ */ -+ -+#include -+#include -+#include -+#include "aufs.h" -+ -+/* bits for struct aufs_rdu.flags */ -+#define AuRdu_CALLED 1 -+#define AuRdu_CONT (1 << 1) -+#define AuRdu_FULL (1 << 2) -+#define au_ftest_rdu(flags, name) ((flags) & AuRdu_##name) -+#define au_fset_rdu(flags, name) \ -+ do { (flags) |= AuRdu_##name; } while (0) -+#define au_fclr_rdu(flags, name) \ -+ do { (flags) &= ~AuRdu_##name; } while (0) -+ -+struct au_rdu_arg { -+ struct dir_context ctx; -+ struct aufs_rdu *rdu; -+ union au_rdu_ent_ul ent; -+ unsigned long end; -+ -+ struct super_block *sb; -+ int err; -+}; -+ -+static int au_rdu_fill(struct dir_context *ctx, const char *name, int nlen, -+ loff_t offset, u64 h_ino, unsigned int d_type) -+{ -+ int err, len; -+ struct au_rdu_arg *arg = container_of(ctx, struct au_rdu_arg, ctx); -+ struct aufs_rdu *rdu = arg->rdu; -+ struct au_rdu_ent ent; -+ -+ err = 0; -+ arg->err = 0; -+ au_fset_rdu(rdu->cookie.flags, CALLED); -+ len = au_rdu_len(nlen); -+ if (arg->ent.ul + len < arg->end) { -+ ent.ino = h_ino; -+ ent.bindex = rdu->cookie.bindex; -+ ent.type = d_type; -+ ent.nlen = nlen; -+ if (unlikely(nlen > AUFS_MAX_NAMELEN)) -+ ent.type = DT_UNKNOWN; -+ -+ /* unnecessary to support mmap_sem since this is a dir */ -+ err = -EFAULT; -+ if (copy_to_user(arg->ent.e, &ent, sizeof(ent))) -+ goto out; -+ if (copy_to_user(arg->ent.e->name, name, nlen)) -+ goto out; -+ /* the terminating NULL */ -+ if (__put_user(0, arg->ent.e->name + nlen)) -+ goto out; -+ err = 0; -+ /* AuDbg("%p, %.*s\n", arg->ent.p, nlen, name); */ -+ arg->ent.ul += len; -+ rdu->rent++; -+ } else { -+ err = -EFAULT; -+ au_fset_rdu(rdu->cookie.flags, FULL); -+ rdu->full = 1; -+ rdu->tail = arg->ent; -+ } -+ -+out: -+ /* AuTraceErr(err); */ -+ return err; -+} -+ -+static int au_rdu_do(struct file *h_file, struct au_rdu_arg *arg) -+{ -+ int err; -+ loff_t offset; -+ struct au_rdu_cookie *cookie = &arg->rdu->cookie; -+ -+ /* we don't have to care (FMODE_32BITHASH | FMODE_64BITHASH) for ext4 */ -+ offset = vfsub_llseek(h_file, cookie->h_pos, SEEK_SET); -+ err = offset; -+ if (unlikely(offset != cookie->h_pos)) -+ goto out; -+ -+ err = 0; -+ do { -+ arg->err = 0; -+ au_fclr_rdu(cookie->flags, CALLED); -+ /* smp_mb(); */ -+ err = vfsub_iterate_dir(h_file, &arg->ctx); -+ if (err >= 0) -+ err = arg->err; -+ } while (!err -+ && au_ftest_rdu(cookie->flags, CALLED) -+ && !au_ftest_rdu(cookie->flags, FULL)); -+ cookie->h_pos = h_file->f_pos; -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+static int au_rdu(struct file *file, struct aufs_rdu *rdu) -+{ -+ int err; -+ aufs_bindex_t bbot; -+ struct au_rdu_arg arg = { -+ .ctx = { -+ .actor = au_rdu_fill -+ } -+ }; -+ struct dentry *dentry; -+ struct inode *inode; -+ struct file *h_file; -+ struct au_rdu_cookie *cookie = &rdu->cookie; -+ -+ /* VERIFY_WRITE */ -+ err = !access_ok(rdu->ent.e, rdu->sz); -+ if (unlikely(err)) { -+ err = -EFAULT; -+ AuTraceErr(err); -+ goto out; -+ } -+ rdu->rent = 0; -+ rdu->tail = rdu->ent; -+ rdu->full = 0; -+ arg.rdu = rdu; -+ arg.ent = rdu->ent; -+ arg.end = arg.ent.ul; -+ arg.end += rdu->sz; -+ -+ err = -ENOTDIR; -+ if (unlikely(!file->f_op->iterate && !file->f_op->iterate_shared)) -+ goto out; -+ -+ err = security_file_permission(file, MAY_READ); -+ AuTraceErr(err); -+ if (unlikely(err)) -+ goto out; -+ -+ dentry = file->f_path.dentry; -+ inode = d_inode(dentry); -+ inode_lock_shared(inode); -+ -+ arg.sb = inode->i_sb; -+ err = si_read_lock(arg.sb, AuLock_FLUSH | AuLock_NOPLM); -+ if (unlikely(err)) -+ goto out_mtx; -+ err = au_alive_dir(dentry); -+ if (unlikely(err)) -+ goto out_si; -+ /* todo: reval? */ -+ fi_read_lock(file); -+ -+ err = -EAGAIN; -+ if (unlikely(au_ftest_rdu(cookie->flags, CONT) -+ && cookie->generation != au_figen(file))) -+ goto out_unlock; -+ -+ err = 0; -+ if (!rdu->blk) { -+ rdu->blk = au_sbi(arg.sb)->si_rdblk; -+ if (!rdu->blk) -+ rdu->blk = au_dir_size(file, /*dentry*/NULL); -+ } -+ bbot = au_fbtop(file); -+ if (cookie->bindex < bbot) -+ cookie->bindex = bbot; -+ bbot = au_fbbot_dir(file); -+ /* AuDbg("b%d, b%d\n", cookie->bindex, bbot); */ -+ for (; !err && cookie->bindex <= bbot; -+ cookie->bindex++, cookie->h_pos = 0) { -+ h_file = au_hf_dir(file, cookie->bindex); -+ if (!h_file) -+ continue; -+ -+ au_fclr_rdu(cookie->flags, FULL); -+ err = au_rdu_do(h_file, &arg); -+ AuTraceErr(err); -+ if (unlikely(au_ftest_rdu(cookie->flags, FULL) || err)) -+ break; -+ } -+ AuDbg("rent %llu\n", rdu->rent); -+ -+ if (!err && !au_ftest_rdu(cookie->flags, CONT)) { -+ rdu->shwh = !!au_opt_test(au_sbi(arg.sb)->si_mntflags, SHWH); -+ au_fset_rdu(cookie->flags, CONT); -+ cookie->generation = au_figen(file); -+ } -+ -+ ii_read_lock_child(inode); -+ fsstack_copy_attr_atime(inode, au_h_iptr(inode, au_ibtop(inode))); -+ ii_read_unlock(inode); -+ -+out_unlock: -+ fi_read_unlock(file); -+out_si: -+ si_read_unlock(arg.sb); -+out_mtx: -+ inode_unlock_shared(inode); -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+static int au_rdu_ino(struct file *file, struct aufs_rdu *rdu) -+{ -+ int err; -+ ino_t ino; -+ unsigned long long nent; -+ union au_rdu_ent_ul *u; -+ struct au_rdu_ent ent; -+ struct super_block *sb; -+ -+ err = 0; -+ nent = rdu->nent; -+ u = &rdu->ent; -+ sb = file->f_path.dentry->d_sb; -+ si_read_lock(sb, AuLock_FLUSH); -+ while (nent-- > 0) { -+ /* unnecessary to support mmap_sem since this is a dir */ -+ err = copy_from_user(&ent, u->e, sizeof(ent)); -+ if (!err) -+ /* VERIFY_WRITE */ -+ err = !access_ok(&u->e->ino, sizeof(ino)); -+ if (unlikely(err)) { -+ err = -EFAULT; -+ AuTraceErr(err); -+ break; -+ } -+ -+ /* AuDbg("b%d, i%llu\n", ent.bindex, ent.ino); */ -+ if (!ent.wh) -+ err = au_ino(sb, ent.bindex, ent.ino, ent.type, &ino); -+ else -+ err = au_wh_ino(sb, ent.bindex, ent.ino, ent.type, -+ &ino); -+ if (unlikely(err)) { -+ AuTraceErr(err); -+ break; -+ } -+ -+ err = __put_user(ino, &u->e->ino); -+ if (unlikely(err)) { -+ err = -EFAULT; -+ AuTraceErr(err); -+ break; -+ } -+ u->ul += au_rdu_len(ent.nlen); -+ } -+ si_read_unlock(sb); -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int au_rdu_verify(struct aufs_rdu *rdu) -+{ -+ AuDbg("rdu{%llu, %p, %u | %u | %llu, %u, %u | " -+ "%llu, b%d, 0x%x, g%u}\n", -+ rdu->sz, rdu->ent.e, rdu->verify[AufsCtlRduV_SZ], -+ rdu->blk, -+ rdu->rent, rdu->shwh, rdu->full, -+ rdu->cookie.h_pos, rdu->cookie.bindex, rdu->cookie.flags, -+ rdu->cookie.generation); -+ -+ if (rdu->verify[AufsCtlRduV_SZ] == sizeof(*rdu)) -+ return 0; -+ -+ AuDbg("%u:%u\n", -+ rdu->verify[AufsCtlRduV_SZ], (unsigned int)sizeof(*rdu)); -+ return -EINVAL; -+} -+ -+long au_rdu_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -+{ -+ long err, e; -+ struct aufs_rdu rdu; -+ void __user *p = (void __user *)arg; -+ -+ err = copy_from_user(&rdu, p, sizeof(rdu)); -+ if (unlikely(err)) { -+ err = -EFAULT; -+ AuTraceErr(err); -+ goto out; -+ } -+ err = au_rdu_verify(&rdu); -+ if (unlikely(err)) -+ goto out; -+ -+ switch (cmd) { -+ case AUFS_CTL_RDU: -+ err = au_rdu(file, &rdu); -+ if (unlikely(err)) -+ break; -+ -+ e = copy_to_user(p, &rdu, sizeof(rdu)); -+ if (unlikely(e)) { -+ err = -EFAULT; -+ AuTraceErr(err); -+ } -+ break; -+ case AUFS_CTL_RDU_INO: -+ err = au_rdu_ino(file, &rdu); -+ break; -+ -+ default: -+ /* err = -ENOTTY; */ -+ err = -EINVAL; -+ } -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+#ifdef CONFIG_COMPAT -+long au_rdu_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -+{ -+ long err, e; -+ struct aufs_rdu rdu; -+ void __user *p = compat_ptr(arg); -+ -+ /* todo: get_user()? */ -+ err = copy_from_user(&rdu, p, sizeof(rdu)); -+ if (unlikely(err)) { -+ err = -EFAULT; -+ AuTraceErr(err); -+ goto out; -+ } -+ rdu.ent.e = compat_ptr(rdu.ent.ul); -+ err = au_rdu_verify(&rdu); -+ if (unlikely(err)) -+ goto out; -+ -+ switch (cmd) { -+ case AUFS_CTL_RDU: -+ err = au_rdu(file, &rdu); -+ if (unlikely(err)) -+ break; -+ -+ rdu.ent.ul = ptr_to_compat(rdu.ent.e); -+ rdu.tail.ul = ptr_to_compat(rdu.tail.e); -+ e = copy_to_user(p, &rdu, sizeof(rdu)); -+ if (unlikely(e)) { -+ err = -EFAULT; -+ AuTraceErr(err); -+ } -+ break; -+ case AUFS_CTL_RDU_INO: -+ err = au_rdu_ino(file, &rdu); -+ break; -+ -+ default: -+ /* err = -ENOTTY; */ -+ err = -EINVAL; -+ } -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+#endif -diff -Nurp linux-5.6.3/fs/aufs/rwsem.h linux-5.6.3-aufs/fs/aufs/rwsem.h ---- linux-5.6.3/fs/aufs/rwsem.h 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/rwsem.h 2020-04-10 12:40:52.192049502 +0300 -@@ -0,0 +1,60 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * simple read-write semaphore wrappers -+ */ -+ -+#ifndef __AUFS_RWSEM_H__ -+#define __AUFS_RWSEM_H__ -+ -+#ifdef __KERNEL__ -+ -+#include "debug.h" -+ -+/* in the future, the name 'au_rwsem' will be totally gone */ -+#define au_rwsem rw_semaphore -+ -+/* to debug easier, do not make them inlined functions */ -+#define AuRwMustNoWaiters(rw) AuDebugOn(rwsem_is_contended(rw)) -+/* rwsem_is_locked() is unusable */ -+#define AuRwMustReadLock(rw) AuDebugOn(!lockdep_recursing(current) \ -+ && debug_locks \ -+ && !lockdep_is_held_type(rw, 1)) -+#define AuRwMustWriteLock(rw) AuDebugOn(!lockdep_recursing(current) \ -+ && debug_locks \ -+ && !lockdep_is_held_type(rw, 0)) -+#define AuRwMustAnyLock(rw) AuDebugOn(!lockdep_recursing(current) \ -+ && debug_locks \ -+ && !lockdep_is_held(rw)) -+#define AuRwDestroy(rw) AuDebugOn(!lockdep_recursing(current) \ -+ && debug_locks \ -+ && lockdep_is_held(rw)) -+ -+#define au_rw_init(rw) init_rwsem(rw) -+ -+#define au_rw_init_wlock(rw) do { \ -+ au_rw_init(rw); \ -+ down_write(rw); \ -+ } while (0) -+ -+#define au_rw_init_wlock_nested(rw, lsc) do { \ -+ au_rw_init(rw); \ -+ down_write_nested(rw, lsc); \ -+ } while (0) -+ -+#define au_rw_read_lock(rw) down_read(rw) -+#define au_rw_read_lock_nested(rw, lsc) down_read_nested(rw, lsc) -+#define au_rw_read_unlock(rw) up_read(rw) -+#define au_rw_dgrade_lock(rw) downgrade_write(rw) -+#define au_rw_write_lock(rw) down_write(rw) -+#define au_rw_write_lock_nested(rw, lsc) down_write_nested(rw, lsc) -+#define au_rw_write_unlock(rw) up_write(rw) -+/* why is not _nested version defined? */ -+#define au_rw_read_trylock(rw) down_read_trylock(rw) -+#define au_rw_write_trylock(rw) down_write_trylock(rw) -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_RWSEM_H__ */ -diff -Nurp linux-5.6.3/fs/aufs/sbinfo.c linux-5.6.3-aufs/fs/aufs/sbinfo.c ---- linux-5.6.3/fs/aufs/sbinfo.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/sbinfo.c 2020-04-10 12:40:52.192049502 +0300 -@@ -0,0 +1,301 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * superblock private data -+ */ -+ -+#include -+#include "aufs.h" -+ -+/* -+ * they are necessary regardless sysfs is disabled. -+ */ -+void au_si_free(struct kobject *kobj) -+{ -+ int i; -+ struct au_sbinfo *sbinfo; -+ char *locked __maybe_unused; /* debug only */ -+ -+ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj); -+ for (i = 0; i < AuPlink_NHASH; i++) -+ AuDebugOn(!hlist_bl_empty(sbinfo->si_plink + i)); -+ AuDebugOn(atomic_read(&sbinfo->si_nowait.nw_len)); -+ -+ AuLCntZero(au_lcnt_read(&sbinfo->si_ninodes, /*do_rev*/0)); -+ au_lcnt_fin(&sbinfo->si_ninodes, /*do_sync*/0); -+ AuLCntZero(au_lcnt_read(&sbinfo->si_nfiles, /*do_rev*/0)); -+ au_lcnt_fin(&sbinfo->si_nfiles, /*do_sync*/0); -+ -+ dbgaufs_si_fin(sbinfo); -+ au_rw_write_lock(&sbinfo->si_rwsem); -+ au_br_free(sbinfo); -+ au_rw_write_unlock(&sbinfo->si_rwsem); -+ -+ au_kfree_try_rcu(sbinfo->si_branch); -+ mutex_destroy(&sbinfo->si_xib_mtx); -+ AuRwDestroy(&sbinfo->si_rwsem); -+ -+ au_lcnt_wait_for_fin(&sbinfo->si_ninodes); -+ /* si_nfiles is waited too */ -+ au_kfree_rcu(sbinfo); -+} -+ -+int au_si_alloc(struct super_block *sb) -+{ -+ int err, i; -+ struct au_sbinfo *sbinfo; -+ -+ err = -ENOMEM; -+ sbinfo = kzalloc(sizeof(*sbinfo), GFP_NOFS); -+ if (unlikely(!sbinfo)) -+ goto out; -+ -+ /* will be reallocated separately */ -+ sbinfo->si_branch = kzalloc(sizeof(*sbinfo->si_branch), GFP_NOFS); -+ if (unlikely(!sbinfo->si_branch)) -+ goto out_sbinfo; -+ -+ err = sysaufs_si_init(sbinfo); -+ if (!err) { -+ dbgaufs_si_null(sbinfo); -+ err = dbgaufs_si_init(sbinfo); -+ if (unlikely(err)) -+ kobject_put(&sbinfo->si_kobj); -+ } -+ if (unlikely(err)) -+ goto out_br; -+ -+ au_nwt_init(&sbinfo->si_nowait); -+ au_rw_init_wlock(&sbinfo->si_rwsem); -+ -+ au_lcnt_init(&sbinfo->si_ninodes, /*release*/NULL); -+ au_lcnt_init(&sbinfo->si_nfiles, /*release*/NULL); -+ -+ sbinfo->si_bbot = -1; -+ sbinfo->si_last_br_id = AUFS_BRANCH_MAX / 2; -+ -+ sbinfo->si_wbr_copyup = AuWbrCopyup_Def; -+ sbinfo->si_wbr_create = AuWbrCreate_Def; -+ sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + sbinfo->si_wbr_copyup; -+ sbinfo->si_wbr_create_ops = au_wbr_create_ops + sbinfo->si_wbr_create; -+ -+ au_fhsm_init(sbinfo); -+ -+ sbinfo->si_mntflags = au_opts_plink(AuOpt_Def); -+ -+ sbinfo->si_xino_jiffy = jiffies; -+ sbinfo->si_xino_expire -+ = msecs_to_jiffies(AUFS_XINO_DEF_SEC * MSEC_PER_SEC); -+ mutex_init(&sbinfo->si_xib_mtx); -+ /* leave si_xib_last_pindex and si_xib_next_bit */ -+ -+ INIT_HLIST_BL_HEAD(&sbinfo->si_aopen); -+ -+ sbinfo->si_rdcache = msecs_to_jiffies(AUFS_RDCACHE_DEF * MSEC_PER_SEC); -+ sbinfo->si_rdblk = AUFS_RDBLK_DEF; -+ sbinfo->si_rdhash = AUFS_RDHASH_DEF; -+ sbinfo->si_dirwh = AUFS_DIRWH_DEF; -+ -+ for (i = 0; i < AuPlink_NHASH; i++) -+ INIT_HLIST_BL_HEAD(sbinfo->si_plink + i); -+ init_waitqueue_head(&sbinfo->si_plink_wq); -+ spin_lock_init(&sbinfo->si_plink_maint_lock); -+ -+ INIT_HLIST_BL_HEAD(&sbinfo->si_files); -+ -+ /* with getattr by default */ -+ sbinfo->si_iop_array = aufs_iop; -+ -+ /* leave other members for sysaufs and si_mnt. */ -+ sbinfo->si_sb = sb; -+ sb->s_fs_info = sbinfo; -+ si_pid_set(sb); -+ return 0; /* success */ -+ -+out_br: -+ au_kfree_try_rcu(sbinfo->si_branch); -+out_sbinfo: -+ au_kfree_rcu(sbinfo); -+out: -+ return err; -+} -+ -+int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr, int may_shrink) -+{ -+ int err, sz; -+ struct au_branch **brp; -+ -+ AuRwMustWriteLock(&sbinfo->si_rwsem); -+ -+ err = -ENOMEM; -+ sz = sizeof(*brp) * (sbinfo->si_bbot + 1); -+ if (unlikely(!sz)) -+ sz = sizeof(*brp); -+ brp = au_kzrealloc(sbinfo->si_branch, sz, sizeof(*brp) * nbr, GFP_NOFS, -+ may_shrink); -+ if (brp) { -+ sbinfo->si_branch = brp; -+ err = 0; -+ } -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+unsigned int au_sigen_inc(struct super_block *sb) -+{ -+ unsigned int gen; -+ struct inode *inode; -+ -+ SiMustWriteLock(sb); -+ -+ gen = ++au_sbi(sb)->si_generation; -+ au_update_digen(sb->s_root); -+ inode = d_inode(sb->s_root); -+ au_update_iigen(inode, /*half*/0); -+ inode_inc_iversion(inode); -+ return gen; -+} -+ -+aufs_bindex_t au_new_br_id(struct super_block *sb) -+{ -+ aufs_bindex_t br_id; -+ int i; -+ struct au_sbinfo *sbinfo; -+ -+ SiMustWriteLock(sb); -+ -+ sbinfo = au_sbi(sb); -+ for (i = 0; i <= AUFS_BRANCH_MAX; i++) { -+ br_id = ++sbinfo->si_last_br_id; -+ AuDebugOn(br_id < 0); -+ if (br_id && au_br_index(sb, br_id) < 0) -+ return br_id; -+ } -+ -+ return -1; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* it is ok that new 'nwt' tasks are appended while we are sleeping */ -+int si_read_lock(struct super_block *sb, int flags) -+{ -+ int err; -+ -+ err = 0; -+ if (au_ftest_lock(flags, FLUSH)) -+ au_nwt_flush(&au_sbi(sb)->si_nowait); -+ -+ si_noflush_read_lock(sb); -+ err = au_plink_maint(sb, flags); -+ if (unlikely(err)) -+ si_read_unlock(sb); -+ -+ return err; -+} -+ -+int si_write_lock(struct super_block *sb, int flags) -+{ -+ int err; -+ -+ if (au_ftest_lock(flags, FLUSH)) -+ au_nwt_flush(&au_sbi(sb)->si_nowait); -+ -+ si_noflush_write_lock(sb); -+ err = au_plink_maint(sb, flags); -+ if (unlikely(err)) -+ si_write_unlock(sb); -+ -+ return err; -+} -+ -+/* dentry and super_block lock. call at entry point */ -+int aufs_read_lock(struct dentry *dentry, int flags) -+{ -+ int err; -+ struct super_block *sb; -+ -+ sb = dentry->d_sb; -+ err = si_read_lock(sb, flags); -+ if (unlikely(err)) -+ goto out; -+ -+ if (au_ftest_lock(flags, DW)) -+ di_write_lock_child(dentry); -+ else -+ di_read_lock_child(dentry, flags); -+ -+ if (au_ftest_lock(flags, GEN)) { -+ err = au_digen_test(dentry, au_sigen(sb)); -+ if (!au_opt_test(au_mntflags(sb), UDBA_NONE)) -+ AuDebugOn(!err && au_dbrange_test(dentry)); -+ else if (!err) -+ err = au_dbrange_test(dentry); -+ if (unlikely(err)) -+ aufs_read_unlock(dentry, flags); -+ } -+ -+out: -+ return err; -+} -+ -+void aufs_read_unlock(struct dentry *dentry, int flags) -+{ -+ if (au_ftest_lock(flags, DW)) -+ di_write_unlock(dentry); -+ else -+ di_read_unlock(dentry, flags); -+ si_read_unlock(dentry->d_sb); -+} -+ -+void aufs_write_lock(struct dentry *dentry) -+{ -+ si_write_lock(dentry->d_sb, AuLock_FLUSH | AuLock_NOPLMW); -+ di_write_lock_child(dentry); -+} -+ -+void aufs_write_unlock(struct dentry *dentry) -+{ -+ di_write_unlock(dentry); -+ si_write_unlock(dentry->d_sb); -+} -+ -+int aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags) -+{ -+ int err; -+ unsigned int sigen; -+ struct super_block *sb; -+ -+ sb = d1->d_sb; -+ err = si_read_lock(sb, flags); -+ if (unlikely(err)) -+ goto out; -+ -+ di_write_lock2_child(d1, d2, au_ftest_lock(flags, DIRS)); -+ -+ if (au_ftest_lock(flags, GEN)) { -+ sigen = au_sigen(sb); -+ err = au_digen_test(d1, sigen); -+ AuDebugOn(!err && au_dbrange_test(d1)); -+ if (!err) { -+ err = au_digen_test(d2, sigen); -+ AuDebugOn(!err && au_dbrange_test(d2)); -+ } -+ if (unlikely(err)) -+ aufs_read_and_write_unlock2(d1, d2); -+ } -+ -+out: -+ return err; -+} -+ -+void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2) -+{ -+ di_write_unlock2(d1, d2); -+ si_read_unlock(d1->d_sb); -+} -diff -Nurp linux-5.6.3/fs/aufs/super.c linux-5.6.3-aufs/fs/aufs/super.c ---- linux-5.6.3/fs/aufs/super.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/super.c 2020-04-10 12:40:52.192049502 +0300 -@@ -0,0 +1,1034 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * mount and super_block operations -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include "aufs.h" -+ -+/* -+ * super_operations -+ */ -+static struct inode *aufs_alloc_inode(struct super_block *sb __maybe_unused) -+{ -+ struct au_icntnr *c; -+ -+ c = au_cache_alloc_icntnr(); -+ if (c) { -+ au_icntnr_init(c); -+ inode_set_iversion(&c->vfs_inode, 1); /* sigen(sb); */ -+ c->iinfo.ii_hinode = NULL; -+ return &c->vfs_inode; -+ } -+ return NULL; -+} -+ -+static void aufs_destroy_inode(struct inode *inode) -+{ -+ if (!au_is_bad_inode(inode)) -+ au_iinfo_fin(inode); -+} -+ -+static void aufs_free_inode(struct inode *inode) -+{ -+ au_cache_free_icntnr(container_of(inode, struct au_icntnr, vfs_inode)); -+} -+ -+struct inode *au_iget_locked(struct super_block *sb, ino_t ino) -+{ -+ struct inode *inode; -+ int err; -+ -+ inode = iget_locked(sb, ino); -+ if (unlikely(!inode)) { -+ inode = ERR_PTR(-ENOMEM); -+ goto out; -+ } -+ if (!(inode->i_state & I_NEW)) -+ goto out; -+ -+ err = au_xigen_new(inode); -+ if (!err) -+ err = au_iinfo_init(inode); -+ if (!err) -+ inode_inc_iversion(inode); -+ else { -+ iget_failed(inode); -+ inode = ERR_PTR(err); -+ } -+ -+out: -+ /* never return NULL */ -+ AuDebugOn(!inode); -+ AuTraceErrPtr(inode); -+ return inode; -+} -+ -+/* lock free root dinfo */ -+static int au_show_brs(struct seq_file *seq, struct super_block *sb) -+{ -+ int err; -+ aufs_bindex_t bindex, bbot; -+ struct path path; -+ struct au_hdentry *hdp; -+ struct au_branch *br; -+ au_br_perm_str_t perm; -+ -+ err = 0; -+ bbot = au_sbbot(sb); -+ bindex = 0; -+ hdp = au_hdentry(au_di(sb->s_root), bindex); -+ for (; !err && bindex <= bbot; bindex++, hdp++) { -+ br = au_sbr(sb, bindex); -+ path.mnt = au_br_mnt(br); -+ path.dentry = hdp->hd_dentry; -+ err = au_seq_path(seq, &path); -+ if (!err) { -+ au_optstr_br_perm(&perm, br->br_perm); -+ seq_printf(seq, "=%s", perm.a); -+ if (bindex != bbot) -+ seq_putc(seq, ':'); -+ } -+ } -+ if (unlikely(err || seq_has_overflowed(seq))) -+ err = -E2BIG; -+ -+ return err; -+} -+ -+static void au_gen_fmt(char *fmt, int len __maybe_unused, const char *pat, -+ const char *append) -+{ -+ char *p; -+ -+ p = fmt; -+ while (*pat != ':') -+ *p++ = *pat++; -+ *p++ = *pat++; -+ strcpy(p, append); -+ AuDebugOn(strlen(fmt) >= len); -+} -+ -+static void au_show_wbr_create(struct seq_file *m, int v, -+ struct au_sbinfo *sbinfo) -+{ -+ const char *pat; -+ char fmt[32]; -+ struct au_wbr_mfs *mfs; -+ -+ AuRwMustAnyLock(&sbinfo->si_rwsem); -+ -+ seq_puts(m, ",create="); -+ pat = au_optstr_wbr_create(v); -+ mfs = &sbinfo->si_wbr_mfs; -+ switch (v) { -+ case AuWbrCreate_TDP: -+ case AuWbrCreate_RR: -+ case AuWbrCreate_MFS: -+ case AuWbrCreate_PMFS: -+ seq_puts(m, pat); -+ break; -+ case AuWbrCreate_MFSRR: -+ case AuWbrCreate_TDMFS: -+ case AuWbrCreate_PMFSRR: -+ au_gen_fmt(fmt, sizeof(fmt), pat, "%llu"); -+ seq_printf(m, fmt, mfs->mfsrr_watermark); -+ break; -+ case AuWbrCreate_MFSV: -+ case AuWbrCreate_PMFSV: -+ au_gen_fmt(fmt, sizeof(fmt), pat, "%lu"); -+ seq_printf(m, fmt, -+ jiffies_to_msecs(mfs->mfs_expire) -+ / MSEC_PER_SEC); -+ break; -+ case AuWbrCreate_MFSRRV: -+ case AuWbrCreate_TDMFSV: -+ case AuWbrCreate_PMFSRRV: -+ au_gen_fmt(fmt, sizeof(fmt), pat, "%llu:%lu"); -+ seq_printf(m, fmt, mfs->mfsrr_watermark, -+ jiffies_to_msecs(mfs->mfs_expire) / MSEC_PER_SEC); -+ break; -+ default: -+ BUG(); -+ } -+} -+ -+static int au_show_xino(struct seq_file *seq, struct super_block *sb) -+{ -+#ifdef CONFIG_SYSFS -+ return 0; -+#else -+ int err; -+ const int len = sizeof(AUFS_XINO_FNAME) - 1; -+ aufs_bindex_t bindex, brid; -+ struct qstr *name; -+ struct file *f; -+ struct dentry *d, *h_root; -+ struct au_branch *br; -+ -+ AuRwMustAnyLock(&sbinfo->si_rwsem); -+ -+ err = 0; -+ f = au_sbi(sb)->si_xib; -+ if (!f) -+ goto out; -+ -+ /* stop printing the default xino path on the first writable branch */ -+ h_root = NULL; -+ bindex = au_xi_root(sb, f->f_path.dentry); -+ if (bindex >= 0) { -+ br = au_sbr_sb(sb, bindex); -+ h_root = au_br_dentry(br); -+ } -+ -+ d = f->f_path.dentry; -+ name = &d->d_name; -+ /* safe ->d_parent because the file is unlinked */ -+ if (d->d_parent == h_root -+ && name->len == len -+ && !memcmp(name->name, AUFS_XINO_FNAME, len)) -+ goto out; -+ -+ seq_puts(seq, ",xino="); -+ err = au_xino_path(seq, f); -+ -+out: -+ return err; -+#endif -+} -+ -+/* seq_file will re-call me in case of too long string */ -+static int aufs_show_options(struct seq_file *m, struct dentry *dentry) -+{ -+ int err; -+ unsigned int mnt_flags, v; -+ struct super_block *sb; -+ struct au_sbinfo *sbinfo; -+ -+#define AuBool(name, str) do { \ -+ v = au_opt_test(mnt_flags, name); \ -+ if (v != au_opt_test(AuOpt_Def, name)) \ -+ seq_printf(m, ",%s" #str, v ? "" : "no"); \ -+} while (0) -+ -+#define AuStr(name, str) do { \ -+ v = mnt_flags & AuOptMask_##name; \ -+ if (v != (AuOpt_Def & AuOptMask_##name)) \ -+ seq_printf(m, "," #str "=%s", au_optstr_##str(v)); \ -+} while (0) -+ -+#define AuUInt(name, str, val) do { \ -+ if (val != AUFS_##name##_DEF) \ -+ seq_printf(m, "," #str "=%u", val); \ -+} while (0) -+ -+ sb = dentry->d_sb; -+ if (sb->s_flags & SB_POSIXACL) -+ seq_puts(m, ",acl"); -+#if 0 /* reserved for future use */ -+ if (sb->s_flags & SB_I_VERSION) -+ seq_puts(m, ",i_version"); -+#endif -+ -+ /* lock free root dinfo */ -+ si_noflush_read_lock(sb); -+ sbinfo = au_sbi(sb); -+ seq_printf(m, ",si=%lx", sysaufs_si_id(sbinfo)); -+ -+ mnt_flags = au_mntflags(sb); -+ if (au_opt_test(mnt_flags, XINO)) { -+ err = au_show_xino(m, sb); -+ if (unlikely(err)) -+ goto out; -+ } else -+ seq_puts(m, ",noxino"); -+ -+ AuBool(TRUNC_XINO, trunc_xino); -+ AuStr(UDBA, udba); -+ AuBool(SHWH, shwh); -+ AuBool(PLINK, plink); -+ AuBool(DIO, dio); -+ AuBool(DIRPERM1, dirperm1); -+ -+ v = sbinfo->si_wbr_create; -+ if (v != AuWbrCreate_Def) -+ au_show_wbr_create(m, v, sbinfo); -+ -+ v = sbinfo->si_wbr_copyup; -+ if (v != AuWbrCopyup_Def) -+ seq_printf(m, ",cpup=%s", au_optstr_wbr_copyup(v)); -+ -+ v = au_opt_test(mnt_flags, ALWAYS_DIROPQ); -+ if (v != au_opt_test(AuOpt_Def, ALWAYS_DIROPQ)) -+ seq_printf(m, ",diropq=%c", v ? 'a' : 'w'); -+ -+ AuUInt(DIRWH, dirwh, sbinfo->si_dirwh); -+ -+ v = jiffies_to_msecs(sbinfo->si_rdcache) / MSEC_PER_SEC; -+ AuUInt(RDCACHE, rdcache, v); -+ -+ AuUInt(RDBLK, rdblk, sbinfo->si_rdblk); -+ AuUInt(RDHASH, rdhash, sbinfo->si_rdhash); -+ -+ au_fhsm_show(m, sbinfo); -+ -+ AuBool(DIRREN, dirren); -+ AuBool(SUM, sum); -+ /* AuBool(SUM_W, wsum); */ -+ AuBool(WARN_PERM, warn_perm); -+ AuBool(VERBOSE, verbose); -+ -+out: -+ /* be sure to print "br:" last */ -+ if (!sysaufs_brs) { -+ seq_puts(m, ",br:"); -+ au_show_brs(m, sb); -+ } -+ si_read_unlock(sb); -+ return 0; -+ -+#undef AuBool -+#undef AuStr -+#undef AuUInt -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* sum mode which returns the summation for statfs(2) */ -+ -+static u64 au_add_till_max(u64 a, u64 b) -+{ -+ u64 old; -+ -+ old = a; -+ a += b; -+ if (old <= a) -+ return a; -+ return ULLONG_MAX; -+} -+ -+static u64 au_mul_till_max(u64 a, long mul) -+{ -+ u64 old; -+ -+ old = a; -+ a *= mul; -+ if (old <= a) -+ return a; -+ return ULLONG_MAX; -+} -+ -+static int au_statfs_sum(struct super_block *sb, struct kstatfs *buf) -+{ -+ int err; -+ long bsize, factor; -+ u64 blocks, bfree, bavail, files, ffree; -+ aufs_bindex_t bbot, bindex, i; -+ unsigned char shared; -+ struct path h_path; -+ struct super_block *h_sb; -+ -+ err = 0; -+ bsize = LONG_MAX; -+ files = 0; -+ ffree = 0; -+ blocks = 0; -+ bfree = 0; -+ bavail = 0; -+ bbot = au_sbbot(sb); -+ for (bindex = 0; bindex <= bbot; bindex++) { -+ h_path.mnt = au_sbr_mnt(sb, bindex); -+ h_sb = h_path.mnt->mnt_sb; -+ shared = 0; -+ for (i = 0; !shared && i < bindex; i++) -+ shared = (au_sbr_sb(sb, i) == h_sb); -+ if (shared) -+ continue; -+ -+ /* sb->s_root for NFS is unreliable */ -+ h_path.dentry = h_path.mnt->mnt_root; -+ err = vfs_statfs(&h_path, buf); -+ if (unlikely(err)) -+ goto out; -+ -+ if (bsize > buf->f_bsize) { -+ /* -+ * we will reduce bsize, so we have to expand blocks -+ * etc. to match them again -+ */ -+ factor = (bsize / buf->f_bsize); -+ blocks = au_mul_till_max(blocks, factor); -+ bfree = au_mul_till_max(bfree, factor); -+ bavail = au_mul_till_max(bavail, factor); -+ bsize = buf->f_bsize; -+ } -+ -+ factor = (buf->f_bsize / bsize); -+ blocks = au_add_till_max(blocks, -+ au_mul_till_max(buf->f_blocks, factor)); -+ bfree = au_add_till_max(bfree, -+ au_mul_till_max(buf->f_bfree, factor)); -+ bavail = au_add_till_max(bavail, -+ au_mul_till_max(buf->f_bavail, factor)); -+ files = au_add_till_max(files, buf->f_files); -+ ffree = au_add_till_max(ffree, buf->f_ffree); -+ } -+ -+ buf->f_bsize = bsize; -+ buf->f_blocks = blocks; -+ buf->f_bfree = bfree; -+ buf->f_bavail = bavail; -+ buf->f_files = files; -+ buf->f_ffree = ffree; -+ buf->f_frsize = 0; -+ -+out: -+ return err; -+} -+ -+static int aufs_statfs(struct dentry *dentry, struct kstatfs *buf) -+{ -+ int err; -+ struct path h_path; -+ struct super_block *sb; -+ -+ /* lock free root dinfo */ -+ sb = dentry->d_sb; -+ si_noflush_read_lock(sb); -+ if (!au_opt_test(au_mntflags(sb), SUM)) { -+ /* sb->s_root for NFS is unreliable */ -+ h_path.mnt = au_sbr_mnt(sb, 0); -+ h_path.dentry = h_path.mnt->mnt_root; -+ err = vfs_statfs(&h_path, buf); -+ } else -+ err = au_statfs_sum(sb, buf); -+ si_read_unlock(sb); -+ -+ if (!err) { -+ buf->f_type = AUFS_SUPER_MAGIC; -+ buf->f_namelen = AUFS_MAX_NAMELEN; -+ memset(&buf->f_fsid, 0, sizeof(buf->f_fsid)); -+ } -+ /* buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1; */ -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int aufs_sync_fs(struct super_block *sb, int wait) -+{ -+ int err, e; -+ aufs_bindex_t bbot, bindex; -+ struct au_branch *br; -+ struct super_block *h_sb; -+ -+ err = 0; -+ si_noflush_read_lock(sb); -+ bbot = au_sbbot(sb); -+ for (bindex = 0; bindex <= bbot; bindex++) { -+ br = au_sbr(sb, bindex); -+ if (!au_br_writable(br->br_perm)) -+ continue; -+ -+ h_sb = au_sbr_sb(sb, bindex); -+ e = vfsub_sync_filesystem(h_sb, wait); -+ if (unlikely(e && !err)) -+ err = e; -+ /* go on even if an error happens */ -+ } -+ si_read_unlock(sb); -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* final actions when unmounting a file system */ -+static void aufs_put_super(struct super_block *sb) -+{ -+ struct au_sbinfo *sbinfo; -+ -+ sbinfo = au_sbi(sb); -+ if (sbinfo) -+ kobject_put(&sbinfo->si_kobj); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+void *au_array_alloc(unsigned long long *hint, au_arraycb_t cb, -+ struct super_block *sb, void *arg) -+{ -+ void *array; -+ unsigned long long n, sz; -+ -+ array = NULL; -+ n = 0; -+ if (!*hint) -+ goto out; -+ -+ if (*hint > ULLONG_MAX / sizeof(array)) { -+ array = ERR_PTR(-EMFILE); -+ pr_err("hint %llu\n", *hint); -+ goto out; -+ } -+ -+ sz = sizeof(array) * *hint; -+ array = kzalloc(sz, GFP_NOFS); -+ if (unlikely(!array)) -+ array = vzalloc(sz); -+ if (unlikely(!array)) { -+ array = ERR_PTR(-ENOMEM); -+ goto out; -+ } -+ -+ n = cb(sb, array, *hint, arg); -+ AuDebugOn(n > *hint); -+ -+out: -+ *hint = n; -+ return array; -+} -+ -+static unsigned long long au_iarray_cb(struct super_block *sb, void *a, -+ unsigned long long max __maybe_unused, -+ void *arg) -+{ -+ unsigned long long n; -+ struct inode **p, *inode; -+ struct list_head *head; -+ -+ n = 0; -+ p = a; -+ head = arg; -+ spin_lock(&sb->s_inode_list_lock); -+ list_for_each_entry(inode, head, i_sb_list) { -+ if (!au_is_bad_inode(inode) -+ && au_ii(inode)->ii_btop >= 0) { -+ spin_lock(&inode->i_lock); -+ if (atomic_read(&inode->i_count)) { -+ au_igrab(inode); -+ *p++ = inode; -+ n++; -+ AuDebugOn(n > max); -+ } -+ spin_unlock(&inode->i_lock); -+ } -+ } -+ spin_unlock(&sb->s_inode_list_lock); -+ -+ return n; -+} -+ -+struct inode **au_iarray_alloc(struct super_block *sb, unsigned long long *max) -+{ -+ struct au_sbinfo *sbi; -+ -+ sbi = au_sbi(sb); -+ *max = au_lcnt_read(&sbi->si_ninodes, /*do_rev*/1); -+ return au_array_alloc(max, au_iarray_cb, sb, &sb->s_inodes); -+} -+ -+void au_iarray_free(struct inode **a, unsigned long long max) -+{ -+ unsigned long long ull; -+ -+ for (ull = 0; ull < max; ull++) -+ iput(a[ull]); -+ kvfree(a); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * refresh dentry and inode at remount time. -+ */ -+/* todo: consolidate with simple_reval_dpath() and au_reval_for_attr() */ -+static int au_do_refresh(struct dentry *dentry, unsigned int dir_flags, -+ struct dentry *parent) -+{ -+ int err; -+ -+ di_write_lock_child(dentry); -+ di_read_lock_parent(parent, AuLock_IR); -+ err = au_refresh_dentry(dentry, parent); -+ if (!err && dir_flags) -+ au_hn_reset(d_inode(dentry), dir_flags); -+ di_read_unlock(parent, AuLock_IR); -+ di_write_unlock(dentry); -+ -+ return err; -+} -+ -+static int au_do_refresh_d(struct dentry *dentry, unsigned int sigen, -+ struct au_sbinfo *sbinfo, -+ const unsigned int dir_flags, unsigned int do_idop) -+{ -+ int err; -+ struct dentry *parent; -+ -+ err = 0; -+ parent = dget_parent(dentry); -+ if (!au_digen_test(parent, sigen) && au_digen_test(dentry, sigen)) { -+ if (d_really_is_positive(dentry)) { -+ if (!d_is_dir(dentry)) -+ err = au_do_refresh(dentry, /*dir_flags*/0, -+ parent); -+ else { -+ err = au_do_refresh(dentry, dir_flags, parent); -+ if (unlikely(err)) -+ au_fset_si(sbinfo, FAILED_REFRESH_DIR); -+ } -+ } else -+ err = au_do_refresh(dentry, /*dir_flags*/0, parent); -+ AuDbgDentry(dentry); -+ } -+ dput(parent); -+ -+ if (!err) { -+ if (do_idop) -+ au_refresh_dop(dentry, /*force_reval*/0); -+ } else -+ au_refresh_dop(dentry, /*force_reval*/1); -+ -+ AuTraceErr(err); -+ return err; -+} -+ -+static int au_refresh_d(struct super_block *sb, unsigned int do_idop) -+{ -+ int err, i, j, ndentry, e; -+ unsigned int sigen; -+ struct au_dcsub_pages dpages; -+ struct au_dpage *dpage; -+ struct dentry **dentries, *d; -+ struct au_sbinfo *sbinfo; -+ struct dentry *root = sb->s_root; -+ const unsigned int dir_flags = au_hi_flags(d_inode(root), /*isdir*/1); -+ -+ if (do_idop) -+ au_refresh_dop(root, /*force_reval*/0); -+ -+ err = au_dpages_init(&dpages, GFP_NOFS); -+ if (unlikely(err)) -+ goto out; -+ err = au_dcsub_pages(&dpages, root, NULL, NULL); -+ if (unlikely(err)) -+ goto out_dpages; -+ -+ sigen = au_sigen(sb); -+ sbinfo = au_sbi(sb); -+ for (i = 0; i < dpages.ndpage; i++) { -+ dpage = dpages.dpages + i; -+ dentries = dpage->dentries; -+ ndentry = dpage->ndentry; -+ for (j = 0; j < ndentry; j++) { -+ d = dentries[j]; -+ e = au_do_refresh_d(d, sigen, sbinfo, dir_flags, -+ do_idop); -+ if (unlikely(e && !err)) -+ err = e; -+ /* go on even err */ -+ } -+ } -+ -+out_dpages: -+ au_dpages_free(&dpages); -+out: -+ return err; -+} -+ -+static int au_refresh_i(struct super_block *sb, unsigned int do_idop) -+{ -+ int err, e; -+ unsigned int sigen; -+ unsigned long long max, ull; -+ struct inode *inode, **array; -+ -+ array = au_iarray_alloc(sb, &max); -+ err = PTR_ERR(array); -+ if (IS_ERR(array)) -+ goto out; -+ -+ err = 0; -+ sigen = au_sigen(sb); -+ for (ull = 0; ull < max; ull++) { -+ inode = array[ull]; -+ if (unlikely(!inode)) -+ break; -+ -+ e = 0; -+ ii_write_lock_child(inode); -+ if (au_iigen(inode, NULL) != sigen) { -+ e = au_refresh_hinode_self(inode); -+ if (unlikely(e)) { -+ au_refresh_iop(inode, /*force_getattr*/1); -+ pr_err("error %d, i%lu\n", e, inode->i_ino); -+ if (!err) -+ err = e; -+ /* go on even if err */ -+ } -+ } -+ if (!e && do_idop) -+ au_refresh_iop(inode, /*force_getattr*/0); -+ ii_write_unlock(inode); -+ } -+ -+ au_iarray_free(array, max); -+ -+out: -+ return err; -+} -+ -+static void au_remount_refresh(struct super_block *sb, unsigned int do_idop) -+{ -+ int err, e; -+ unsigned int udba; -+ aufs_bindex_t bindex, bbot; -+ struct dentry *root; -+ struct inode *inode; -+ struct au_branch *br; -+ struct au_sbinfo *sbi; -+ -+ au_sigen_inc(sb); -+ sbi = au_sbi(sb); -+ au_fclr_si(sbi, FAILED_REFRESH_DIR); -+ -+ root = sb->s_root; -+ DiMustNoWaiters(root); -+ inode = d_inode(root); -+ IiMustNoWaiters(inode); -+ -+ udba = au_opt_udba(sb); -+ bbot = au_sbbot(sb); -+ for (bindex = 0; bindex <= bbot; bindex++) { -+ br = au_sbr(sb, bindex); -+ err = au_hnotify_reset_br(udba, br, br->br_perm); -+ if (unlikely(err)) -+ AuIOErr("hnotify failed on br %d, %d, ignored\n", -+ bindex, err); -+ /* go on even if err */ -+ } -+ au_hn_reset(inode, au_hi_flags(inode, /*isdir*/1)); -+ -+ if (do_idop) { -+ if (au_ftest_si(sbi, NO_DREVAL)) { -+ AuDebugOn(sb->s_d_op == &aufs_dop_noreval); -+ sb->s_d_op = &aufs_dop_noreval; -+ AuDebugOn(sbi->si_iop_array == aufs_iop_nogetattr); -+ sbi->si_iop_array = aufs_iop_nogetattr; -+ } else { -+ AuDebugOn(sb->s_d_op == &aufs_dop); -+ sb->s_d_op = &aufs_dop; -+ AuDebugOn(sbi->si_iop_array == aufs_iop); -+ sbi->si_iop_array = aufs_iop; -+ } -+ pr_info("reset to %ps and %ps\n", -+ sb->s_d_op, sbi->si_iop_array); -+ } -+ -+ di_write_unlock(root); -+ err = au_refresh_d(sb, do_idop); -+ e = au_refresh_i(sb, do_idop); -+ if (unlikely(e && !err)) -+ err = e; -+ /* aufs_write_lock() calls ..._child() */ -+ di_write_lock_child(root); -+ -+ au_cpup_attr_all(inode, /*force*/1); -+ -+ if (unlikely(err)) -+ AuIOErr("refresh failed, ignored, %d\n", err); -+} -+ -+/* stop extra interpretation of errno in mount(8), and strange error messages */ -+static int cvt_err(int err) -+{ -+ AuTraceErr(err); -+ -+ switch (err) { -+ case -ENOENT: -+ case -ENOTDIR: -+ case -EEXIST: -+ case -EIO: -+ err = -EINVAL; -+ } -+ return err; -+} -+ -+static int aufs_remount_fs(struct super_block *sb, int *flags, char *data) -+{ -+ int err, do_dx; -+ unsigned int mntflags; -+ struct au_opts opts = { -+ .opt = NULL -+ }; -+ struct dentry *root; -+ struct inode *inode; -+ struct au_sbinfo *sbinfo; -+ -+ err = 0; -+ root = sb->s_root; -+ if (!data || !*data) { -+ err = si_write_lock(sb, AuLock_FLUSH | AuLock_NOPLM); -+ if (!err) { -+ di_write_lock_child(root); -+ err = au_opts_verify(sb, *flags, /*pending*/0); -+ aufs_write_unlock(root); -+ } -+ goto out; -+ } -+ -+ err = -ENOMEM; -+ opts.opt = (void *)__get_free_page(GFP_NOFS); -+ if (unlikely(!opts.opt)) -+ goto out; -+ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt); -+ opts.flags = AuOpts_REMOUNT; -+ opts.sb_flags = *flags; -+ -+ /* parse it before aufs lock */ -+ err = au_opts_parse(sb, data, &opts); -+ if (unlikely(err)) -+ goto out_opts; -+ -+ sbinfo = au_sbi(sb); -+ inode = d_inode(root); -+ inode_lock(inode); -+ err = si_write_lock(sb, AuLock_FLUSH | AuLock_NOPLM); -+ if (unlikely(err)) -+ goto out_mtx; -+ di_write_lock_child(root); -+ -+ /* au_opts_remount() may return an error */ -+ err = au_opts_remount(sb, &opts); -+ au_opts_free(&opts); -+ -+ if (au_ftest_opts(opts.flags, REFRESH)) -+ au_remount_refresh(sb, au_ftest_opts(opts.flags, REFRESH_IDOP)); -+ -+ if (au_ftest_opts(opts.flags, REFRESH_DYAOP)) { -+ mntflags = au_mntflags(sb); -+ do_dx = !!au_opt_test(mntflags, DIO); -+ au_dy_arefresh(do_dx); -+ } -+ -+ au_fhsm_wrote_all(sb, /*force*/1); /* ?? */ -+ aufs_write_unlock(root); -+ -+out_mtx: -+ inode_unlock(inode); -+out_opts: -+ free_page((unsigned long)opts.opt); -+out: -+ err = cvt_err(err); -+ AuTraceErr(err); -+ return err; -+} -+ -+static const struct super_operations aufs_sop = { -+ .alloc_inode = aufs_alloc_inode, -+ .destroy_inode = aufs_destroy_inode, -+ .free_inode = aufs_free_inode, -+ /* always deleting, no clearing */ -+ .drop_inode = generic_delete_inode, -+ .show_options = aufs_show_options, -+ .statfs = aufs_statfs, -+ .put_super = aufs_put_super, -+ .sync_fs = aufs_sync_fs, -+ .remount_fs = aufs_remount_fs -+}; -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int alloc_root(struct super_block *sb) -+{ -+ int err; -+ struct inode *inode; -+ struct dentry *root; -+ -+ err = -ENOMEM; -+ inode = au_iget_locked(sb, AUFS_ROOT_INO); -+ err = PTR_ERR(inode); -+ if (IS_ERR(inode)) -+ goto out; -+ -+ inode->i_op = aufs_iop + AuIop_DIR; /* with getattr by default */ -+ inode->i_fop = &aufs_dir_fop; -+ inode->i_mode = S_IFDIR; -+ set_nlink(inode, 2); -+ unlock_new_inode(inode); -+ -+ root = d_make_root(inode); -+ if (unlikely(!root)) -+ goto out; -+ err = PTR_ERR(root); -+ if (IS_ERR(root)) -+ goto out; -+ -+ err = au_di_init(root); -+ if (!err) { -+ sb->s_root = root; -+ return 0; /* success */ -+ } -+ dput(root); -+ -+out: -+ return err; -+} -+ -+static int aufs_fill_super(struct super_block *sb, void *raw_data, -+ int silent __maybe_unused) -+{ -+ int err; -+ struct au_opts opts = { -+ .opt = NULL -+ }; -+ struct au_sbinfo *sbinfo; -+ struct dentry *root; -+ struct inode *inode; -+ char *arg = raw_data; -+ -+ if (unlikely(!arg || !*arg)) { -+ err = -EINVAL; -+ pr_err("no arg\n"); -+ goto out; -+ } -+ -+ err = -ENOMEM; -+ opts.opt = (void *)__get_free_page(GFP_NOFS); -+ if (unlikely(!opts.opt)) -+ goto out; -+ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt); -+ opts.sb_flags = sb->s_flags; -+ -+ err = au_si_alloc(sb); -+ if (unlikely(err)) -+ goto out_opts; -+ sbinfo = au_sbi(sb); -+ -+ /* all timestamps always follow the ones on the branch */ -+ sb->s_flags |= SB_NOATIME | SB_NODIRATIME; -+ sb->s_flags |= SB_I_VERSION; /* do we really need this? */ -+ sb->s_op = &aufs_sop; -+ sb->s_d_op = &aufs_dop; -+ sb->s_magic = AUFS_SUPER_MAGIC; -+ sb->s_maxbytes = 0; -+ sb->s_stack_depth = 1; -+ au_export_init(sb); -+ au_xattr_init(sb); -+ -+ err = alloc_root(sb); -+ if (unlikely(err)) { -+ si_write_unlock(sb); -+ goto out_info; -+ } -+ root = sb->s_root; -+ inode = d_inode(root); -+ -+ /* -+ * actually we can parse options regardless aufs lock here. -+ * but at remount time, parsing must be done before aufs lock. -+ * so we follow the same rule. -+ */ -+ ii_write_lock_parent(inode); -+ aufs_write_unlock(root); -+ err = au_opts_parse(sb, arg, &opts); -+ if (unlikely(err)) -+ goto out_root; -+ -+ /* lock vfs_inode first, then aufs. */ -+ inode_lock(inode); -+ aufs_write_lock(root); -+ err = au_opts_mount(sb, &opts); -+ au_opts_free(&opts); -+ if (!err && au_ftest_si(sbinfo, NO_DREVAL)) { -+ sb->s_d_op = &aufs_dop_noreval; -+ pr_info("%ps\n", sb->s_d_op); -+ au_refresh_dop(root, /*force_reval*/0); -+ sbinfo->si_iop_array = aufs_iop_nogetattr; -+ au_refresh_iop(inode, /*force_getattr*/0); -+ } -+ aufs_write_unlock(root); -+ inode_unlock(inode); -+ if (!err) -+ goto out_opts; /* success */ -+ -+out_root: -+ dput(root); -+ sb->s_root = NULL; -+out_info: -+ kobject_put(&sbinfo->si_kobj); -+ sb->s_fs_info = NULL; -+out_opts: -+ free_page((unsigned long)opts.opt); -+out: -+ AuTraceErr(err); -+ err = cvt_err(err); -+ AuTraceErr(err); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static struct dentry *aufs_mount(struct file_system_type *fs_type, int flags, -+ const char *dev_name __maybe_unused, -+ void *raw_data) -+{ -+ struct dentry *root; -+ -+ /* all timestamps always follow the ones on the branch */ -+ /* mnt->mnt_flags |= MNT_NOATIME | MNT_NODIRATIME; */ -+ root = mount_nodev(fs_type, flags, raw_data, aufs_fill_super); -+ if (IS_ERR(root)) -+ goto out; -+ -+ au_sbilist_add(root->d_sb); -+ -+out: -+ return root; -+} -+ -+static void aufs_kill_sb(struct super_block *sb) -+{ -+ struct au_sbinfo *sbinfo; -+ -+ sbinfo = au_sbi(sb); -+ if (sbinfo) { -+ au_sbilist_del(sb); -+ aufs_write_lock(sb->s_root); -+ au_fhsm_fin(sb); -+ if (sbinfo->si_wbr_create_ops->fin) -+ sbinfo->si_wbr_create_ops->fin(sb); -+ if (au_opt_test(sbinfo->si_mntflags, UDBA_HNOTIFY)) { -+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_NONE); -+ au_remount_refresh(sb, /*do_idop*/0); -+ } -+ if (au_opt_test(sbinfo->si_mntflags, PLINK)) -+ au_plink_put(sb, /*verbose*/1); -+ au_xino_clr(sb); -+ au_dr_opt_flush(sb); -+ sbinfo->si_sb = NULL; -+ aufs_write_unlock(sb->s_root); -+ au_nwt_flush(&sbinfo->si_nowait); -+ } -+ kill_anon_super(sb); -+} -+ -+struct file_system_type aufs_fs_type = { -+ .name = AUFS_FSTYPE, -+ /* a race between rename and others */ -+ .fs_flags = FS_RENAME_DOES_D_MOVE, -+ .mount = aufs_mount, -+ .kill_sb = aufs_kill_sb, -+ /* no need to __module_get() and module_put(). */ -+ .owner = THIS_MODULE, -+}; -diff -Nurp linux-5.6.3/fs/aufs/super.h linux-5.6.3-aufs/fs/aufs/super.h ---- linux-5.6.3/fs/aufs/super.h 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/super.h 2020-04-10 12:40:52.192049502 +0300 -@@ -0,0 +1,576 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * super_block operations -+ */ -+ -+#ifndef __AUFS_SUPER_H__ -+#define __AUFS_SUPER_H__ -+ -+#ifdef __KERNEL__ -+ -+#include -+#include -+#include "hbl.h" -+#include "lcnt.h" -+#include "rwsem.h" -+#include "wkq.h" -+ -+/* policies to select one among multiple writable branches */ -+struct au_wbr_copyup_operations { -+ int (*copyup)(struct dentry *dentry); -+}; -+ -+#define AuWbr_DIR 1 /* target is a dir */ -+#define AuWbr_PARENT (1 << 1) /* always require a parent */ -+ -+#define au_ftest_wbr(flags, name) ((flags) & AuWbr_##name) -+#define au_fset_wbr(flags, name) { (flags) |= AuWbr_##name; } -+#define au_fclr_wbr(flags, name) { (flags) &= ~AuWbr_##name; } -+ -+struct au_wbr_create_operations { -+ int (*create)(struct dentry *dentry, unsigned int flags); -+ int (*init)(struct super_block *sb); -+ int (*fin)(struct super_block *sb); -+}; -+ -+struct au_wbr_mfs { -+ struct mutex mfs_lock; /* protect this structure */ -+ unsigned long mfs_jiffy; -+ unsigned long mfs_expire; -+ aufs_bindex_t mfs_bindex; -+ -+ unsigned long long mfsrr_bytes; -+ unsigned long long mfsrr_watermark; -+}; -+ -+#define AuPlink_NHASH 100 -+static inline int au_plink_hash(ino_t ino) -+{ -+ return ino % AuPlink_NHASH; -+} -+ -+/* File-based Hierarchical Storage Management */ -+struct au_fhsm { -+#ifdef CONFIG_AUFS_FHSM -+ /* allow only one process who can receive the notification */ -+ spinlock_t fhsm_spin; -+ pid_t fhsm_pid; -+ wait_queue_head_t fhsm_wqh; -+ atomic_t fhsm_readable; -+ -+ /* these are protected by si_rwsem */ -+ unsigned long fhsm_expire; -+ aufs_bindex_t fhsm_bottom; -+#endif -+}; -+ -+struct au_branch; -+struct au_sbinfo { -+ /* nowait tasks in the system-wide workqueue */ -+ struct au_nowait_tasks si_nowait; -+ -+ /* -+ * tried sb->s_umount, but failed due to the dependency between i_mutex. -+ * rwsem for au_sbinfo is necessary. -+ */ -+ struct au_rwsem si_rwsem; -+ -+ /* -+ * dirty approach to protect sb->sb_inodes and ->s_files (gone) from -+ * remount. -+ */ -+ au_lcnt_t si_ninodes, si_nfiles; -+ -+ /* branch management */ -+ unsigned int si_generation; -+ -+ /* see AuSi_ flags */ -+ unsigned char au_si_status; -+ -+ aufs_bindex_t si_bbot; -+ -+ /* dirty trick to keep br_id plus */ -+ unsigned int si_last_br_id : -+ sizeof(aufs_bindex_t) * BITS_PER_BYTE - 1; -+ struct au_branch **si_branch; -+ -+ /* policy to select a writable branch */ -+ unsigned char si_wbr_copyup; -+ unsigned char si_wbr_create; -+ struct au_wbr_copyup_operations *si_wbr_copyup_ops; -+ struct au_wbr_create_operations *si_wbr_create_ops; -+ -+ /* round robin */ -+ atomic_t si_wbr_rr_next; -+ -+ /* most free space */ -+ struct au_wbr_mfs si_wbr_mfs; -+ -+ /* File-based Hierarchical Storage Management */ -+ struct au_fhsm si_fhsm; -+ -+ /* mount flags */ -+ /* include/asm-ia64/siginfo.h defines a macro named si_flags */ -+ unsigned int si_mntflags; -+ -+ /* external inode number (bitmap and translation table) */ -+ vfs_readf_t si_xread; -+ vfs_writef_t si_xwrite; -+ loff_t si_ximaxent; /* max entries in a xino */ -+ -+ struct file *si_xib; -+ struct mutex si_xib_mtx; /* protect xib members */ -+ unsigned long *si_xib_buf; -+ unsigned long si_xib_last_pindex; -+ int si_xib_next_bit; -+ -+ unsigned long si_xino_jiffy; -+ unsigned long si_xino_expire; -+ /* reserved for future use */ -+ /* unsigned long long si_xib_limit; */ /* Max xib file size */ -+ -+#ifdef CONFIG_AUFS_EXPORT -+ /* i_generation */ -+ /* todo: make xigen file an array to support many inode numbers */ -+ struct file *si_xigen; -+ atomic_t si_xigen_next; -+#endif -+ -+ /* dirty trick to support atomic_open */ -+ struct hlist_bl_head si_aopen; -+ -+ /* vdir parameters */ -+ unsigned long si_rdcache; /* max cache time in jiffies */ -+ unsigned int si_rdblk; /* deblk size */ -+ unsigned int si_rdhash; /* hash size */ -+ -+ /* -+ * If the number of whiteouts are larger than si_dirwh, leave all of -+ * them after au_whtmp_ren to reduce the cost of rmdir(2). -+ * future fsck.aufs or kernel thread will remove them later. -+ * Otherwise, remove all whiteouts and the dir in rmdir(2). -+ */ -+ unsigned int si_dirwh; -+ -+ /* pseudo_link list */ -+ struct hlist_bl_head si_plink[AuPlink_NHASH]; -+ wait_queue_head_t si_plink_wq; -+ spinlock_t si_plink_maint_lock; -+ pid_t si_plink_maint_pid; -+ -+ /* file list */ -+ struct hlist_bl_head si_files; -+ -+ /* with/without getattr, brother of sb->s_d_op */ -+ const struct inode_operations *si_iop_array; -+ -+ /* -+ * sysfs and lifetime management. -+ * this is not a small structure and it may be a waste of memory in case -+ * of sysfs is disabled, particularly when many aufs-es are mounted. -+ * but using sysfs is majority. -+ */ -+ struct kobject si_kobj; -+#ifdef CONFIG_DEBUG_FS -+ struct dentry *si_dbgaufs; -+ struct dentry *si_dbgaufs_plink; -+ struct dentry *si_dbgaufs_xib; -+#ifdef CONFIG_AUFS_EXPORT -+ struct dentry *si_dbgaufs_xigen; -+#endif -+#endif -+ -+#ifdef CONFIG_AUFS_SBILIST -+ struct hlist_bl_node si_list; -+#endif -+ -+ /* dirty, necessary for unmounting, sysfs and sysrq */ -+ struct super_block *si_sb; -+}; -+ -+/* sbinfo status flags */ -+/* -+ * set true when refresh_dirs() failed at remount time. -+ * then try refreshing dirs at access time again. -+ * if it is false, refreshing dirs at access time is unnecessary -+ */ -+#define AuSi_FAILED_REFRESH_DIR 1 -+#define AuSi_FHSM (1 << 1) /* fhsm is active now */ -+#define AuSi_NO_DREVAL (1 << 2) /* disable all d_revalidate */ -+ -+#ifndef CONFIG_AUFS_FHSM -+#undef AuSi_FHSM -+#define AuSi_FHSM 0 -+#endif -+ -+static inline unsigned char au_do_ftest_si(struct au_sbinfo *sbi, -+ unsigned int flag) -+{ -+ AuRwMustAnyLock(&sbi->si_rwsem); -+ return sbi->au_si_status & flag; -+} -+#define au_ftest_si(sbinfo, name) au_do_ftest_si(sbinfo, AuSi_##name) -+#define au_fset_si(sbinfo, name) do { \ -+ AuRwMustWriteLock(&(sbinfo)->si_rwsem); \ -+ (sbinfo)->au_si_status |= AuSi_##name; \ -+} while (0) -+#define au_fclr_si(sbinfo, name) do { \ -+ AuRwMustWriteLock(&(sbinfo)->si_rwsem); \ -+ (sbinfo)->au_si_status &= ~AuSi_##name; \ -+} while (0) -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* policy to select one among writable branches */ -+#define AuWbrCopyup(sbinfo, ...) \ -+ ((sbinfo)->si_wbr_copyup_ops->copyup(__VA_ARGS__)) -+#define AuWbrCreate(sbinfo, ...) \ -+ ((sbinfo)->si_wbr_create_ops->create(__VA_ARGS__)) -+ -+/* flags for si_read_lock()/aufs_read_lock()/di_read_lock() */ -+#define AuLock_DW 1 /* write-lock dentry */ -+#define AuLock_IR (1 << 1) /* read-lock inode */ -+#define AuLock_IW (1 << 2) /* write-lock inode */ -+#define AuLock_FLUSH (1 << 3) /* wait for 'nowait' tasks */ -+#define AuLock_DIRS (1 << 4) /* target is a pair of dirs */ -+ /* except RENAME_EXCHANGE */ -+#define AuLock_NOPLM (1 << 5) /* return err in plm mode */ -+#define AuLock_NOPLMW (1 << 6) /* wait for plm mode ends */ -+#define AuLock_GEN (1 << 7) /* test digen/iigen */ -+#define au_ftest_lock(flags, name) ((flags) & AuLock_##name) -+#define au_fset_lock(flags, name) \ -+ do { (flags) |= AuLock_##name; } while (0) -+#define au_fclr_lock(flags, name) \ -+ do { (flags) &= ~AuLock_##name; } while (0) -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* super.c */ -+extern struct file_system_type aufs_fs_type; -+struct inode *au_iget_locked(struct super_block *sb, ino_t ino); -+typedef unsigned long long (*au_arraycb_t)(struct super_block *sb, void *array, -+ unsigned long long max, void *arg); -+void *au_array_alloc(unsigned long long *hint, au_arraycb_t cb, -+ struct super_block *sb, void *arg); -+struct inode **au_iarray_alloc(struct super_block *sb, unsigned long long *max); -+void au_iarray_free(struct inode **a, unsigned long long max); -+ -+/* sbinfo.c */ -+void au_si_free(struct kobject *kobj); -+int au_si_alloc(struct super_block *sb); -+int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr, int may_shrink); -+ -+unsigned int au_sigen_inc(struct super_block *sb); -+aufs_bindex_t au_new_br_id(struct super_block *sb); -+ -+int si_read_lock(struct super_block *sb, int flags); -+int si_write_lock(struct super_block *sb, int flags); -+int aufs_read_lock(struct dentry *dentry, int flags); -+void aufs_read_unlock(struct dentry *dentry, int flags); -+void aufs_write_lock(struct dentry *dentry); -+void aufs_write_unlock(struct dentry *dentry); -+int aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags); -+void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2); -+ -+/* wbr_policy.c */ -+extern struct au_wbr_copyup_operations au_wbr_copyup_ops[]; -+extern struct au_wbr_create_operations au_wbr_create_ops[]; -+int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst); -+int au_wbr_nonopq(struct dentry *dentry, aufs_bindex_t bindex); -+int au_wbr_do_copyup_bu(struct dentry *dentry, aufs_bindex_t btop); -+ -+/* mvdown.c */ -+int au_mvdown(struct dentry *dentry, struct aufs_mvdown __user *arg); -+ -+#ifdef CONFIG_AUFS_FHSM -+/* fhsm.c */ -+ -+static inline pid_t au_fhsm_pid(struct au_fhsm *fhsm) -+{ -+ pid_t pid; -+ -+ spin_lock(&fhsm->fhsm_spin); -+ pid = fhsm->fhsm_pid; -+ spin_unlock(&fhsm->fhsm_spin); -+ -+ return pid; -+} -+ -+void au_fhsm_wrote(struct super_block *sb, aufs_bindex_t bindex, int force); -+void au_fhsm_wrote_all(struct super_block *sb, int force); -+int au_fhsm_fd(struct super_block *sb, int oflags); -+int au_fhsm_br_alloc(struct au_branch *br); -+void au_fhsm_set_bottom(struct super_block *sb, aufs_bindex_t bindex); -+void au_fhsm_fin(struct super_block *sb); -+void au_fhsm_init(struct au_sbinfo *sbinfo); -+void au_fhsm_set(struct au_sbinfo *sbinfo, unsigned int sec); -+void au_fhsm_show(struct seq_file *seq, struct au_sbinfo *sbinfo); -+#else -+AuStubVoid(au_fhsm_wrote, struct super_block *sb, aufs_bindex_t bindex, -+ int force) -+AuStubVoid(au_fhsm_wrote_all, struct super_block *sb, int force) -+AuStub(int, au_fhsm_fd, return -EOPNOTSUPP, struct super_block *sb, int oflags) -+AuStub(pid_t, au_fhsm_pid, return 0, struct au_fhsm *fhsm) -+AuStubInt0(au_fhsm_br_alloc, struct au_branch *br) -+AuStubVoid(au_fhsm_set_bottom, struct super_block *sb, aufs_bindex_t bindex) -+AuStubVoid(au_fhsm_fin, struct super_block *sb) -+AuStubVoid(au_fhsm_init, struct au_sbinfo *sbinfo) -+AuStubVoid(au_fhsm_set, struct au_sbinfo *sbinfo, unsigned int sec) -+AuStubVoid(au_fhsm_show, struct seq_file *seq, struct au_sbinfo *sbinfo) -+#endif -+ -+/* ---------------------------------------------------------------------- */ -+ -+static inline struct au_sbinfo *au_sbi(struct super_block *sb) -+{ -+ return sb->s_fs_info; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+#ifdef CONFIG_AUFS_EXPORT -+int au_test_nfsd(void); -+void au_export_init(struct super_block *sb); -+void au_xigen_inc(struct inode *inode); -+int au_xigen_new(struct inode *inode); -+int au_xigen_set(struct super_block *sb, struct path *path); -+void au_xigen_clr(struct super_block *sb); -+ -+static inline int au_busy_or_stale(void) -+{ -+ if (!au_test_nfsd()) -+ return -EBUSY; -+ return -ESTALE; -+} -+#else -+AuStubInt0(au_test_nfsd, void) -+AuStubVoid(au_export_init, struct super_block *sb) -+AuStubVoid(au_xigen_inc, struct inode *inode) -+AuStubInt0(au_xigen_new, struct inode *inode) -+AuStubInt0(au_xigen_set, struct super_block *sb, struct path *path) -+AuStubVoid(au_xigen_clr, struct super_block *sb) -+AuStub(int, au_busy_or_stale, return -EBUSY, void) -+#endif /* CONFIG_AUFS_EXPORT */ -+ -+/* ---------------------------------------------------------------------- */ -+ -+#ifdef CONFIG_AUFS_SBILIST -+/* module.c */ -+extern struct hlist_bl_head au_sbilist; -+ -+static inline void au_sbilist_init(void) -+{ -+ INIT_HLIST_BL_HEAD(&au_sbilist); -+} -+ -+static inline void au_sbilist_add(struct super_block *sb) -+{ -+ au_hbl_add(&au_sbi(sb)->si_list, &au_sbilist); -+} -+ -+static inline void au_sbilist_del(struct super_block *sb) -+{ -+ au_hbl_del(&au_sbi(sb)->si_list, &au_sbilist); -+} -+ -+#ifdef CONFIG_AUFS_MAGIC_SYSRQ -+static inline void au_sbilist_lock(void) -+{ -+ hlist_bl_lock(&au_sbilist); -+} -+ -+static inline void au_sbilist_unlock(void) -+{ -+ hlist_bl_unlock(&au_sbilist); -+} -+#define AuGFP_SBILIST GFP_ATOMIC -+#else -+AuStubVoid(au_sbilist_lock, void) -+AuStubVoid(au_sbilist_unlock, void) -+#define AuGFP_SBILIST GFP_NOFS -+#endif /* CONFIG_AUFS_MAGIC_SYSRQ */ -+#else -+AuStubVoid(au_sbilist_init, void) -+AuStubVoid(au_sbilist_add, struct super_block *sb) -+AuStubVoid(au_sbilist_del, struct super_block *sb) -+AuStubVoid(au_sbilist_lock, void) -+AuStubVoid(au_sbilist_unlock, void) -+#define AuGFP_SBILIST GFP_NOFS -+#endif -+ -+/* ---------------------------------------------------------------------- */ -+ -+static inline void dbgaufs_si_null(struct au_sbinfo *sbinfo) -+{ -+ /* -+ * This function is a dynamic '__init' function actually, -+ * so the tiny check for si_rwsem is unnecessary. -+ */ -+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */ -+#ifdef CONFIG_DEBUG_FS -+ sbinfo->si_dbgaufs = NULL; -+ sbinfo->si_dbgaufs_plink = NULL; -+ sbinfo->si_dbgaufs_xib = NULL; -+#ifdef CONFIG_AUFS_EXPORT -+ sbinfo->si_dbgaufs_xigen = NULL; -+#endif -+#endif -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* current->atomic_flags */ -+/* this value should never corrupt the ones defined in linux/sched.h */ -+#define PFA_AUFS 0x10 -+ -+TASK_PFA_TEST(AUFS, test_aufs) /* task_test_aufs */ -+TASK_PFA_SET(AUFS, aufs) /* task_set_aufs */ -+TASK_PFA_CLEAR(AUFS, aufs) /* task_clear_aufs */ -+ -+static inline int si_pid_test(struct super_block *sb) -+{ -+ return !!task_test_aufs(current); -+} -+ -+static inline void si_pid_clr(struct super_block *sb) -+{ -+ AuDebugOn(!task_test_aufs(current)); -+ task_clear_aufs(current); -+} -+ -+static inline void si_pid_set(struct super_block *sb) -+{ -+ AuDebugOn(task_test_aufs(current)); -+ task_set_aufs(current); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* lock superblock. mainly for entry point functions */ -+#define __si_read_lock(sb) au_rw_read_lock(&au_sbi(sb)->si_rwsem) -+#define __si_write_lock(sb) au_rw_write_lock(&au_sbi(sb)->si_rwsem) -+#define __si_read_trylock(sb) au_rw_read_trylock(&au_sbi(sb)->si_rwsem) -+#define __si_write_trylock(sb) au_rw_write_trylock(&au_sbi(sb)->si_rwsem) -+/* -+#define __si_read_trylock_nested(sb) \ -+ au_rw_read_trylock_nested(&au_sbi(sb)->si_rwsem) -+#define __si_write_trylock_nested(sb) \ -+ au_rw_write_trylock_nested(&au_sbi(sb)->si_rwsem) -+*/ -+ -+#define __si_read_unlock(sb) au_rw_read_unlock(&au_sbi(sb)->si_rwsem) -+#define __si_write_unlock(sb) au_rw_write_unlock(&au_sbi(sb)->si_rwsem) -+#define __si_downgrade_lock(sb) au_rw_dgrade_lock(&au_sbi(sb)->si_rwsem) -+ -+#define SiMustNoWaiters(sb) AuRwMustNoWaiters(&au_sbi(sb)->si_rwsem) -+#define SiMustAnyLock(sb) AuRwMustAnyLock(&au_sbi(sb)->si_rwsem) -+#define SiMustWriteLock(sb) AuRwMustWriteLock(&au_sbi(sb)->si_rwsem) -+ -+static inline void si_noflush_read_lock(struct super_block *sb) -+{ -+ __si_read_lock(sb); -+ si_pid_set(sb); -+} -+ -+static inline int si_noflush_read_trylock(struct super_block *sb) -+{ -+ int locked; -+ -+ locked = __si_read_trylock(sb); -+ if (locked) -+ si_pid_set(sb); -+ return locked; -+} -+ -+static inline void si_noflush_write_lock(struct super_block *sb) -+{ -+ __si_write_lock(sb); -+ si_pid_set(sb); -+} -+ -+static inline int si_noflush_write_trylock(struct super_block *sb) -+{ -+ int locked; -+ -+ locked = __si_write_trylock(sb); -+ if (locked) -+ si_pid_set(sb); -+ return locked; -+} -+ -+#if 0 /* reserved */ -+static inline int si_read_trylock(struct super_block *sb, int flags) -+{ -+ if (au_ftest_lock(flags, FLUSH)) -+ au_nwt_flush(&au_sbi(sb)->si_nowait); -+ return si_noflush_read_trylock(sb); -+} -+#endif -+ -+static inline void si_read_unlock(struct super_block *sb) -+{ -+ si_pid_clr(sb); -+ __si_read_unlock(sb); -+} -+ -+#if 0 /* reserved */ -+static inline int si_write_trylock(struct super_block *sb, int flags) -+{ -+ if (au_ftest_lock(flags, FLUSH)) -+ au_nwt_flush(&au_sbi(sb)->si_nowait); -+ return si_noflush_write_trylock(sb); -+} -+#endif -+ -+static inline void si_write_unlock(struct super_block *sb) -+{ -+ si_pid_clr(sb); -+ __si_write_unlock(sb); -+} -+ -+#if 0 /* reserved */ -+static inline void si_downgrade_lock(struct super_block *sb) -+{ -+ __si_downgrade_lock(sb); -+} -+#endif -+ -+/* ---------------------------------------------------------------------- */ -+ -+static inline aufs_bindex_t au_sbbot(struct super_block *sb) -+{ -+ SiMustAnyLock(sb); -+ return au_sbi(sb)->si_bbot; -+} -+ -+static inline unsigned int au_mntflags(struct super_block *sb) -+{ -+ SiMustAnyLock(sb); -+ return au_sbi(sb)->si_mntflags; -+} -+ -+static inline unsigned int au_sigen(struct super_block *sb) -+{ -+ SiMustAnyLock(sb); -+ return au_sbi(sb)->si_generation; -+} -+ -+static inline struct au_branch *au_sbr(struct super_block *sb, -+ aufs_bindex_t bindex) -+{ -+ SiMustAnyLock(sb); -+ return au_sbi(sb)->si_branch[0 + bindex]; -+} -+ -+static inline loff_t au_xi_maxent(struct super_block *sb) -+{ -+ SiMustAnyLock(sb); -+ return au_sbi(sb)->si_ximaxent; -+} -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_SUPER_H__ */ -diff -Nurp linux-5.6.3/fs/aufs/sysaufs.c linux-5.6.3-aufs/fs/aufs/sysaufs.c ---- linux-5.6.3/fs/aufs/sysaufs.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/sysaufs.c 2020-04-10 12:40:52.192049502 +0300 -@@ -0,0 +1,80 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * sysfs interface and lifetime management -+ * they are necessary regardless sysfs is disabled. -+ */ -+ -+#include -+#include "aufs.h" -+ -+unsigned long sysaufs_si_mask; -+struct kset *sysaufs_kset; -+ -+#define AuSiAttr(_name) { \ -+ .attr = { .name = __stringify(_name), .mode = 0444 }, \ -+ .show = sysaufs_si_##_name, \ -+} -+ -+static struct sysaufs_si_attr sysaufs_si_attr_xi_path = AuSiAttr(xi_path); -+struct attribute *sysaufs_si_attrs[] = { -+ &sysaufs_si_attr_xi_path.attr, -+ NULL, -+}; -+ -+static const struct sysfs_ops au_sbi_ops = { -+ .show = sysaufs_si_show -+}; -+ -+static struct kobj_type au_sbi_ktype = { -+ .release = au_si_free, -+ .sysfs_ops = &au_sbi_ops, -+ .default_attrs = sysaufs_si_attrs -+}; -+ -+/* ---------------------------------------------------------------------- */ -+ -+int sysaufs_si_init(struct au_sbinfo *sbinfo) -+{ -+ int err; -+ -+ sbinfo->si_kobj.kset = sysaufs_kset; -+ /* cf. sysaufs_name() */ -+ err = kobject_init_and_add -+ (&sbinfo->si_kobj, &au_sbi_ktype, /*&sysaufs_kset->kobj*/NULL, -+ SysaufsSiNamePrefix "%lx", sysaufs_si_id(sbinfo)); -+ -+ return err; -+} -+ -+void sysaufs_fin(void) -+{ -+ sysfs_remove_group(&sysaufs_kset->kobj, sysaufs_attr_group); -+ kset_unregister(sysaufs_kset); -+} -+ -+int __init sysaufs_init(void) -+{ -+ int err; -+ -+ do { -+ get_random_bytes(&sysaufs_si_mask, sizeof(sysaufs_si_mask)); -+ } while (!sysaufs_si_mask); -+ -+ err = -EINVAL; -+ sysaufs_kset = kset_create_and_add(AUFS_NAME, NULL, fs_kobj); -+ if (unlikely(!sysaufs_kset)) -+ goto out; -+ err = PTR_ERR(sysaufs_kset); -+ if (IS_ERR(sysaufs_kset)) -+ goto out; -+ err = sysfs_create_group(&sysaufs_kset->kobj, sysaufs_attr_group); -+ if (unlikely(err)) -+ kset_unregister(sysaufs_kset); -+ -+out: -+ return err; -+} -diff -Nurp linux-5.6.3/fs/aufs/sysaufs.h linux-5.6.3-aufs/fs/aufs/sysaufs.h ---- linux-5.6.3/fs/aufs/sysaufs.h 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/sysaufs.h 2020-04-10 12:40:52.192049502 +0300 -@@ -0,0 +1,89 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * sysfs interface and mount lifetime management -+ */ -+ -+#ifndef __SYSAUFS_H__ -+#define __SYSAUFS_H__ -+ -+#ifdef __KERNEL__ -+ -+#include -+#include "module.h" -+ -+struct super_block; -+struct au_sbinfo; -+ -+struct sysaufs_si_attr { -+ struct attribute attr; -+ int (*show)(struct seq_file *seq, struct super_block *sb); -+}; -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* sysaufs.c */ -+extern unsigned long sysaufs_si_mask; -+extern struct kset *sysaufs_kset; -+extern struct attribute *sysaufs_si_attrs[]; -+int sysaufs_si_init(struct au_sbinfo *sbinfo); -+int __init sysaufs_init(void); -+void sysaufs_fin(void); -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* some people doesn't like to show a pointer in kernel */ -+static inline unsigned long sysaufs_si_id(struct au_sbinfo *sbinfo) -+{ -+ return sysaufs_si_mask ^ (unsigned long)sbinfo; -+} -+ -+#define SysaufsSiNamePrefix "si_" -+#define SysaufsSiNameLen (sizeof(SysaufsSiNamePrefix) + 16) -+static inline void sysaufs_name(struct au_sbinfo *sbinfo, char *name) -+{ -+ snprintf(name, SysaufsSiNameLen, SysaufsSiNamePrefix "%lx", -+ sysaufs_si_id(sbinfo)); -+} -+ -+struct au_branch; -+#ifdef CONFIG_SYSFS -+/* sysfs.c */ -+extern struct attribute_group *sysaufs_attr_group; -+ -+int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb); -+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr, -+ char *buf); -+long au_brinfo_ioctl(struct file *file, unsigned long arg); -+#ifdef CONFIG_COMPAT -+long au_brinfo_compat_ioctl(struct file *file, unsigned long arg); -+#endif -+ -+void sysaufs_br_init(struct au_branch *br); -+void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex); -+void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex); -+ -+#define sysaufs_brs_init() do {} while (0) -+ -+#else -+#define sysaufs_attr_group NULL -+ -+AuStubInt0(sysaufs_si_xi_path, struct seq_file *seq, struct super_block *sb) -+AuStub(ssize_t, sysaufs_si_show, return 0, struct kobject *kobj, -+ struct attribute *attr, char *buf) -+AuStubVoid(sysaufs_br_init, struct au_branch *br) -+AuStubVoid(sysaufs_brs_add, struct super_block *sb, aufs_bindex_t bindex) -+AuStubVoid(sysaufs_brs_del, struct super_block *sb, aufs_bindex_t bindex) -+ -+static inline void sysaufs_brs_init(void) -+{ -+ sysaufs_brs = 0; -+} -+ -+#endif /* CONFIG_SYSFS */ -+ -+#endif /* __KERNEL__ */ -+#endif /* __SYSAUFS_H__ */ -diff -Nurp linux-5.6.3/fs/aufs/sysfs.c linux-5.6.3-aufs/fs/aufs/sysfs.c ---- linux-5.6.3/fs/aufs/sysfs.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/sysfs.c 2020-04-10 12:40:52.192049502 +0300 -@@ -0,0 +1,338 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * sysfs interface -+ */ -+ -+#include -+#include -+#include "aufs.h" -+ -+static struct attribute *au_attr[] = { -+ NULL, /* need to NULL terminate the list of attributes */ -+}; -+ -+static struct attribute_group sysaufs_attr_group_body = { -+ .attrs = au_attr -+}; -+ -+struct attribute_group *sysaufs_attr_group = &sysaufs_attr_group_body; -+ -+/* ---------------------------------------------------------------------- */ -+ -+int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb) -+{ -+ int err; -+ -+ SiMustAnyLock(sb); -+ -+ err = 0; -+ if (au_opt_test(au_mntflags(sb), XINO)) { -+ err = au_xino_path(seq, au_sbi(sb)->si_xib); -+ seq_putc(seq, '\n'); -+ } -+ return err; -+} -+ -+/* -+ * the lifetime of branch is independent from the entry under sysfs. -+ * sysfs handles the lifetime of the entry, and never call ->show() after it is -+ * unlinked. -+ */ -+static int sysaufs_si_br(struct seq_file *seq, struct super_block *sb, -+ aufs_bindex_t bindex, int idx) -+{ -+ int err; -+ struct path path; -+ struct dentry *root; -+ struct au_branch *br; -+ au_br_perm_str_t perm; -+ -+ AuDbg("b%d\n", bindex); -+ -+ err = 0; -+ root = sb->s_root; -+ di_read_lock_parent(root, !AuLock_IR); -+ br = au_sbr(sb, bindex); -+ -+ switch (idx) { -+ case AuBrSysfs_BR: -+ path.mnt = au_br_mnt(br); -+ path.dentry = au_h_dptr(root, bindex); -+ err = au_seq_path(seq, &path); -+ if (!err) { -+ au_optstr_br_perm(&perm, br->br_perm); -+ seq_printf(seq, "=%s\n", perm.a); -+ } -+ break; -+ case AuBrSysfs_BRID: -+ seq_printf(seq, "%d\n", br->br_id); -+ break; -+ } -+ di_read_unlock(root, !AuLock_IR); -+ if (unlikely(err || seq_has_overflowed(seq))) -+ err = -E2BIG; -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static struct seq_file *au_seq(char *p, ssize_t len) -+{ -+ struct seq_file *seq; -+ -+ seq = kzalloc(sizeof(*seq), GFP_NOFS); -+ if (seq) { -+ /* mutex_init(&seq.lock); */ -+ seq->buf = p; -+ seq->size = len; -+ return seq; /* success */ -+ } -+ -+ seq = ERR_PTR(-ENOMEM); -+ return seq; -+} -+ -+#define SysaufsBr_PREFIX "br" -+#define SysaufsBrid_PREFIX "brid" -+ -+/* todo: file size may exceed PAGE_SIZE */ -+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr, -+ char *buf) -+{ -+ ssize_t err; -+ int idx; -+ long l; -+ aufs_bindex_t bbot; -+ struct au_sbinfo *sbinfo; -+ struct super_block *sb; -+ struct seq_file *seq; -+ char *name; -+ struct attribute **cattr; -+ -+ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj); -+ sb = sbinfo->si_sb; -+ -+ /* -+ * prevent a race condition between sysfs and aufs. -+ * for instance, sysfs_file_read() calls sysfs_get_active_two() which -+ * prohibits maintaining the sysfs entries. -+ * hew we acquire read lock after sysfs_get_active_two(). -+ * on the other hand, the remount process may maintain the sysfs/aufs -+ * entries after acquiring write lock. -+ * it can cause a deadlock. -+ * simply we gave up processing read here. -+ */ -+ err = -EBUSY; -+ if (unlikely(!si_noflush_read_trylock(sb))) -+ goto out; -+ -+ seq = au_seq(buf, PAGE_SIZE); -+ err = PTR_ERR(seq); -+ if (IS_ERR(seq)) -+ goto out_unlock; -+ -+ name = (void *)attr->name; -+ cattr = sysaufs_si_attrs; -+ while (*cattr) { -+ if (!strcmp(name, (*cattr)->name)) { -+ err = container_of(*cattr, struct sysaufs_si_attr, attr) -+ ->show(seq, sb); -+ goto out_seq; -+ } -+ cattr++; -+ } -+ -+ if (!strncmp(name, SysaufsBrid_PREFIX, -+ sizeof(SysaufsBrid_PREFIX) - 1)) { -+ idx = AuBrSysfs_BRID; -+ name += sizeof(SysaufsBrid_PREFIX) - 1; -+ } else if (!strncmp(name, SysaufsBr_PREFIX, -+ sizeof(SysaufsBr_PREFIX) - 1)) { -+ idx = AuBrSysfs_BR; -+ name += sizeof(SysaufsBr_PREFIX) - 1; -+ } else -+ BUG(); -+ -+ err = kstrtol(name, 10, &l); -+ if (!err) { -+ bbot = au_sbbot(sb); -+ if (l <= bbot) -+ err = sysaufs_si_br(seq, sb, (aufs_bindex_t)l, idx); -+ else -+ err = -ENOENT; -+ } -+ -+out_seq: -+ if (!err) { -+ err = seq->count; -+ /* sysfs limit */ -+ if (unlikely(err == PAGE_SIZE)) -+ err = -EFBIG; -+ } -+ au_kfree_rcu(seq); -+out_unlock: -+ si_read_unlock(sb); -+out: -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int au_brinfo(struct super_block *sb, union aufs_brinfo __user *arg) -+{ -+ int err; -+ int16_t brid; -+ aufs_bindex_t bindex, bbot; -+ size_t sz; -+ char *buf; -+ struct seq_file *seq; -+ struct au_branch *br; -+ -+ si_read_lock(sb, AuLock_FLUSH); -+ bbot = au_sbbot(sb); -+ err = bbot + 1; -+ if (!arg) -+ goto out; -+ -+ err = -ENOMEM; -+ buf = (void *)__get_free_page(GFP_NOFS); -+ if (unlikely(!buf)) -+ goto out; -+ -+ seq = au_seq(buf, PAGE_SIZE); -+ err = PTR_ERR(seq); -+ if (IS_ERR(seq)) -+ goto out_buf; -+ -+ sz = sizeof(*arg) - offsetof(union aufs_brinfo, path); -+ for (bindex = 0; bindex <= bbot; bindex++, arg++) { -+ /* VERIFY_WRITE */ -+ err = !access_ok(arg, sizeof(*arg)); -+ if (unlikely(err)) -+ break; -+ -+ br = au_sbr(sb, bindex); -+ brid = br->br_id; -+ BUILD_BUG_ON(sizeof(brid) != sizeof(arg->id)); -+ err = __put_user(brid, &arg->id); -+ if (unlikely(err)) -+ break; -+ -+ BUILD_BUG_ON(sizeof(br->br_perm) != sizeof(arg->perm)); -+ err = __put_user(br->br_perm, &arg->perm); -+ if (unlikely(err)) -+ break; -+ -+ err = au_seq_path(seq, &br->br_path); -+ if (unlikely(err)) -+ break; -+ seq_putc(seq, '\0'); -+ if (!seq_has_overflowed(seq)) { -+ err = copy_to_user(arg->path, seq->buf, seq->count); -+ seq->count = 0; -+ if (unlikely(err)) -+ break; -+ } else { -+ err = -E2BIG; -+ goto out_seq; -+ } -+ } -+ if (unlikely(err)) -+ err = -EFAULT; -+ -+out_seq: -+ au_kfree_rcu(seq); -+out_buf: -+ free_page((unsigned long)buf); -+out: -+ si_read_unlock(sb); -+ return err; -+} -+ -+long au_brinfo_ioctl(struct file *file, unsigned long arg) -+{ -+ return au_brinfo(file->f_path.dentry->d_sb, (void __user *)arg); -+} -+ -+#ifdef CONFIG_COMPAT -+long au_brinfo_compat_ioctl(struct file *file, unsigned long arg) -+{ -+ return au_brinfo(file->f_path.dentry->d_sb, compat_ptr(arg)); -+} -+#endif -+ -+/* ---------------------------------------------------------------------- */ -+ -+void sysaufs_br_init(struct au_branch *br) -+{ -+ int i; -+ struct au_brsysfs *br_sysfs; -+ struct attribute *attr; -+ -+ br_sysfs = br->br_sysfs; -+ for (i = 0; i < ARRAY_SIZE(br->br_sysfs); i++) { -+ attr = &br_sysfs->attr; -+ sysfs_attr_init(attr); -+ attr->name = br_sysfs->name; -+ attr->mode = 0444; -+ br_sysfs++; -+ } -+} -+ -+void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex) -+{ -+ struct au_branch *br; -+ struct kobject *kobj; -+ struct au_brsysfs *br_sysfs; -+ int i; -+ aufs_bindex_t bbot; -+ -+ if (!sysaufs_brs) -+ return; -+ -+ kobj = &au_sbi(sb)->si_kobj; -+ bbot = au_sbbot(sb); -+ for (; bindex <= bbot; bindex++) { -+ br = au_sbr(sb, bindex); -+ br_sysfs = br->br_sysfs; -+ for (i = 0; i < ARRAY_SIZE(br->br_sysfs); i++) { -+ sysfs_remove_file(kobj, &br_sysfs->attr); -+ br_sysfs++; -+ } -+ } -+} -+ -+void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex) -+{ -+ int err, i; -+ aufs_bindex_t bbot; -+ struct kobject *kobj; -+ struct au_branch *br; -+ struct au_brsysfs *br_sysfs; -+ -+ if (!sysaufs_brs) -+ return; -+ -+ kobj = &au_sbi(sb)->si_kobj; -+ bbot = au_sbbot(sb); -+ for (; bindex <= bbot; bindex++) { -+ br = au_sbr(sb, bindex); -+ br_sysfs = br->br_sysfs; -+ snprintf(br_sysfs[AuBrSysfs_BR].name, sizeof(br_sysfs->name), -+ SysaufsBr_PREFIX "%d", bindex); -+ snprintf(br_sysfs[AuBrSysfs_BRID].name, sizeof(br_sysfs->name), -+ SysaufsBrid_PREFIX "%d", bindex); -+ for (i = 0; i < ARRAY_SIZE(br->br_sysfs); i++) { -+ err = sysfs_create_file(kobj, &br_sysfs->attr); -+ if (unlikely(err)) -+ pr_warn("failed %s under sysfs(%d)\n", -+ br_sysfs->name, err); -+ br_sysfs++; -+ } -+ } -+} -diff -Nurp linux-5.6.3/fs/aufs/sysrq.c linux-5.6.3-aufs/fs/aufs/sysrq.c ---- linux-5.6.3/fs/aufs/sysrq.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/sysrq.c 2020-04-10 12:40:52.192049502 +0300 -@@ -0,0 +1,136 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * magic sysrq handler -+ */ -+ -+/* #include */ -+#include -+#include "aufs.h" -+ -+/* ---------------------------------------------------------------------- */ -+ -+static void sysrq_sb(struct super_block *sb) -+{ -+ char *plevel; -+ struct au_sbinfo *sbinfo; -+ struct file *file; -+ struct hlist_bl_head *files; -+ struct hlist_bl_node *pos; -+ struct au_finfo *finfo; -+ struct inode *i; -+ -+ plevel = au_plevel; -+ au_plevel = KERN_WARNING; -+ -+ /* since we define pr_fmt, call printk directly */ -+#define pr(str) printk(KERN_WARNING AUFS_NAME ": " str) -+ -+ sbinfo = au_sbi(sb); -+ printk(KERN_WARNING "si=%lx\n", sysaufs_si_id(sbinfo)); -+ pr("superblock\n"); -+ au_dpri_sb(sb); -+ -+#if 0 /* reserved */ -+ do { -+ int err, i, j, ndentry; -+ struct au_dcsub_pages dpages; -+ struct au_dpage *dpage; -+ -+ err = au_dpages_init(&dpages, GFP_ATOMIC); -+ if (unlikely(err)) -+ break; -+ err = au_dcsub_pages(&dpages, sb->s_root, NULL, NULL); -+ if (!err) -+ for (i = 0; i < dpages.ndpage; i++) { -+ dpage = dpages.dpages + i; -+ ndentry = dpage->ndentry; -+ for (j = 0; j < ndentry; j++) -+ au_dpri_dentry(dpage->dentries[j]); -+ } -+ au_dpages_free(&dpages); -+ } while (0); -+#endif -+ -+ pr("isolated inode\n"); -+ spin_lock(&sb->s_inode_list_lock); -+ list_for_each_entry(i, &sb->s_inodes, i_sb_list) { -+ spin_lock(&i->i_lock); -+ if (hlist_empty(&i->i_dentry)) -+ au_dpri_inode(i); -+ spin_unlock(&i->i_lock); -+ } -+ spin_unlock(&sb->s_inode_list_lock); -+ -+ pr("files\n"); -+ files = &au_sbi(sb)->si_files; -+ hlist_bl_lock(files); -+ hlist_bl_for_each_entry(finfo, pos, files, fi_hlist) { -+ umode_t mode; -+ -+ file = finfo->fi_file; -+ mode = file_inode(file)->i_mode; -+ if (!special_file(mode)) -+ au_dpri_file(file); -+ } -+ hlist_bl_unlock(files); -+ pr("done\n"); -+ -+#undef pr -+ au_plevel = plevel; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* module parameter */ -+static char *aufs_sysrq_key = "a"; -+module_param_named(sysrq, aufs_sysrq_key, charp, 0444); -+MODULE_PARM_DESC(sysrq, "MagicSysRq key for " AUFS_NAME); -+ -+static void au_sysrq(int key __maybe_unused) -+{ -+ struct au_sbinfo *sbinfo; -+ struct hlist_bl_node *pos; -+ -+ lockdep_off(); -+ au_sbilist_lock(); -+ hlist_bl_for_each_entry(sbinfo, pos, &au_sbilist, si_list) -+ sysrq_sb(sbinfo->si_sb); -+ au_sbilist_unlock(); -+ lockdep_on(); -+} -+ -+static struct sysrq_key_op au_sysrq_op = { -+ .handler = au_sysrq, -+ .help_msg = "Aufs", -+ .action_msg = "Aufs", -+ .enable_mask = SYSRQ_ENABLE_DUMP -+}; -+ -+/* ---------------------------------------------------------------------- */ -+ -+int __init au_sysrq_init(void) -+{ -+ int err; -+ char key; -+ -+ err = -1; -+ key = *aufs_sysrq_key; -+ if ('a' <= key && key <= 'z') -+ err = register_sysrq_key(key, &au_sysrq_op); -+ if (unlikely(err)) -+ pr_err("err %d, sysrq=%c\n", err, key); -+ return err; -+} -+ -+void au_sysrq_fin(void) -+{ -+ int err; -+ -+ err = unregister_sysrq_key(*aufs_sysrq_key, &au_sysrq_op); -+ if (unlikely(err)) -+ pr_err("err %d (ignored)\n", err); -+} -diff -Nurp linux-5.6.3/fs/aufs/wbr_policy.c linux-5.6.3-aufs/fs/aufs/wbr_policy.c ---- linux-5.6.3/fs/aufs/wbr_policy.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/wbr_policy.c 2020-04-10 12:40:52.193049549 +0300 -@@ -0,0 +1,817 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * policies for selecting one among multiple writable branches -+ */ -+ -+#include -+#include "aufs.h" -+ -+/* subset of cpup_attr() */ -+static noinline_for_stack -+int au_cpdown_attr(struct path *h_path, struct dentry *h_src) -+{ -+ int err, sbits; -+ struct iattr ia; -+ struct inode *h_isrc; -+ -+ h_isrc = d_inode(h_src); -+ ia.ia_valid = ATTR_FORCE | ATTR_MODE | ATTR_UID | ATTR_GID; -+ ia.ia_mode = h_isrc->i_mode; -+ ia.ia_uid = h_isrc->i_uid; -+ ia.ia_gid = h_isrc->i_gid; -+ sbits = !!(ia.ia_mode & (S_ISUID | S_ISGID)); -+ au_cpup_attr_flags(d_inode(h_path->dentry), h_isrc->i_flags); -+ /* no delegation since it is just created */ -+ err = vfsub_sio_notify_change(h_path, &ia, /*delegated*/NULL); -+ -+ /* is this nfs only? */ -+ if (!err && sbits && au_test_nfs(h_path->dentry->d_sb)) { -+ ia.ia_valid = ATTR_FORCE | ATTR_MODE; -+ ia.ia_mode = h_isrc->i_mode; -+ err = vfsub_sio_notify_change(h_path, &ia, /*delegated*/NULL); -+ } -+ -+ return err; -+} -+ -+#define AuCpdown_PARENT_OPQ 1 -+#define AuCpdown_WHED (1 << 1) -+#define AuCpdown_MADE_DIR (1 << 2) -+#define AuCpdown_DIROPQ (1 << 3) -+#define au_ftest_cpdown(flags, name) ((flags) & AuCpdown_##name) -+#define au_fset_cpdown(flags, name) \ -+ do { (flags) |= AuCpdown_##name; } while (0) -+#define au_fclr_cpdown(flags, name) \ -+ do { (flags) &= ~AuCpdown_##name; } while (0) -+ -+static int au_cpdown_dir_opq(struct dentry *dentry, aufs_bindex_t bdst, -+ unsigned int *flags) -+{ -+ int err; -+ struct dentry *opq_dentry; -+ -+ opq_dentry = au_diropq_create(dentry, bdst); -+ err = PTR_ERR(opq_dentry); -+ if (IS_ERR(opq_dentry)) -+ goto out; -+ dput(opq_dentry); -+ au_fset_cpdown(*flags, DIROPQ); -+ -+out: -+ return err; -+} -+ -+static int au_cpdown_dir_wh(struct dentry *dentry, struct dentry *h_parent, -+ struct inode *dir, aufs_bindex_t bdst) -+{ -+ int err; -+ struct path h_path; -+ struct au_branch *br; -+ -+ br = au_sbr(dentry->d_sb, bdst); -+ h_path.dentry = au_wh_lkup(h_parent, &dentry->d_name, br); -+ err = PTR_ERR(h_path.dentry); -+ if (IS_ERR(h_path.dentry)) -+ goto out; -+ -+ err = 0; -+ if (d_is_positive(h_path.dentry)) { -+ h_path.mnt = au_br_mnt(br); -+ err = au_wh_unlink_dentry(au_h_iptr(dir, bdst), &h_path, -+ dentry); -+ } -+ dput(h_path.dentry); -+ -+out: -+ return err; -+} -+ -+static int au_cpdown_dir(struct dentry *dentry, aufs_bindex_t bdst, -+ struct au_pin *pin, -+ struct dentry *h_parent, void *arg) -+{ -+ int err, rerr; -+ aufs_bindex_t bopq, btop; -+ struct path h_path; -+ struct dentry *parent; -+ struct inode *h_dir, *h_inode, *inode, *dir; -+ unsigned int *flags = arg; -+ -+ btop = au_dbtop(dentry); -+ /* dentry is di-locked */ -+ parent = dget_parent(dentry); -+ dir = d_inode(parent); -+ h_dir = d_inode(h_parent); -+ AuDebugOn(h_dir != au_h_iptr(dir, bdst)); -+ IMustLock(h_dir); -+ -+ err = au_lkup_neg(dentry, bdst, /*wh*/0); -+ if (unlikely(err < 0)) -+ goto out; -+ h_path.dentry = au_h_dptr(dentry, bdst); -+ h_path.mnt = au_sbr_mnt(dentry->d_sb, bdst); -+ err = vfsub_sio_mkdir(au_h_iptr(dir, bdst), &h_path, 0755); -+ if (unlikely(err)) -+ goto out_put; -+ au_fset_cpdown(*flags, MADE_DIR); -+ -+ bopq = au_dbdiropq(dentry); -+ au_fclr_cpdown(*flags, WHED); -+ au_fclr_cpdown(*flags, DIROPQ); -+ if (au_dbwh(dentry) == bdst) -+ au_fset_cpdown(*flags, WHED); -+ if (!au_ftest_cpdown(*flags, PARENT_OPQ) && bopq <= bdst) -+ au_fset_cpdown(*flags, PARENT_OPQ); -+ h_inode = d_inode(h_path.dentry); -+ inode_lock_nested(h_inode, AuLsc_I_CHILD); -+ if (au_ftest_cpdown(*flags, WHED)) { -+ err = au_cpdown_dir_opq(dentry, bdst, flags); -+ if (unlikely(err)) { -+ inode_unlock(h_inode); -+ goto out_dir; -+ } -+ } -+ -+ err = au_cpdown_attr(&h_path, au_h_dptr(dentry, btop)); -+ inode_unlock(h_inode); -+ if (unlikely(err)) -+ goto out_opq; -+ -+ if (au_ftest_cpdown(*flags, WHED)) { -+ err = au_cpdown_dir_wh(dentry, h_parent, dir, bdst); -+ if (unlikely(err)) -+ goto out_opq; -+ } -+ -+ inode = d_inode(dentry); -+ if (au_ibbot(inode) < bdst) -+ au_set_ibbot(inode, bdst); -+ au_set_h_iptr(inode, bdst, au_igrab(h_inode), -+ au_hi_flags(inode, /*isdir*/1)); -+ au_fhsm_wrote(dentry->d_sb, bdst, /*force*/0); -+ goto out; /* success */ -+ -+ /* revert */ -+out_opq: -+ if (au_ftest_cpdown(*flags, DIROPQ)) { -+ inode_lock_nested(h_inode, AuLsc_I_CHILD); -+ rerr = au_diropq_remove(dentry, bdst); -+ inode_unlock(h_inode); -+ if (unlikely(rerr)) { -+ AuIOErr("failed removing diropq for %pd b%d (%d)\n", -+ dentry, bdst, rerr); -+ err = -EIO; -+ goto out; -+ } -+ } -+out_dir: -+ if (au_ftest_cpdown(*flags, MADE_DIR)) { -+ rerr = vfsub_sio_rmdir(au_h_iptr(dir, bdst), &h_path); -+ if (unlikely(rerr)) { -+ AuIOErr("failed removing %pd b%d (%d)\n", -+ dentry, bdst, rerr); -+ err = -EIO; -+ } -+ } -+out_put: -+ au_set_h_dptr(dentry, bdst, NULL); -+ if (au_dbbot(dentry) == bdst) -+ au_update_dbbot(dentry); -+out: -+ dput(parent); -+ return err; -+} -+ -+int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst) -+{ -+ int err; -+ unsigned int flags; -+ -+ flags = 0; -+ err = au_cp_dirs(dentry, bdst, au_cpdown_dir, &flags); -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* policies for create */ -+ -+int au_wbr_nonopq(struct dentry *dentry, aufs_bindex_t bindex) -+{ -+ int err, i, j, ndentry; -+ aufs_bindex_t bopq; -+ struct au_dcsub_pages dpages; -+ struct au_dpage *dpage; -+ struct dentry **dentries, *parent, *d; -+ -+ err = au_dpages_init(&dpages, GFP_NOFS); -+ if (unlikely(err)) -+ goto out; -+ parent = dget_parent(dentry); -+ err = au_dcsub_pages_rev_aufs(&dpages, parent, /*do_include*/0); -+ if (unlikely(err)) -+ goto out_free; -+ -+ err = bindex; -+ for (i = 0; i < dpages.ndpage; i++) { -+ dpage = dpages.dpages + i; -+ dentries = dpage->dentries; -+ ndentry = dpage->ndentry; -+ for (j = 0; j < ndentry; j++) { -+ d = dentries[j]; -+ di_read_lock_parent2(d, !AuLock_IR); -+ bopq = au_dbdiropq(d); -+ di_read_unlock(d, !AuLock_IR); -+ if (bopq >= 0 && bopq < err) -+ err = bopq; -+ } -+ } -+ -+out_free: -+ dput(parent); -+ au_dpages_free(&dpages); -+out: -+ return err; -+} -+ -+static int au_wbr_bu(struct super_block *sb, aufs_bindex_t bindex) -+{ -+ for (; bindex >= 0; bindex--) -+ if (!au_br_rdonly(au_sbr(sb, bindex))) -+ return bindex; -+ return -EROFS; -+} -+ -+/* top down parent */ -+static int au_wbr_create_tdp(struct dentry *dentry, -+ unsigned int flags __maybe_unused) -+{ -+ int err; -+ aufs_bindex_t btop, bindex; -+ struct super_block *sb; -+ struct dentry *parent, *h_parent; -+ -+ sb = dentry->d_sb; -+ btop = au_dbtop(dentry); -+ err = btop; -+ if (!au_br_rdonly(au_sbr(sb, btop))) -+ goto out; -+ -+ err = -EROFS; -+ parent = dget_parent(dentry); -+ for (bindex = au_dbtop(parent); bindex < btop; bindex++) { -+ h_parent = au_h_dptr(parent, bindex); -+ if (!h_parent || d_is_negative(h_parent)) -+ continue; -+ -+ if (!au_br_rdonly(au_sbr(sb, bindex))) { -+ err = bindex; -+ break; -+ } -+ } -+ dput(parent); -+ -+ /* bottom up here */ -+ if (unlikely(err < 0)) { -+ err = au_wbr_bu(sb, btop - 1); -+ if (err >= 0) -+ err = au_wbr_nonopq(dentry, err); -+ } -+ -+out: -+ AuDbg("b%d\n", err); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* an exception for the policy other than tdp */ -+static int au_wbr_create_exp(struct dentry *dentry) -+{ -+ int err; -+ aufs_bindex_t bwh, bdiropq; -+ struct dentry *parent; -+ -+ err = -1; -+ bwh = au_dbwh(dentry); -+ parent = dget_parent(dentry); -+ bdiropq = au_dbdiropq(parent); -+ if (bwh >= 0) { -+ if (bdiropq >= 0) -+ err = min(bdiropq, bwh); -+ else -+ err = bwh; -+ AuDbg("%d\n", err); -+ } else if (bdiropq >= 0) { -+ err = bdiropq; -+ AuDbg("%d\n", err); -+ } -+ dput(parent); -+ -+ if (err >= 0) -+ err = au_wbr_nonopq(dentry, err); -+ -+ if (err >= 0 && au_br_rdonly(au_sbr(dentry->d_sb, err))) -+ err = -1; -+ -+ AuDbg("%d\n", err); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* round robin */ -+static int au_wbr_create_init_rr(struct super_block *sb) -+{ -+ int err; -+ -+ err = au_wbr_bu(sb, au_sbbot(sb)); -+ atomic_set(&au_sbi(sb)->si_wbr_rr_next, -err); /* less important */ -+ /* smp_mb(); */ -+ -+ AuDbg("b%d\n", err); -+ return err; -+} -+ -+static int au_wbr_create_rr(struct dentry *dentry, unsigned int flags) -+{ -+ int err, nbr; -+ unsigned int u; -+ aufs_bindex_t bindex, bbot; -+ struct super_block *sb; -+ atomic_t *next; -+ -+ err = au_wbr_create_exp(dentry); -+ if (err >= 0) -+ goto out; -+ -+ sb = dentry->d_sb; -+ next = &au_sbi(sb)->si_wbr_rr_next; -+ bbot = au_sbbot(sb); -+ nbr = bbot + 1; -+ for (bindex = 0; bindex <= bbot; bindex++) { -+ if (!au_ftest_wbr(flags, DIR)) { -+ err = atomic_dec_return(next) + 1; -+ /* modulo for 0 is meaningless */ -+ if (unlikely(!err)) -+ err = atomic_dec_return(next) + 1; -+ } else -+ err = atomic_read(next); -+ AuDbg("%d\n", err); -+ u = err; -+ err = u % nbr; -+ AuDbg("%d\n", err); -+ if (!au_br_rdonly(au_sbr(sb, err))) -+ break; -+ err = -EROFS; -+ } -+ -+ if (err >= 0) -+ err = au_wbr_nonopq(dentry, err); -+ -+out: -+ AuDbg("%d\n", err); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* most free space */ -+static void au_mfs(struct dentry *dentry, struct dentry *parent) -+{ -+ struct super_block *sb; -+ struct au_branch *br; -+ struct au_wbr_mfs *mfs; -+ struct dentry *h_parent; -+ aufs_bindex_t bindex, bbot; -+ int err; -+ unsigned long long b, bavail; -+ struct path h_path; -+ /* reduce the stack usage */ -+ struct kstatfs *st; -+ -+ st = kmalloc(sizeof(*st), GFP_NOFS); -+ if (unlikely(!st)) { -+ AuWarn1("failed updating mfs(%d), ignored\n", -ENOMEM); -+ return; -+ } -+ -+ bavail = 0; -+ sb = dentry->d_sb; -+ mfs = &au_sbi(sb)->si_wbr_mfs; -+ MtxMustLock(&mfs->mfs_lock); -+ mfs->mfs_bindex = -EROFS; -+ mfs->mfsrr_bytes = 0; -+ if (!parent) { -+ bindex = 0; -+ bbot = au_sbbot(sb); -+ } else { -+ bindex = au_dbtop(parent); -+ bbot = au_dbtaildir(parent); -+ } -+ -+ for (; bindex <= bbot; bindex++) { -+ if (parent) { -+ h_parent = au_h_dptr(parent, bindex); -+ if (!h_parent || d_is_negative(h_parent)) -+ continue; -+ } -+ br = au_sbr(sb, bindex); -+ if (au_br_rdonly(br)) -+ continue; -+ -+ /* sb->s_root for NFS is unreliable */ -+ h_path.mnt = au_br_mnt(br); -+ h_path.dentry = h_path.mnt->mnt_root; -+ err = vfs_statfs(&h_path, st); -+ if (unlikely(err)) { -+ AuWarn1("failed statfs, b%d, %d\n", bindex, err); -+ continue; -+ } -+ -+ /* when the available size is equal, select the lower one */ -+ BUILD_BUG_ON(sizeof(b) < sizeof(st->f_bavail) -+ || sizeof(b) < sizeof(st->f_bsize)); -+ b = st->f_bavail * st->f_bsize; -+ br->br_wbr->wbr_bytes = b; -+ if (b >= bavail) { -+ bavail = b; -+ mfs->mfs_bindex = bindex; -+ mfs->mfs_jiffy = jiffies; -+ } -+ } -+ -+ mfs->mfsrr_bytes = bavail; -+ AuDbg("b%d\n", mfs->mfs_bindex); -+ au_kfree_rcu(st); -+} -+ -+static int au_wbr_create_mfs(struct dentry *dentry, unsigned int flags) -+{ -+ int err; -+ struct dentry *parent; -+ struct super_block *sb; -+ struct au_wbr_mfs *mfs; -+ -+ err = au_wbr_create_exp(dentry); -+ if (err >= 0) -+ goto out; -+ -+ sb = dentry->d_sb; -+ parent = NULL; -+ if (au_ftest_wbr(flags, PARENT)) -+ parent = dget_parent(dentry); -+ mfs = &au_sbi(sb)->si_wbr_mfs; -+ mutex_lock(&mfs->mfs_lock); -+ if (time_after(jiffies, mfs->mfs_jiffy + mfs->mfs_expire) -+ || mfs->mfs_bindex < 0 -+ || au_br_rdonly(au_sbr(sb, mfs->mfs_bindex))) -+ au_mfs(dentry, parent); -+ mutex_unlock(&mfs->mfs_lock); -+ err = mfs->mfs_bindex; -+ dput(parent); -+ -+ if (err >= 0) -+ err = au_wbr_nonopq(dentry, err); -+ -+out: -+ AuDbg("b%d\n", err); -+ return err; -+} -+ -+static int au_wbr_create_init_mfs(struct super_block *sb) -+{ -+ struct au_wbr_mfs *mfs; -+ -+ mfs = &au_sbi(sb)->si_wbr_mfs; -+ mutex_init(&mfs->mfs_lock); -+ mfs->mfs_jiffy = 0; -+ mfs->mfs_bindex = -EROFS; -+ -+ return 0; -+} -+ -+static int au_wbr_create_fin_mfs(struct super_block *sb __maybe_unused) -+{ -+ mutex_destroy(&au_sbi(sb)->si_wbr_mfs.mfs_lock); -+ return 0; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* top down regardless parent, and then mfs */ -+static int au_wbr_create_tdmfs(struct dentry *dentry, -+ unsigned int flags __maybe_unused) -+{ -+ int err; -+ aufs_bindex_t bwh, btail, bindex, bfound, bmfs; -+ unsigned long long watermark; -+ struct super_block *sb; -+ struct au_wbr_mfs *mfs; -+ struct au_branch *br; -+ struct dentry *parent; -+ -+ sb = dentry->d_sb; -+ mfs = &au_sbi(sb)->si_wbr_mfs; -+ mutex_lock(&mfs->mfs_lock); -+ if (time_after(jiffies, mfs->mfs_jiffy + mfs->mfs_expire) -+ || mfs->mfs_bindex < 0) -+ au_mfs(dentry, /*parent*/NULL); -+ watermark = mfs->mfsrr_watermark; -+ bmfs = mfs->mfs_bindex; -+ mutex_unlock(&mfs->mfs_lock); -+ -+ /* another style of au_wbr_create_exp() */ -+ bwh = au_dbwh(dentry); -+ parent = dget_parent(dentry); -+ btail = au_dbtaildir(parent); -+ if (bwh >= 0 && bwh < btail) -+ btail = bwh; -+ -+ err = au_wbr_nonopq(dentry, btail); -+ if (unlikely(err < 0)) -+ goto out; -+ btail = err; -+ bfound = -1; -+ for (bindex = 0; bindex <= btail; bindex++) { -+ br = au_sbr(sb, bindex); -+ if (au_br_rdonly(br)) -+ continue; -+ if (br->br_wbr->wbr_bytes > watermark) { -+ bfound = bindex; -+ break; -+ } -+ } -+ err = bfound; -+ if (err < 0) -+ err = bmfs; -+ -+out: -+ dput(parent); -+ AuDbg("b%d\n", err); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* most free space and then round robin */ -+static int au_wbr_create_mfsrr(struct dentry *dentry, unsigned int flags) -+{ -+ int err; -+ struct au_wbr_mfs *mfs; -+ -+ err = au_wbr_create_mfs(dentry, flags); -+ if (err >= 0) { -+ mfs = &au_sbi(dentry->d_sb)->si_wbr_mfs; -+ mutex_lock(&mfs->mfs_lock); -+ if (mfs->mfsrr_bytes < mfs->mfsrr_watermark) -+ err = au_wbr_create_rr(dentry, flags); -+ mutex_unlock(&mfs->mfs_lock); -+ } -+ -+ AuDbg("b%d\n", err); -+ return err; -+} -+ -+static int au_wbr_create_init_mfsrr(struct super_block *sb) -+{ -+ int err; -+ -+ au_wbr_create_init_mfs(sb); /* ignore */ -+ err = au_wbr_create_init_rr(sb); -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* top down parent and most free space */ -+static int au_wbr_create_pmfs(struct dentry *dentry, unsigned int flags) -+{ -+ int err, e2; -+ unsigned long long b; -+ aufs_bindex_t bindex, btop, bbot; -+ struct super_block *sb; -+ struct dentry *parent, *h_parent; -+ struct au_branch *br; -+ -+ err = au_wbr_create_tdp(dentry, flags); -+ if (unlikely(err < 0)) -+ goto out; -+ parent = dget_parent(dentry); -+ btop = au_dbtop(parent); -+ bbot = au_dbtaildir(parent); -+ if (btop == bbot) -+ goto out_parent; /* success */ -+ -+ e2 = au_wbr_create_mfs(dentry, flags); -+ if (e2 < 0) -+ goto out_parent; /* success */ -+ -+ /* when the available size is equal, select upper one */ -+ sb = dentry->d_sb; -+ br = au_sbr(sb, err); -+ b = br->br_wbr->wbr_bytes; -+ AuDbg("b%d, %llu\n", err, b); -+ -+ for (bindex = btop; bindex <= bbot; bindex++) { -+ h_parent = au_h_dptr(parent, bindex); -+ if (!h_parent || d_is_negative(h_parent)) -+ continue; -+ -+ br = au_sbr(sb, bindex); -+ if (!au_br_rdonly(br) && br->br_wbr->wbr_bytes > b) { -+ b = br->br_wbr->wbr_bytes; -+ err = bindex; -+ AuDbg("b%d, %llu\n", err, b); -+ } -+ } -+ -+ if (err >= 0) -+ err = au_wbr_nonopq(dentry, err); -+ -+out_parent: -+ dput(parent); -+out: -+ AuDbg("b%d\n", err); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * - top down parent -+ * - most free space with parent -+ * - most free space round-robin regardless parent -+ */ -+static int au_wbr_create_pmfsrr(struct dentry *dentry, unsigned int flags) -+{ -+ int err; -+ unsigned long long watermark; -+ struct super_block *sb; -+ struct au_branch *br; -+ struct au_wbr_mfs *mfs; -+ -+ err = au_wbr_create_pmfs(dentry, flags | AuWbr_PARENT); -+ if (unlikely(err < 0)) -+ goto out; -+ -+ sb = dentry->d_sb; -+ br = au_sbr(sb, err); -+ mfs = &au_sbi(sb)->si_wbr_mfs; -+ mutex_lock(&mfs->mfs_lock); -+ watermark = mfs->mfsrr_watermark; -+ mutex_unlock(&mfs->mfs_lock); -+ if (br->br_wbr->wbr_bytes < watermark) -+ /* regardless the parent dir */ -+ err = au_wbr_create_mfsrr(dentry, flags); -+ -+out: -+ AuDbg("b%d\n", err); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* policies for copyup */ -+ -+/* top down parent */ -+static int au_wbr_copyup_tdp(struct dentry *dentry) -+{ -+ return au_wbr_create_tdp(dentry, /*flags, anything is ok*/0); -+} -+ -+/* bottom up parent */ -+static int au_wbr_copyup_bup(struct dentry *dentry) -+{ -+ int err; -+ aufs_bindex_t bindex, btop; -+ struct dentry *parent, *h_parent; -+ struct super_block *sb; -+ -+ err = -EROFS; -+ sb = dentry->d_sb; -+ parent = dget_parent(dentry); -+ btop = au_dbtop(parent); -+ for (bindex = au_dbtop(dentry); bindex >= btop; bindex--) { -+ h_parent = au_h_dptr(parent, bindex); -+ if (!h_parent || d_is_negative(h_parent)) -+ continue; -+ -+ if (!au_br_rdonly(au_sbr(sb, bindex))) { -+ err = bindex; -+ break; -+ } -+ } -+ dput(parent); -+ -+ /* bottom up here */ -+ if (unlikely(err < 0)) -+ err = au_wbr_bu(sb, btop - 1); -+ -+ AuDbg("b%d\n", err); -+ return err; -+} -+ -+/* bottom up */ -+int au_wbr_do_copyup_bu(struct dentry *dentry, aufs_bindex_t btop) -+{ -+ int err; -+ -+ err = au_wbr_bu(dentry->d_sb, btop); -+ AuDbg("b%d\n", err); -+ if (err > btop) -+ err = au_wbr_nonopq(dentry, err); -+ -+ AuDbg("b%d\n", err); -+ return err; -+} -+ -+static int au_wbr_copyup_bu(struct dentry *dentry) -+{ -+ int err; -+ aufs_bindex_t btop; -+ -+ btop = au_dbtop(dentry); -+ err = au_wbr_do_copyup_bu(dentry, btop); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct au_wbr_copyup_operations au_wbr_copyup_ops[] = { -+ [AuWbrCopyup_TDP] = { -+ .copyup = au_wbr_copyup_tdp -+ }, -+ [AuWbrCopyup_BUP] = { -+ .copyup = au_wbr_copyup_bup -+ }, -+ [AuWbrCopyup_BU] = { -+ .copyup = au_wbr_copyup_bu -+ } -+}; -+ -+struct au_wbr_create_operations au_wbr_create_ops[] = { -+ [AuWbrCreate_TDP] = { -+ .create = au_wbr_create_tdp -+ }, -+ [AuWbrCreate_RR] = { -+ .create = au_wbr_create_rr, -+ .init = au_wbr_create_init_rr -+ }, -+ [AuWbrCreate_MFS] = { -+ .create = au_wbr_create_mfs, -+ .init = au_wbr_create_init_mfs, -+ .fin = au_wbr_create_fin_mfs -+ }, -+ [AuWbrCreate_MFSV] = { -+ .create = au_wbr_create_mfs, -+ .init = au_wbr_create_init_mfs, -+ .fin = au_wbr_create_fin_mfs -+ }, -+ [AuWbrCreate_MFSRR] = { -+ .create = au_wbr_create_mfsrr, -+ .init = au_wbr_create_init_mfsrr, -+ .fin = au_wbr_create_fin_mfs -+ }, -+ [AuWbrCreate_MFSRRV] = { -+ .create = au_wbr_create_mfsrr, -+ .init = au_wbr_create_init_mfsrr, -+ .fin = au_wbr_create_fin_mfs -+ }, -+ [AuWbrCreate_TDMFS] = { -+ .create = au_wbr_create_tdmfs, -+ .init = au_wbr_create_init_mfs, -+ .fin = au_wbr_create_fin_mfs -+ }, -+ [AuWbrCreate_TDMFSV] = { -+ .create = au_wbr_create_tdmfs, -+ .init = au_wbr_create_init_mfs, -+ .fin = au_wbr_create_fin_mfs -+ }, -+ [AuWbrCreate_PMFS] = { -+ .create = au_wbr_create_pmfs, -+ .init = au_wbr_create_init_mfs, -+ .fin = au_wbr_create_fin_mfs -+ }, -+ [AuWbrCreate_PMFSV] = { -+ .create = au_wbr_create_pmfs, -+ .init = au_wbr_create_init_mfs, -+ .fin = au_wbr_create_fin_mfs -+ }, -+ [AuWbrCreate_PMFSRR] = { -+ .create = au_wbr_create_pmfsrr, -+ .init = au_wbr_create_init_mfsrr, -+ .fin = au_wbr_create_fin_mfs -+ }, -+ [AuWbrCreate_PMFSRRV] = { -+ .create = au_wbr_create_pmfsrr, -+ .init = au_wbr_create_init_mfsrr, -+ .fin = au_wbr_create_fin_mfs -+ } -+}; -diff -Nurp linux-5.6.3/fs/aufs/vdir.c linux-5.6.3-aufs/fs/aufs/vdir.c ---- linux-5.6.3/fs/aufs/vdir.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/vdir.c 2020-04-10 12:40:52.193049549 +0300 -@@ -0,0 +1,883 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * virtual or vertical directory -+ */ -+ -+#include -+#include "aufs.h" -+ -+static unsigned int calc_size(int nlen) -+{ -+ return ALIGN(sizeof(struct au_vdir_de) + nlen, sizeof(ino_t)); -+} -+ -+static int set_deblk_end(union au_vdir_deblk_p *p, -+ union au_vdir_deblk_p *deblk_end) -+{ -+ if (calc_size(0) <= deblk_end->deblk - p->deblk) { -+ p->de->de_str.len = 0; -+ /* smp_mb(); */ -+ return 0; -+ } -+ return -1; /* error */ -+} -+ -+/* returns true or false */ -+static int is_deblk_end(union au_vdir_deblk_p *p, -+ union au_vdir_deblk_p *deblk_end) -+{ -+ if (calc_size(0) <= deblk_end->deblk - p->deblk) -+ return !p->de->de_str.len; -+ return 1; -+} -+ -+static unsigned char *last_deblk(struct au_vdir *vdir) -+{ -+ return vdir->vd_deblk[vdir->vd_nblk - 1]; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* estimate the appropriate size for name hash table */ -+unsigned int au_rdhash_est(loff_t sz) -+{ -+ unsigned int n; -+ -+ n = UINT_MAX; -+ sz >>= 10; -+ if (sz < n) -+ n = sz; -+ if (sz < AUFS_RDHASH_DEF) -+ n = AUFS_RDHASH_DEF; -+ /* pr_info("n %u\n", n); */ -+ return n; -+} -+ -+/* -+ * the allocated memory has to be freed by -+ * au_nhash_wh_free() or au_nhash_de_free(). -+ */ -+int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp) -+{ -+ struct hlist_head *head; -+ unsigned int u; -+ size_t sz; -+ -+ sz = sizeof(*nhash->nh_head) * num_hash; -+ head = kmalloc(sz, gfp); -+ if (head) { -+ nhash->nh_num = num_hash; -+ nhash->nh_head = head; -+ for (u = 0; u < num_hash; u++) -+ INIT_HLIST_HEAD(head++); -+ return 0; /* success */ -+ } -+ -+ return -ENOMEM; -+} -+ -+static void nhash_count(struct hlist_head *head) -+{ -+#if 0 /* debugging */ -+ unsigned long n; -+ struct hlist_node *pos; -+ -+ n = 0; -+ hlist_for_each(pos, head) -+ n++; -+ pr_info("%lu\n", n); -+#endif -+} -+ -+static void au_nhash_wh_do_free(struct hlist_head *head) -+{ -+ struct au_vdir_wh *pos; -+ struct hlist_node *node; -+ -+ hlist_for_each_entry_safe(pos, node, head, wh_hash) -+ au_kfree_rcu(pos); -+} -+ -+static void au_nhash_de_do_free(struct hlist_head *head) -+{ -+ struct au_vdir_dehstr *pos; -+ struct hlist_node *node; -+ -+ hlist_for_each_entry_safe(pos, node, head, hash) -+ au_cache_free_vdir_dehstr(pos); -+} -+ -+static void au_nhash_do_free(struct au_nhash *nhash, -+ void (*free)(struct hlist_head *head)) -+{ -+ unsigned int n; -+ struct hlist_head *head; -+ -+ n = nhash->nh_num; -+ if (!n) -+ return; -+ -+ head = nhash->nh_head; -+ while (n-- > 0) { -+ nhash_count(head); -+ free(head++); -+ } -+ au_kfree_try_rcu(nhash->nh_head); -+} -+ -+void au_nhash_wh_free(struct au_nhash *whlist) -+{ -+ au_nhash_do_free(whlist, au_nhash_wh_do_free); -+} -+ -+static void au_nhash_de_free(struct au_nhash *delist) -+{ -+ au_nhash_do_free(delist, au_nhash_de_do_free); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt, -+ int limit) -+{ -+ int num; -+ unsigned int u, n; -+ struct hlist_head *head; -+ struct au_vdir_wh *pos; -+ -+ num = 0; -+ n = whlist->nh_num; -+ head = whlist->nh_head; -+ for (u = 0; u < n; u++, head++) -+ hlist_for_each_entry(pos, head, wh_hash) -+ if (pos->wh_bindex == btgt && ++num > limit) -+ return 1; -+ return 0; -+} -+ -+static struct hlist_head *au_name_hash(struct au_nhash *nhash, -+ unsigned char *name, -+ unsigned int len) -+{ -+ unsigned int v; -+ /* const unsigned int magic_bit = 12; */ -+ -+ AuDebugOn(!nhash->nh_num || !nhash->nh_head); -+ -+ v = 0; -+ if (len > 8) -+ len = 8; -+ while (len--) -+ v += *name++; -+ /* v = hash_long(v, magic_bit); */ -+ v %= nhash->nh_num; -+ return nhash->nh_head + v; -+} -+ -+static int au_nhash_test_name(struct au_vdir_destr *str, const char *name, -+ int nlen) -+{ -+ return str->len == nlen && !memcmp(str->name, name, nlen); -+} -+ -+/* returns found or not */ -+int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen) -+{ -+ struct hlist_head *head; -+ struct au_vdir_wh *pos; -+ struct au_vdir_destr *str; -+ -+ head = au_name_hash(whlist, name, nlen); -+ hlist_for_each_entry(pos, head, wh_hash) { -+ str = &pos->wh_str; -+ AuDbg("%.*s\n", str->len, str->name); -+ if (au_nhash_test_name(str, name, nlen)) -+ return 1; -+ } -+ return 0; -+} -+ -+/* returns found(true) or not */ -+static int test_known(struct au_nhash *delist, char *name, int nlen) -+{ -+ struct hlist_head *head; -+ struct au_vdir_dehstr *pos; -+ struct au_vdir_destr *str; -+ -+ head = au_name_hash(delist, name, nlen); -+ hlist_for_each_entry(pos, head, hash) { -+ str = pos->str; -+ AuDbg("%.*s\n", str->len, str->name); -+ if (au_nhash_test_name(str, name, nlen)) -+ return 1; -+ } -+ return 0; -+} -+ -+static void au_shwh_init_wh(struct au_vdir_wh *wh, ino_t ino, -+ unsigned char d_type) -+{ -+#ifdef CONFIG_AUFS_SHWH -+ wh->wh_ino = ino; -+ wh->wh_type = d_type; -+#endif -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino, -+ unsigned int d_type, aufs_bindex_t bindex, -+ unsigned char shwh) -+{ -+ int err; -+ struct au_vdir_destr *str; -+ struct au_vdir_wh *wh; -+ -+ AuDbg("%.*s\n", nlen, name); -+ AuDebugOn(!whlist->nh_num || !whlist->nh_head); -+ -+ err = -ENOMEM; -+ wh = kmalloc(sizeof(*wh) + nlen, GFP_NOFS); -+ if (unlikely(!wh)) -+ goto out; -+ -+ err = 0; -+ wh->wh_bindex = bindex; -+ if (shwh) -+ au_shwh_init_wh(wh, ino, d_type); -+ str = &wh->wh_str; -+ str->len = nlen; -+ memcpy(str->name, name, nlen); -+ hlist_add_head(&wh->wh_hash, au_name_hash(whlist, name, nlen)); -+ /* smp_mb(); */ -+ -+out: -+ return err; -+} -+ -+static int append_deblk(struct au_vdir *vdir) -+{ -+ int err; -+ unsigned long ul; -+ const unsigned int deblk_sz = vdir->vd_deblk_sz; -+ union au_vdir_deblk_p p, deblk_end; -+ unsigned char **o; -+ -+ err = -ENOMEM; -+ o = au_krealloc(vdir->vd_deblk, sizeof(*o) * (vdir->vd_nblk + 1), -+ GFP_NOFS, /*may_shrink*/0); -+ if (unlikely(!o)) -+ goto out; -+ -+ vdir->vd_deblk = o; -+ p.deblk = kmalloc(deblk_sz, GFP_NOFS); -+ if (p.deblk) { -+ ul = vdir->vd_nblk++; -+ vdir->vd_deblk[ul] = p.deblk; -+ vdir->vd_last.ul = ul; -+ vdir->vd_last.p.deblk = p.deblk; -+ deblk_end.deblk = p.deblk + deblk_sz; -+ err = set_deblk_end(&p, &deblk_end); -+ } -+ -+out: -+ return err; -+} -+ -+static int append_de(struct au_vdir *vdir, char *name, int nlen, ino_t ino, -+ unsigned int d_type, struct au_nhash *delist) -+{ -+ int err; -+ unsigned int sz; -+ const unsigned int deblk_sz = vdir->vd_deblk_sz; -+ union au_vdir_deblk_p p, *room, deblk_end; -+ struct au_vdir_dehstr *dehstr; -+ -+ p.deblk = last_deblk(vdir); -+ deblk_end.deblk = p.deblk + deblk_sz; -+ room = &vdir->vd_last.p; -+ AuDebugOn(room->deblk < p.deblk || deblk_end.deblk <= room->deblk -+ || !is_deblk_end(room, &deblk_end)); -+ -+ sz = calc_size(nlen); -+ if (unlikely(sz > deblk_end.deblk - room->deblk)) { -+ err = append_deblk(vdir); -+ if (unlikely(err)) -+ goto out; -+ -+ p.deblk = last_deblk(vdir); -+ deblk_end.deblk = p.deblk + deblk_sz; -+ /* smp_mb(); */ -+ AuDebugOn(room->deblk != p.deblk); -+ } -+ -+ err = -ENOMEM; -+ dehstr = au_cache_alloc_vdir_dehstr(); -+ if (unlikely(!dehstr)) -+ goto out; -+ -+ dehstr->str = &room->de->de_str; -+ hlist_add_head(&dehstr->hash, au_name_hash(delist, name, nlen)); -+ room->de->de_ino = ino; -+ room->de->de_type = d_type; -+ room->de->de_str.len = nlen; -+ memcpy(room->de->de_str.name, name, nlen); -+ -+ err = 0; -+ room->deblk += sz; -+ if (unlikely(set_deblk_end(room, &deblk_end))) -+ err = append_deblk(vdir); -+ /* smp_mb(); */ -+ -+out: -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+void au_vdir_free(struct au_vdir *vdir) -+{ -+ unsigned char **deblk; -+ -+ deblk = vdir->vd_deblk; -+ while (vdir->vd_nblk--) -+ au_kfree_try_rcu(*deblk++); -+ au_kfree_try_rcu(vdir->vd_deblk); -+ au_cache_free_vdir(vdir); -+} -+ -+static struct au_vdir *alloc_vdir(struct file *file) -+{ -+ struct au_vdir *vdir; -+ struct super_block *sb; -+ int err; -+ -+ sb = file->f_path.dentry->d_sb; -+ SiMustAnyLock(sb); -+ -+ err = -ENOMEM; -+ vdir = au_cache_alloc_vdir(); -+ if (unlikely(!vdir)) -+ goto out; -+ -+ vdir->vd_deblk = kzalloc(sizeof(*vdir->vd_deblk), GFP_NOFS); -+ if (unlikely(!vdir->vd_deblk)) -+ goto out_free; -+ -+ vdir->vd_deblk_sz = au_sbi(sb)->si_rdblk; -+ if (!vdir->vd_deblk_sz) { -+ /* estimate the appropriate size for deblk */ -+ vdir->vd_deblk_sz = au_dir_size(file, /*dentry*/NULL); -+ /* pr_info("vd_deblk_sz %u\n", vdir->vd_deblk_sz); */ -+ } -+ vdir->vd_nblk = 0; -+ vdir->vd_version = 0; -+ vdir->vd_jiffy = 0; -+ err = append_deblk(vdir); -+ if (!err) -+ return vdir; /* success */ -+ -+ au_kfree_try_rcu(vdir->vd_deblk); -+ -+out_free: -+ au_cache_free_vdir(vdir); -+out: -+ vdir = ERR_PTR(err); -+ return vdir; -+} -+ -+static int reinit_vdir(struct au_vdir *vdir) -+{ -+ int err; -+ union au_vdir_deblk_p p, deblk_end; -+ -+ while (vdir->vd_nblk > 1) { -+ au_kfree_try_rcu(vdir->vd_deblk[vdir->vd_nblk - 1]); -+ /* vdir->vd_deblk[vdir->vd_nblk - 1] = NULL; */ -+ vdir->vd_nblk--; -+ } -+ p.deblk = vdir->vd_deblk[0]; -+ deblk_end.deblk = p.deblk + vdir->vd_deblk_sz; -+ err = set_deblk_end(&p, &deblk_end); -+ /* keep vd_dblk_sz */ -+ vdir->vd_last.ul = 0; -+ vdir->vd_last.p.deblk = vdir->vd_deblk[0]; -+ vdir->vd_version = 0; -+ vdir->vd_jiffy = 0; -+ /* smp_mb(); */ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+#define AuFillVdir_CALLED 1 -+#define AuFillVdir_WHABLE (1 << 1) -+#define AuFillVdir_SHWH (1 << 2) -+#define au_ftest_fillvdir(flags, name) ((flags) & AuFillVdir_##name) -+#define au_fset_fillvdir(flags, name) \ -+ do { (flags) |= AuFillVdir_##name; } while (0) -+#define au_fclr_fillvdir(flags, name) \ -+ do { (flags) &= ~AuFillVdir_##name; } while (0) -+ -+#ifndef CONFIG_AUFS_SHWH -+#undef AuFillVdir_SHWH -+#define AuFillVdir_SHWH 0 -+#endif -+ -+struct fillvdir_arg { -+ struct dir_context ctx; -+ struct file *file; -+ struct au_vdir *vdir; -+ struct au_nhash delist; -+ struct au_nhash whlist; -+ aufs_bindex_t bindex; -+ unsigned int flags; -+ int err; -+}; -+ -+static int fillvdir(struct dir_context *ctx, const char *__name, int nlen, -+ loff_t offset __maybe_unused, u64 h_ino, -+ unsigned int d_type) -+{ -+ struct fillvdir_arg *arg = container_of(ctx, struct fillvdir_arg, ctx); -+ char *name = (void *)__name; -+ struct super_block *sb; -+ ino_t ino; -+ const unsigned char shwh = !!au_ftest_fillvdir(arg->flags, SHWH); -+ -+ arg->err = 0; -+ sb = arg->file->f_path.dentry->d_sb; -+ au_fset_fillvdir(arg->flags, CALLED); -+ /* smp_mb(); */ -+ if (nlen <= AUFS_WH_PFX_LEN -+ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) { -+ if (test_known(&arg->delist, name, nlen) -+ || au_nhash_test_known_wh(&arg->whlist, name, nlen)) -+ goto out; /* already exists or whiteouted */ -+ -+ arg->err = au_ino(sb, arg->bindex, h_ino, d_type, &ino); -+ if (!arg->err) { -+ if (unlikely(nlen > AUFS_MAX_NAMELEN)) -+ d_type = DT_UNKNOWN; -+ arg->err = append_de(arg->vdir, name, nlen, ino, -+ d_type, &arg->delist); -+ } -+ } else if (au_ftest_fillvdir(arg->flags, WHABLE)) { -+ name += AUFS_WH_PFX_LEN; -+ nlen -= AUFS_WH_PFX_LEN; -+ if (au_nhash_test_known_wh(&arg->whlist, name, nlen)) -+ goto out; /* already whiteouted */ -+ -+ ino = 0; /* just to suppress a warning */ -+ if (shwh) -+ arg->err = au_wh_ino(sb, arg->bindex, h_ino, d_type, -+ &ino); -+ if (!arg->err) { -+ if (nlen <= AUFS_MAX_NAMELEN + AUFS_WH_PFX_LEN) -+ d_type = DT_UNKNOWN; -+ arg->err = au_nhash_append_wh -+ (&arg->whlist, name, nlen, ino, d_type, -+ arg->bindex, shwh); -+ } -+ } -+ -+out: -+ if (!arg->err) -+ arg->vdir->vd_jiffy = jiffies; -+ /* smp_mb(); */ -+ AuTraceErr(arg->err); -+ return arg->err; -+} -+ -+static int au_handle_shwh(struct super_block *sb, struct au_vdir *vdir, -+ struct au_nhash *whlist, struct au_nhash *delist) -+{ -+#ifdef CONFIG_AUFS_SHWH -+ int err; -+ unsigned int nh, u; -+ struct hlist_head *head; -+ struct au_vdir_wh *pos; -+ struct hlist_node *n; -+ char *p, *o; -+ struct au_vdir_destr *destr; -+ -+ AuDebugOn(!au_opt_test(au_mntflags(sb), SHWH)); -+ -+ err = -ENOMEM; -+ o = p = (void *)__get_free_page(GFP_NOFS); -+ if (unlikely(!p)) -+ goto out; -+ -+ err = 0; -+ nh = whlist->nh_num; -+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN); -+ p += AUFS_WH_PFX_LEN; -+ for (u = 0; u < nh; u++) { -+ head = whlist->nh_head + u; -+ hlist_for_each_entry_safe(pos, n, head, wh_hash) { -+ destr = &pos->wh_str; -+ memcpy(p, destr->name, destr->len); -+ err = append_de(vdir, o, destr->len + AUFS_WH_PFX_LEN, -+ pos->wh_ino, pos->wh_type, delist); -+ if (unlikely(err)) -+ break; -+ } -+ } -+ -+ free_page((unsigned long)o); -+ -+out: -+ AuTraceErr(err); -+ return err; -+#else -+ return 0; -+#endif -+} -+ -+static int au_do_read_vdir(struct fillvdir_arg *arg) -+{ -+ int err; -+ unsigned int rdhash; -+ loff_t offset; -+ aufs_bindex_t bbot, bindex, btop; -+ unsigned char shwh; -+ struct file *hf, *file; -+ struct super_block *sb; -+ -+ file = arg->file; -+ sb = file->f_path.dentry->d_sb; -+ SiMustAnyLock(sb); -+ -+ rdhash = au_sbi(sb)->si_rdhash; -+ if (!rdhash) -+ rdhash = au_rdhash_est(au_dir_size(file, /*dentry*/NULL)); -+ err = au_nhash_alloc(&arg->delist, rdhash, GFP_NOFS); -+ if (unlikely(err)) -+ goto out; -+ err = au_nhash_alloc(&arg->whlist, rdhash, GFP_NOFS); -+ if (unlikely(err)) -+ goto out_delist; -+ -+ err = 0; -+ arg->flags = 0; -+ shwh = 0; -+ if (au_opt_test(au_mntflags(sb), SHWH)) { -+ shwh = 1; -+ au_fset_fillvdir(arg->flags, SHWH); -+ } -+ btop = au_fbtop(file); -+ bbot = au_fbbot_dir(file); -+ for (bindex = btop; !err && bindex <= bbot; bindex++) { -+ hf = au_hf_dir(file, bindex); -+ if (!hf) -+ continue; -+ -+ offset = vfsub_llseek(hf, 0, SEEK_SET); -+ err = offset; -+ if (unlikely(offset)) -+ break; -+ -+ arg->bindex = bindex; -+ au_fclr_fillvdir(arg->flags, WHABLE); -+ if (shwh -+ || (bindex != bbot -+ && au_br_whable(au_sbr_perm(sb, bindex)))) -+ au_fset_fillvdir(arg->flags, WHABLE); -+ do { -+ arg->err = 0; -+ au_fclr_fillvdir(arg->flags, CALLED); -+ /* smp_mb(); */ -+ err = vfsub_iterate_dir(hf, &arg->ctx); -+ if (err >= 0) -+ err = arg->err; -+ } while (!err && au_ftest_fillvdir(arg->flags, CALLED)); -+ -+ /* -+ * dir_relax() may be good for concurrency, but aufs should not -+ * use it since it will cause a lockdep problem. -+ */ -+ } -+ -+ if (!err && shwh) -+ err = au_handle_shwh(sb, arg->vdir, &arg->whlist, &arg->delist); -+ -+ au_nhash_wh_free(&arg->whlist); -+ -+out_delist: -+ au_nhash_de_free(&arg->delist); -+out: -+ return err; -+} -+ -+static int read_vdir(struct file *file, int may_read) -+{ -+ int err; -+ unsigned long expire; -+ unsigned char do_read; -+ struct fillvdir_arg arg = { -+ .ctx = { -+ .actor = fillvdir -+ } -+ }; -+ struct inode *inode; -+ struct au_vdir *vdir, *allocated; -+ -+ err = 0; -+ inode = file_inode(file); -+ IMustLock(inode); -+ IiMustWriteLock(inode); -+ SiMustAnyLock(inode->i_sb); -+ -+ allocated = NULL; -+ do_read = 0; -+ expire = au_sbi(inode->i_sb)->si_rdcache; -+ vdir = au_ivdir(inode); -+ if (!vdir) { -+ do_read = 1; -+ vdir = alloc_vdir(file); -+ err = PTR_ERR(vdir); -+ if (IS_ERR(vdir)) -+ goto out; -+ err = 0; -+ allocated = vdir; -+ } else if (may_read -+ && (!inode_eq_iversion(inode, vdir->vd_version) -+ || time_after(jiffies, vdir->vd_jiffy + expire))) { -+ do_read = 1; -+ err = reinit_vdir(vdir); -+ if (unlikely(err)) -+ goto out; -+ } -+ -+ if (!do_read) -+ return 0; /* success */ -+ -+ arg.file = file; -+ arg.vdir = vdir; -+ err = au_do_read_vdir(&arg); -+ if (!err) { -+ /* file->f_pos = 0; */ /* todo: ctx->pos? */ -+ vdir->vd_version = inode_query_iversion(inode); -+ vdir->vd_last.ul = 0; -+ vdir->vd_last.p.deblk = vdir->vd_deblk[0]; -+ if (allocated) -+ au_set_ivdir(inode, allocated); -+ } else if (allocated) -+ au_vdir_free(allocated); -+ -+out: -+ return err; -+} -+ -+static int copy_vdir(struct au_vdir *tgt, struct au_vdir *src) -+{ -+ int err, rerr; -+ unsigned long ul, n; -+ const unsigned int deblk_sz = src->vd_deblk_sz; -+ -+ AuDebugOn(tgt->vd_nblk != 1); -+ -+ err = -ENOMEM; -+ if (tgt->vd_nblk < src->vd_nblk) { -+ unsigned char **p; -+ -+ p = au_krealloc(tgt->vd_deblk, sizeof(*p) * src->vd_nblk, -+ GFP_NOFS, /*may_shrink*/0); -+ if (unlikely(!p)) -+ goto out; -+ tgt->vd_deblk = p; -+ } -+ -+ if (tgt->vd_deblk_sz != deblk_sz) { -+ unsigned char *p; -+ -+ tgt->vd_deblk_sz = deblk_sz; -+ p = au_krealloc(tgt->vd_deblk[0], deblk_sz, GFP_NOFS, -+ /*may_shrink*/1); -+ if (unlikely(!p)) -+ goto out; -+ tgt->vd_deblk[0] = p; -+ } -+ memcpy(tgt->vd_deblk[0], src->vd_deblk[0], deblk_sz); -+ tgt->vd_version = src->vd_version; -+ tgt->vd_jiffy = src->vd_jiffy; -+ -+ n = src->vd_nblk; -+ for (ul = 1; ul < n; ul++) { -+ tgt->vd_deblk[ul] = kmemdup(src->vd_deblk[ul], deblk_sz, -+ GFP_NOFS); -+ if (unlikely(!tgt->vd_deblk[ul])) -+ goto out; -+ tgt->vd_nblk++; -+ } -+ tgt->vd_nblk = n; -+ tgt->vd_last.ul = tgt->vd_last.ul; -+ tgt->vd_last.p.deblk = tgt->vd_deblk[tgt->vd_last.ul]; -+ tgt->vd_last.p.deblk += src->vd_last.p.deblk -+ - src->vd_deblk[src->vd_last.ul]; -+ /* smp_mb(); */ -+ return 0; /* success */ -+ -+out: -+ rerr = reinit_vdir(tgt); -+ BUG_ON(rerr); -+ return err; -+} -+ -+int au_vdir_init(struct file *file) -+{ -+ int err; -+ struct inode *inode; -+ struct au_vdir *vdir_cache, *allocated; -+ -+ /* test file->f_pos here instead of ctx->pos */ -+ err = read_vdir(file, !file->f_pos); -+ if (unlikely(err)) -+ goto out; -+ -+ allocated = NULL; -+ vdir_cache = au_fvdir_cache(file); -+ if (!vdir_cache) { -+ vdir_cache = alloc_vdir(file); -+ err = PTR_ERR(vdir_cache); -+ if (IS_ERR(vdir_cache)) -+ goto out; -+ allocated = vdir_cache; -+ } else if (!file->f_pos && vdir_cache->vd_version != file->f_version) { -+ /* test file->f_pos here instead of ctx->pos */ -+ err = reinit_vdir(vdir_cache); -+ if (unlikely(err)) -+ goto out; -+ } else -+ return 0; /* success */ -+ -+ inode = file_inode(file); -+ err = copy_vdir(vdir_cache, au_ivdir(inode)); -+ if (!err) { -+ file->f_version = inode_query_iversion(inode); -+ if (allocated) -+ au_set_fvdir_cache(file, allocated); -+ } else if (allocated) -+ au_vdir_free(allocated); -+ -+out: -+ return err; -+} -+ -+static loff_t calc_offset(struct au_vdir *vdir) -+{ -+ loff_t offset; -+ union au_vdir_deblk_p p; -+ -+ p.deblk = vdir->vd_deblk[vdir->vd_last.ul]; -+ offset = vdir->vd_last.p.deblk - p.deblk; -+ offset += vdir->vd_deblk_sz * vdir->vd_last.ul; -+ return offset; -+} -+ -+/* returns true or false */ -+static int seek_vdir(struct file *file, struct dir_context *ctx) -+{ -+ int valid; -+ unsigned int deblk_sz; -+ unsigned long ul, n; -+ loff_t offset; -+ union au_vdir_deblk_p p, deblk_end; -+ struct au_vdir *vdir_cache; -+ -+ valid = 1; -+ vdir_cache = au_fvdir_cache(file); -+ offset = calc_offset(vdir_cache); -+ AuDbg("offset %lld\n", offset); -+ if (ctx->pos == offset) -+ goto out; -+ -+ vdir_cache->vd_last.ul = 0; -+ vdir_cache->vd_last.p.deblk = vdir_cache->vd_deblk[0]; -+ if (!ctx->pos) -+ goto out; -+ -+ valid = 0; -+ deblk_sz = vdir_cache->vd_deblk_sz; -+ ul = div64_u64(ctx->pos, deblk_sz); -+ AuDbg("ul %lu\n", ul); -+ if (ul >= vdir_cache->vd_nblk) -+ goto out; -+ -+ n = vdir_cache->vd_nblk; -+ for (; ul < n; ul++) { -+ p.deblk = vdir_cache->vd_deblk[ul]; -+ deblk_end.deblk = p.deblk + deblk_sz; -+ offset = ul; -+ offset *= deblk_sz; -+ while (!is_deblk_end(&p, &deblk_end) && offset < ctx->pos) { -+ unsigned int l; -+ -+ l = calc_size(p.de->de_str.len); -+ offset += l; -+ p.deblk += l; -+ } -+ if (!is_deblk_end(&p, &deblk_end)) { -+ valid = 1; -+ vdir_cache->vd_last.ul = ul; -+ vdir_cache->vd_last.p = p; -+ break; -+ } -+ } -+ -+out: -+ /* smp_mb(); */ -+ if (!valid) -+ AuDbg("valid %d\n", !valid); -+ return valid; -+} -+ -+int au_vdir_fill_de(struct file *file, struct dir_context *ctx) -+{ -+ unsigned int l, deblk_sz; -+ union au_vdir_deblk_p deblk_end; -+ struct au_vdir *vdir_cache; -+ struct au_vdir_de *de; -+ -+ if (!seek_vdir(file, ctx)) -+ return 0; -+ -+ vdir_cache = au_fvdir_cache(file); -+ deblk_sz = vdir_cache->vd_deblk_sz; -+ while (1) { -+ deblk_end.deblk = vdir_cache->vd_deblk[vdir_cache->vd_last.ul]; -+ deblk_end.deblk += deblk_sz; -+ while (!is_deblk_end(&vdir_cache->vd_last.p, &deblk_end)) { -+ de = vdir_cache->vd_last.p.de; -+ AuDbg("%.*s, off%lld, i%lu, dt%d\n", -+ de->de_str.len, de->de_str.name, ctx->pos, -+ (unsigned long)de->de_ino, de->de_type); -+ if (unlikely(!dir_emit(ctx, de->de_str.name, -+ de->de_str.len, de->de_ino, -+ de->de_type))) { -+ /* todo: ignore the error caused by udba? */ -+ /* return err; */ -+ return 0; -+ } -+ -+ l = calc_size(de->de_str.len); -+ vdir_cache->vd_last.p.deblk += l; -+ ctx->pos += l; -+ } -+ if (vdir_cache->vd_last.ul < vdir_cache->vd_nblk - 1) { -+ vdir_cache->vd_last.ul++; -+ vdir_cache->vd_last.p.deblk -+ = vdir_cache->vd_deblk[vdir_cache->vd_last.ul]; -+ ctx->pos = deblk_sz * vdir_cache->vd_last.ul; -+ continue; -+ } -+ break; -+ } -+ -+ /* smp_mb(); */ -+ return 0; -+} -diff -Nurp linux-5.6.3/fs/aufs/vfsub.c linux-5.6.3-aufs/fs/aufs/vfsub.c ---- linux-5.6.3/fs/aufs/vfsub.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/vfsub.c 2020-04-10 12:40:52.193049549 +0300 -@@ -0,0 +1,889 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * sub-routines for VFS -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include "aufs.h" -+ -+#ifdef CONFIG_AUFS_BR_FUSE -+int vfsub_test_mntns(struct vfsmount *mnt, struct super_block *h_sb) -+{ -+ if (!au_test_fuse(h_sb) || !au_userns) -+ return 0; -+ -+ return is_current_mnt_ns(mnt) ? 0 : -EACCES; -+} -+#endif -+ -+int vfsub_sync_filesystem(struct super_block *h_sb, int wait) -+{ -+ int err; -+ -+ lockdep_off(); -+ down_read(&h_sb->s_umount); -+ err = __sync_filesystem(h_sb, wait); -+ up_read(&h_sb->s_umount); -+ lockdep_on(); -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+int vfsub_update_h_iattr(struct path *h_path, int *did) -+{ -+ int err; -+ struct kstat st; -+ struct super_block *h_sb; -+ -+ /* for remote fs, leave work for its getattr or d_revalidate */ -+ /* for bad i_attr fs, handle them in aufs_getattr() */ -+ /* still some fs may acquire i_mutex. we need to skip them */ -+ err = 0; -+ if (!did) -+ did = &err; -+ h_sb = h_path->dentry->d_sb; -+ *did = (!au_test_fs_remote(h_sb) && au_test_fs_refresh_iattr(h_sb)); -+ if (*did) -+ err = vfsub_getattr(h_path, &st); -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct file *vfsub_dentry_open(struct path *path, int flags) -+{ -+ struct file *file; -+ -+ file = dentry_open(path, flags /* | __FMODE_NONOTIFY */, -+ current_cred()); -+ if (!IS_ERR_OR_NULL(file) -+ && (file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) -+ i_readcount_inc(d_inode(path->dentry)); -+ -+ return file; -+} -+ -+struct file *vfsub_filp_open(const char *path, int oflags, int mode) -+{ -+ struct file *file; -+ -+ lockdep_off(); -+ file = filp_open(path, -+ oflags /* | __FMODE_NONOTIFY */, -+ mode); -+ lockdep_on(); -+ if (IS_ERR(file)) -+ goto out; -+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/ -+ -+out: -+ return file; -+} -+ -+/* -+ * Ideally this function should call VFS:do_last() in order to keep all its -+ * checkings. But it is very hard for aufs to regenerate several VFS internal -+ * structure such as nameidata. This is a second (or third) best approach. -+ * cf. linux/fs/namei.c:do_last(), lookup_open() and atomic_open(). -+ */ -+int vfsub_atomic_open(struct inode *dir, struct dentry *dentry, -+ struct vfsub_aopen_args *args) -+{ -+ int err; -+ struct au_branch *br = args->br; -+ struct file *file = args->file; -+ /* copied from linux/fs/namei.c:atomic_open() */ -+ struct dentry *const DENTRY_NOT_SET = (void *)-1UL; -+ -+ IMustLock(dir); -+ AuDebugOn(!dir->i_op->atomic_open); -+ -+ err = au_br_test_oflag(args->open_flag, br); -+ if (unlikely(err)) -+ goto out; -+ -+ au_lcnt_inc(&br->br_nfiles); -+ file->f_path.dentry = DENTRY_NOT_SET; -+ file->f_path.mnt = au_br_mnt(br); -+ AuDbg("%ps\n", dir->i_op->atomic_open); -+ err = dir->i_op->atomic_open(dir, dentry, file, args->open_flag, -+ args->create_mode); -+ if (unlikely(err < 0)) { -+ au_lcnt_dec(&br->br_nfiles); -+ goto out; -+ } -+ -+ /* temporary workaround for nfsv4 branch */ -+ if (au_test_nfs(dir->i_sb)) -+ nfs_mark_for_revalidate(dir); -+ -+ if (file->f_mode & FMODE_CREATED) -+ fsnotify_create(dir, dentry); -+ if (!(file->f_mode & FMODE_OPENED)) { -+ au_lcnt_dec(&br->br_nfiles); -+ goto out; -+ } -+ -+ /* todo: call VFS:may_open() here */ -+ /* todo: ima_file_check() too? */ -+ if (!err && (args->open_flag & __FMODE_EXEC)) -+ err = deny_write_access(file); -+ if (!err) -+ fsnotify_open(file); -+ else -+ au_lcnt_dec(&br->br_nfiles); -+ /* note that the file is created and still opened */ -+ -+out: -+ return err; -+} -+ -+int vfsub_kern_path(const char *name, unsigned int flags, struct path *path) -+{ -+ int err; -+ -+ err = kern_path(name, flags, path); -+ if (!err && d_is_positive(path->dentry)) -+ vfsub_update_h_iattr(path, /*did*/NULL); /*ignore*/ -+ return err; -+} -+ -+struct dentry *vfsub_lookup_one_len_unlocked(const char *name, -+ struct dentry *parent, int len) -+{ -+ struct path path = { -+ .mnt = NULL -+ }; -+ -+ path.dentry = lookup_one_len_unlocked(name, parent, len); -+ if (IS_ERR(path.dentry)) -+ goto out; -+ if (d_is_positive(path.dentry)) -+ vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/ -+ -+out: -+ AuTraceErrPtr(path.dentry); -+ return path.dentry; -+} -+ -+struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent, -+ int len) -+{ -+ struct path path = { -+ .mnt = NULL -+ }; -+ -+ /* VFS checks it too, but by WARN_ON_ONCE() */ -+ IMustLock(d_inode(parent)); -+ -+ path.dentry = lookup_one_len(name, parent, len); -+ if (IS_ERR(path.dentry)) -+ goto out; -+ if (d_is_positive(path.dentry)) -+ vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/ -+ -+out: -+ AuTraceErrPtr(path.dentry); -+ return path.dentry; -+} -+ -+void vfsub_call_lkup_one(void *args) -+{ -+ struct vfsub_lkup_one_args *a = args; -+ *a->errp = vfsub_lkup_one(a->name, a->parent); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1, -+ struct dentry *d2, struct au_hinode *hdir2) -+{ -+ struct dentry *d; -+ -+ lockdep_off(); -+ d = lock_rename(d1, d2); -+ lockdep_on(); -+ au_hn_suspend(hdir1); -+ if (hdir1 != hdir2) -+ au_hn_suspend(hdir2); -+ -+ return d; -+} -+ -+void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1, -+ struct dentry *d2, struct au_hinode *hdir2) -+{ -+ au_hn_resume(hdir1); -+ if (hdir1 != hdir2) -+ au_hn_resume(hdir2); -+ lockdep_off(); -+ unlock_rename(d1, d2); -+ lockdep_on(); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+int vfsub_create(struct inode *dir, struct path *path, int mode, bool want_excl) -+{ -+ int err; -+ struct dentry *d; -+ -+ IMustLock(dir); -+ -+ d = path->dentry; -+ path->dentry = d->d_parent; -+ err = security_path_mknod(path, d, mode, 0); -+ path->dentry = d; -+ if (unlikely(err)) -+ goto out; -+ -+ lockdep_off(); -+ err = vfs_create(dir, path->dentry, mode, want_excl); -+ lockdep_on(); -+ if (!err) { -+ struct path tmp = *path; -+ int did; -+ -+ vfsub_update_h_iattr(&tmp, &did); -+ if (did) { -+ tmp.dentry = path->dentry->d_parent; -+ vfsub_update_h_iattr(&tmp, /*did*/NULL); -+ } -+ /*ignore*/ -+ } -+ -+out: -+ return err; -+} -+ -+int vfsub_symlink(struct inode *dir, struct path *path, const char *symname) -+{ -+ int err; -+ struct dentry *d; -+ -+ IMustLock(dir); -+ -+ d = path->dentry; -+ path->dentry = d->d_parent; -+ err = security_path_symlink(path, d, symname); -+ path->dentry = d; -+ if (unlikely(err)) -+ goto out; -+ -+ lockdep_off(); -+ err = vfs_symlink(dir, path->dentry, symname); -+ lockdep_on(); -+ if (!err) { -+ struct path tmp = *path; -+ int did; -+ -+ vfsub_update_h_iattr(&tmp, &did); -+ if (did) { -+ tmp.dentry = path->dentry->d_parent; -+ vfsub_update_h_iattr(&tmp, /*did*/NULL); -+ } -+ /*ignore*/ -+ } -+ -+out: -+ return err; -+} -+ -+int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev) -+{ -+ int err; -+ struct dentry *d; -+ -+ IMustLock(dir); -+ -+ d = path->dentry; -+ path->dentry = d->d_parent; -+ err = security_path_mknod(path, d, mode, new_encode_dev(dev)); -+ path->dentry = d; -+ if (unlikely(err)) -+ goto out; -+ -+ lockdep_off(); -+ err = vfs_mknod(dir, path->dentry, mode, dev); -+ lockdep_on(); -+ if (!err) { -+ struct path tmp = *path; -+ int did; -+ -+ vfsub_update_h_iattr(&tmp, &did); -+ if (did) { -+ tmp.dentry = path->dentry->d_parent; -+ vfsub_update_h_iattr(&tmp, /*did*/NULL); -+ } -+ /*ignore*/ -+ } -+ -+out: -+ return err; -+} -+ -+static int au_test_nlink(struct inode *inode) -+{ -+ const unsigned int link_max = UINT_MAX >> 1; /* rough margin */ -+ -+ if (!au_test_fs_no_limit_nlink(inode->i_sb) -+ || inode->i_nlink < link_max) -+ return 0; -+ return -EMLINK; -+} -+ -+int vfsub_link(struct dentry *src_dentry, struct inode *dir, struct path *path, -+ struct inode **delegated_inode) -+{ -+ int err; -+ struct dentry *d; -+ -+ IMustLock(dir); -+ -+ err = au_test_nlink(d_inode(src_dentry)); -+ if (unlikely(err)) -+ return err; -+ -+ /* we don't call may_linkat() */ -+ d = path->dentry; -+ path->dentry = d->d_parent; -+ err = security_path_link(src_dentry, path, d); -+ path->dentry = d; -+ if (unlikely(err)) -+ goto out; -+ -+ lockdep_off(); -+ err = vfs_link(src_dentry, dir, path->dentry, delegated_inode); -+ lockdep_on(); -+ if (!err) { -+ struct path tmp = *path; -+ int did; -+ -+ /* fuse has different memory inode for the same inumber */ -+ vfsub_update_h_iattr(&tmp, &did); -+ if (did) { -+ tmp.dentry = path->dentry->d_parent; -+ vfsub_update_h_iattr(&tmp, /*did*/NULL); -+ tmp.dentry = src_dentry; -+ vfsub_update_h_iattr(&tmp, /*did*/NULL); -+ } -+ /*ignore*/ -+ } -+ -+out: -+ return err; -+} -+ -+int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry, -+ struct inode *dir, struct path *path, -+ struct inode **delegated_inode, unsigned int flags) -+{ -+ int err; -+ struct path tmp = { -+ .mnt = path->mnt -+ }; -+ struct dentry *d; -+ -+ IMustLock(dir); -+ IMustLock(src_dir); -+ -+ d = path->dentry; -+ path->dentry = d->d_parent; -+ tmp.dentry = src_dentry->d_parent; -+ err = security_path_rename(&tmp, src_dentry, path, d, /*flags*/0); -+ path->dentry = d; -+ if (unlikely(err)) -+ goto out; -+ -+ lockdep_off(); -+ err = vfs_rename(src_dir, src_dentry, dir, path->dentry, -+ delegated_inode, flags); -+ lockdep_on(); -+ if (!err) { -+ int did; -+ -+ tmp.dentry = d->d_parent; -+ vfsub_update_h_iattr(&tmp, &did); -+ if (did) { -+ tmp.dentry = src_dentry; -+ vfsub_update_h_iattr(&tmp, /*did*/NULL); -+ tmp.dentry = src_dentry->d_parent; -+ vfsub_update_h_iattr(&tmp, /*did*/NULL); -+ } -+ /*ignore*/ -+ } -+ -+out: -+ return err; -+} -+ -+int vfsub_mkdir(struct inode *dir, struct path *path, int mode) -+{ -+ int err; -+ struct dentry *d; -+ -+ IMustLock(dir); -+ -+ d = path->dentry; -+ path->dentry = d->d_parent; -+ err = security_path_mkdir(path, d, mode); -+ path->dentry = d; -+ if (unlikely(err)) -+ goto out; -+ -+ lockdep_off(); -+ err = vfs_mkdir(dir, path->dentry, mode); -+ lockdep_on(); -+ if (!err) { -+ struct path tmp = *path; -+ int did; -+ -+ vfsub_update_h_iattr(&tmp, &did); -+ if (did) { -+ tmp.dentry = path->dentry->d_parent; -+ vfsub_update_h_iattr(&tmp, /*did*/NULL); -+ } -+ /*ignore*/ -+ } -+ -+out: -+ return err; -+} -+ -+int vfsub_rmdir(struct inode *dir, struct path *path) -+{ -+ int err; -+ struct dentry *d; -+ -+ IMustLock(dir); -+ -+ d = path->dentry; -+ path->dentry = d->d_parent; -+ err = security_path_rmdir(path, d); -+ path->dentry = d; -+ if (unlikely(err)) -+ goto out; -+ -+ lockdep_off(); -+ err = vfs_rmdir(dir, path->dentry); -+ lockdep_on(); -+ if (!err) { -+ struct path tmp = { -+ .dentry = path->dentry->d_parent, -+ .mnt = path->mnt -+ }; -+ -+ vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/ -+ } -+ -+out: -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* todo: support mmap_sem? */ -+ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count, -+ loff_t *ppos) -+{ -+ ssize_t err; -+ -+ lockdep_off(); -+ err = vfs_read(file, ubuf, count, ppos); -+ lockdep_on(); -+ if (err >= 0) -+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/ -+ return err; -+} -+ -+/* todo: kernel_read()? */ -+ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count, -+ loff_t *ppos) -+{ -+ ssize_t err; -+ mm_segment_t oldfs; -+ union { -+ void *k; -+ char __user *u; -+ } buf; -+ -+ buf.k = kbuf; -+ oldfs = get_fs(); -+ set_fs(KERNEL_DS); -+ err = vfsub_read_u(file, buf.u, count, ppos); -+ set_fs(oldfs); -+ return err; -+} -+ -+ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count, -+ loff_t *ppos) -+{ -+ ssize_t err; -+ -+ lockdep_off(); -+ err = vfs_write(file, ubuf, count, ppos); -+ lockdep_on(); -+ if (err >= 0) -+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/ -+ return err; -+} -+ -+ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, loff_t *ppos) -+{ -+ ssize_t err; -+ mm_segment_t oldfs; -+ union { -+ void *k; -+ const char __user *u; -+ } buf; -+ -+ buf.k = kbuf; -+ oldfs = get_fs(); -+ set_fs(KERNEL_DS); -+ err = vfsub_write_u(file, buf.u, count, ppos); -+ set_fs(oldfs); -+ return err; -+} -+ -+int vfsub_flush(struct file *file, fl_owner_t id) -+{ -+ int err; -+ -+ err = 0; -+ if (file->f_op->flush) { -+ if (!au_test_nfs(file->f_path.dentry->d_sb)) -+ err = file->f_op->flush(file, id); -+ else { -+ lockdep_off(); -+ err = file->f_op->flush(file, id); -+ lockdep_on(); -+ } -+ if (!err) -+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); -+ /*ignore*/ -+ } -+ return err; -+} -+ -+int vfsub_iterate_dir(struct file *file, struct dir_context *ctx) -+{ -+ int err; -+ -+ AuDbg("%pD, ctx{%ps, %llu}\n", file, ctx->actor, ctx->pos); -+ -+ lockdep_off(); -+ err = iterate_dir(file, ctx); -+ lockdep_on(); -+ if (err >= 0) -+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/ -+ -+ return err; -+} -+ -+long vfsub_splice_to(struct file *in, loff_t *ppos, -+ struct pipe_inode_info *pipe, size_t len, -+ unsigned int flags) -+{ -+ long err; -+ -+ lockdep_off(); -+ err = do_splice_to(in, ppos, pipe, len, flags); -+ lockdep_on(); -+ file_accessed(in); -+ if (err >= 0) -+ vfsub_update_h_iattr(&in->f_path, /*did*/NULL); /*ignore*/ -+ return err; -+} -+ -+long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out, -+ loff_t *ppos, size_t len, unsigned int flags) -+{ -+ long err; -+ -+ lockdep_off(); -+ err = do_splice_from(pipe, out, ppos, len, flags); -+ lockdep_on(); -+ if (err >= 0) -+ vfsub_update_h_iattr(&out->f_path, /*did*/NULL); /*ignore*/ -+ return err; -+} -+ -+int vfsub_fsync(struct file *file, struct path *path, int datasync) -+{ -+ int err; -+ -+ /* file can be NULL */ -+ lockdep_off(); -+ err = vfs_fsync(file, datasync); -+ lockdep_on(); -+ if (!err) { -+ if (!path) { -+ AuDebugOn(!file); -+ path = &file->f_path; -+ } -+ vfsub_update_h_iattr(path, /*did*/NULL); /*ignore*/ -+ } -+ return err; -+} -+ -+/* cf. open.c:do_sys_truncate() and do_sys_ftruncate() */ -+int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr, -+ struct file *h_file) -+{ -+ int err; -+ struct inode *h_inode; -+ struct super_block *h_sb; -+ -+ if (!h_file) { -+ err = vfsub_truncate(h_path, length); -+ goto out; -+ } -+ -+ h_inode = d_inode(h_path->dentry); -+ h_sb = h_inode->i_sb; -+ lockdep_off(); -+ sb_start_write(h_sb); -+ lockdep_on(); -+ err = locks_verify_truncate(h_inode, h_file, length); -+ if (!err) -+ err = security_path_truncate(h_path); -+ if (!err) { -+ lockdep_off(); -+ err = do_truncate(h_path->dentry, length, attr, h_file); -+ lockdep_on(); -+ } -+ lockdep_off(); -+ sb_end_write(h_sb); -+ lockdep_on(); -+ -+out: -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct au_vfsub_mkdir_args { -+ int *errp; -+ struct inode *dir; -+ struct path *path; -+ int mode; -+}; -+ -+static void au_call_vfsub_mkdir(void *args) -+{ -+ struct au_vfsub_mkdir_args *a = args; -+ *a->errp = vfsub_mkdir(a->dir, a->path, a->mode); -+} -+ -+int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode) -+{ -+ int err, do_sio, wkq_err; -+ -+ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE); -+ if (!do_sio) { -+ lockdep_off(); -+ err = vfsub_mkdir(dir, path, mode); -+ lockdep_on(); -+ } else { -+ struct au_vfsub_mkdir_args args = { -+ .errp = &err, -+ .dir = dir, -+ .path = path, -+ .mode = mode -+ }; -+ wkq_err = au_wkq_wait(au_call_vfsub_mkdir, &args); -+ if (unlikely(wkq_err)) -+ err = wkq_err; -+ } -+ -+ return err; -+} -+ -+struct au_vfsub_rmdir_args { -+ int *errp; -+ struct inode *dir; -+ struct path *path; -+}; -+ -+static void au_call_vfsub_rmdir(void *args) -+{ -+ struct au_vfsub_rmdir_args *a = args; -+ *a->errp = vfsub_rmdir(a->dir, a->path); -+} -+ -+int vfsub_sio_rmdir(struct inode *dir, struct path *path) -+{ -+ int err, do_sio, wkq_err; -+ -+ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE); -+ if (!do_sio) { -+ lockdep_off(); -+ err = vfsub_rmdir(dir, path); -+ lockdep_on(); -+ } else { -+ struct au_vfsub_rmdir_args args = { -+ .errp = &err, -+ .dir = dir, -+ .path = path -+ }; -+ wkq_err = au_wkq_wait(au_call_vfsub_rmdir, &args); -+ if (unlikely(wkq_err)) -+ err = wkq_err; -+ } -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct notify_change_args { -+ int *errp; -+ struct path *path; -+ struct iattr *ia; -+ struct inode **delegated_inode; -+}; -+ -+static void call_notify_change(void *args) -+{ -+ struct notify_change_args *a = args; -+ struct inode *h_inode; -+ -+ h_inode = d_inode(a->path->dentry); -+ IMustLock(h_inode); -+ -+ *a->errp = -EPERM; -+ if (!IS_IMMUTABLE(h_inode) && !IS_APPEND(h_inode)) { -+ lockdep_off(); -+ *a->errp = notify_change(a->path->dentry, a->ia, -+ a->delegated_inode); -+ lockdep_on(); -+ if (!*a->errp) -+ vfsub_update_h_iattr(a->path, /*did*/NULL); /*ignore*/ -+ } -+ AuTraceErr(*a->errp); -+} -+ -+int vfsub_notify_change(struct path *path, struct iattr *ia, -+ struct inode **delegated_inode) -+{ -+ int err; -+ struct notify_change_args args = { -+ .errp = &err, -+ .path = path, -+ .ia = ia, -+ .delegated_inode = delegated_inode -+ }; -+ -+ call_notify_change(&args); -+ -+ return err; -+} -+ -+int vfsub_sio_notify_change(struct path *path, struct iattr *ia, -+ struct inode **delegated_inode) -+{ -+ int err, wkq_err; -+ struct notify_change_args args = { -+ .errp = &err, -+ .path = path, -+ .ia = ia, -+ .delegated_inode = delegated_inode -+ }; -+ -+ wkq_err = au_wkq_wait(call_notify_change, &args); -+ if (unlikely(wkq_err)) -+ err = wkq_err; -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct unlink_args { -+ int *errp; -+ struct inode *dir; -+ struct path *path; -+ struct inode **delegated_inode; -+}; -+ -+static void call_unlink(void *args) -+{ -+ struct unlink_args *a = args; -+ struct dentry *d = a->path->dentry; -+ struct inode *h_inode; -+ const int stop_sillyrename = (au_test_nfs(d->d_sb) -+ && au_dcount(d) == 1); -+ -+ IMustLock(a->dir); -+ -+ a->path->dentry = d->d_parent; -+ *a->errp = security_path_unlink(a->path, d); -+ a->path->dentry = d; -+ if (unlikely(*a->errp)) -+ return; -+ -+ if (!stop_sillyrename) -+ dget(d); -+ h_inode = NULL; -+ if (d_is_positive(d)) { -+ h_inode = d_inode(d); -+ ihold(h_inode); -+ } -+ -+ lockdep_off(); -+ *a->errp = vfs_unlink(a->dir, d, a->delegated_inode); -+ lockdep_on(); -+ if (!*a->errp) { -+ struct path tmp = { -+ .dentry = d->d_parent, -+ .mnt = a->path->mnt -+ }; -+ vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/ -+ } -+ -+ if (!stop_sillyrename) -+ dput(d); -+ if (h_inode) -+ iput(h_inode); -+ -+ AuTraceErr(*a->errp); -+} -+ -+/* -+ * @dir: must be locked. -+ * @dentry: target dentry. -+ */ -+int vfsub_unlink(struct inode *dir, struct path *path, -+ struct inode **delegated_inode, int force) -+{ -+ int err; -+ struct unlink_args args = { -+ .errp = &err, -+ .dir = dir, -+ .path = path, -+ .delegated_inode = delegated_inode -+ }; -+ -+ if (!force) -+ call_unlink(&args); -+ else { -+ int wkq_err; -+ -+ wkq_err = au_wkq_wait(call_unlink, &args); -+ if (unlikely(wkq_err)) -+ err = wkq_err; -+ } -+ -+ return err; -+} -diff -Nurp linux-5.6.3/fs/aufs/vfsub.h linux-5.6.3-aufs/fs/aufs/vfsub.h ---- linux-5.6.3/fs/aufs/vfsub.h 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/vfsub.h 2020-04-10 12:40:52.193049549 +0300 -@@ -0,0 +1,341 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * sub-routines for VFS -+ */ -+ -+#ifndef __AUFS_VFSUB_H__ -+#define __AUFS_VFSUB_H__ -+ -+#ifdef __KERNEL__ -+ -+#include -+#include -+#include -+#include -+#include "debug.h" -+ -+/* copied from linux/fs/internal.h */ -+/* todo: BAD approach!! */ -+extern void __mnt_drop_write(struct vfsmount *); -+extern struct file *alloc_empty_file(int, const struct cred *); -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* lock subclass for lower inode */ -+/* default MAX_LOCKDEP_SUBCLASSES(8) is not enough */ -+/* reduce? gave up. */ -+enum { -+ AuLsc_I_Begin = I_MUTEX_PARENT2, /* 5 */ -+ AuLsc_I_PARENT, /* lower inode, parent first */ -+ AuLsc_I_PARENT2, /* copyup dirs */ -+ AuLsc_I_PARENT3, /* copyup wh */ -+ AuLsc_I_CHILD, -+ AuLsc_I_CHILD2, -+ AuLsc_I_End -+}; -+ -+/* to debug easier, do not make them inlined functions */ -+#define MtxMustLock(mtx) AuDebugOn(!mutex_is_locked(mtx)) -+#define IMustLock(i) AuDebugOn(!inode_is_locked(i)) -+ -+/* ---------------------------------------------------------------------- */ -+ -+static inline void vfsub_drop_nlink(struct inode *inode) -+{ -+ AuDebugOn(!inode->i_nlink); -+ drop_nlink(inode); -+} -+ -+static inline void vfsub_dead_dir(struct inode *inode) -+{ -+ AuDebugOn(!S_ISDIR(inode->i_mode)); -+ inode->i_flags |= S_DEAD; -+ clear_nlink(inode); -+} -+ -+static inline int vfsub_native_ro(struct inode *inode) -+{ -+ return sb_rdonly(inode->i_sb) -+ || IS_RDONLY(inode) -+ /* || IS_APPEND(inode) */ -+ || IS_IMMUTABLE(inode); -+} -+ -+#ifdef CONFIG_AUFS_BR_FUSE -+int vfsub_test_mntns(struct vfsmount *mnt, struct super_block *h_sb); -+#else -+AuStubInt0(vfsub_test_mntns, struct vfsmount *mnt, struct super_block *h_sb); -+#endif -+ -+int vfsub_sync_filesystem(struct super_block *h_sb, int wait); -+ -+/* ---------------------------------------------------------------------- */ -+ -+int vfsub_update_h_iattr(struct path *h_path, int *did); -+struct file *vfsub_dentry_open(struct path *path, int flags); -+struct file *vfsub_filp_open(const char *path, int oflags, int mode); -+struct au_branch; -+struct vfsub_aopen_args { -+ struct file *file; -+ unsigned int open_flag; -+ umode_t create_mode; -+ struct au_branch *br; -+}; -+int vfsub_atomic_open(struct inode *dir, struct dentry *dentry, -+ struct vfsub_aopen_args *args); -+int vfsub_kern_path(const char *name, unsigned int flags, struct path *path); -+ -+struct dentry *vfsub_lookup_one_len_unlocked(const char *name, -+ struct dentry *parent, int len); -+struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent, -+ int len); -+ -+struct vfsub_lkup_one_args { -+ struct dentry **errp; -+ struct qstr *name; -+ struct dentry *parent; -+}; -+ -+static inline struct dentry *vfsub_lkup_one(struct qstr *name, -+ struct dentry *parent) -+{ -+ return vfsub_lookup_one_len(name->name, parent, name->len); -+} -+ -+void vfsub_call_lkup_one(void *args); -+ -+/* ---------------------------------------------------------------------- */ -+ -+static inline int vfsub_mnt_want_write(struct vfsmount *mnt) -+{ -+ int err; -+ -+ lockdep_off(); -+ err = mnt_want_write(mnt); -+ lockdep_on(); -+ return err; -+} -+ -+static inline void vfsub_mnt_drop_write(struct vfsmount *mnt) -+{ -+ lockdep_off(); -+ mnt_drop_write(mnt); -+ lockdep_on(); -+} -+ -+#if 0 /* reserved */ -+static inline void vfsub_mnt_drop_write_file(struct file *file) -+{ -+ lockdep_off(); -+ mnt_drop_write_file(file); -+ lockdep_on(); -+} -+#endif -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct au_hinode; -+struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1, -+ struct dentry *d2, struct au_hinode *hdir2); -+void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1, -+ struct dentry *d2, struct au_hinode *hdir2); -+ -+int vfsub_create(struct inode *dir, struct path *path, int mode, -+ bool want_excl); -+int vfsub_symlink(struct inode *dir, struct path *path, -+ const char *symname); -+int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev); -+int vfsub_link(struct dentry *src_dentry, struct inode *dir, -+ struct path *path, struct inode **delegated_inode); -+int vfsub_rename(struct inode *src_hdir, struct dentry *src_dentry, -+ struct inode *hdir, struct path *path, -+ struct inode **delegated_inode, unsigned int flags); -+int vfsub_mkdir(struct inode *dir, struct path *path, int mode); -+int vfsub_rmdir(struct inode *dir, struct path *path); -+ -+/* ---------------------------------------------------------------------- */ -+ -+ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count, -+ loff_t *ppos); -+ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count, -+ loff_t *ppos); -+ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count, -+ loff_t *ppos); -+ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, -+ loff_t *ppos); -+int vfsub_flush(struct file *file, fl_owner_t id); -+int vfsub_iterate_dir(struct file *file, struct dir_context *ctx); -+ -+static inline loff_t vfsub_f_size_read(struct file *file) -+{ -+ return i_size_read(file_inode(file)); -+} -+ -+static inline unsigned int vfsub_file_flags(struct file *file) -+{ -+ unsigned int flags; -+ -+ spin_lock(&file->f_lock); -+ flags = file->f_flags; -+ spin_unlock(&file->f_lock); -+ -+ return flags; -+} -+ -+static inline int vfsub_file_execed(struct file *file) -+{ -+ /* todo: direct access f_flags */ -+ return !!(vfsub_file_flags(file) & __FMODE_EXEC); -+} -+ -+#if 0 /* reserved */ -+static inline void vfsub_file_accessed(struct file *h_file) -+{ -+ file_accessed(h_file); -+ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL); /*ignore*/ -+} -+#endif -+ -+#if 0 /* reserved */ -+static inline void vfsub_touch_atime(struct vfsmount *h_mnt, -+ struct dentry *h_dentry) -+{ -+ struct path h_path = { -+ .dentry = h_dentry, -+ .mnt = h_mnt -+ }; -+ touch_atime(&h_path); -+ vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/ -+} -+#endif -+ -+static inline int vfsub_update_time(struct inode *h_inode, -+ struct timespec64 *ts, int flags) -+{ -+ return update_time(h_inode, ts, flags); -+ /* no vfsub_update_h_iattr() since we don't have struct path */ -+} -+ -+#ifdef CONFIG_FS_POSIX_ACL -+static inline int vfsub_acl_chmod(struct inode *h_inode, umode_t h_mode) -+{ -+ int err; -+ -+ err = posix_acl_chmod(h_inode, h_mode); -+ if (err == -EOPNOTSUPP) -+ err = 0; -+ return err; -+} -+#else -+AuStubInt0(vfsub_acl_chmod, struct inode *h_inode, umode_t h_mode); -+#endif -+ -+long vfsub_splice_to(struct file *in, loff_t *ppos, -+ struct pipe_inode_info *pipe, size_t len, -+ unsigned int flags); -+long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out, -+ loff_t *ppos, size_t len, unsigned int flags); -+ -+static inline long vfsub_truncate(struct path *path, loff_t length) -+{ -+ long err; -+ -+ lockdep_off(); -+ err = vfs_truncate(path, length); -+ lockdep_on(); -+ return err; -+} -+ -+int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr, -+ struct file *h_file); -+int vfsub_fsync(struct file *file, struct path *path, int datasync); -+ -+/* -+ * re-use branch fs's ioctl(FICLONE) while aufs itself doesn't support such -+ * ioctl. -+ */ -+static inline loff_t vfsub_clone_file_range(struct file *src, struct file *dst, -+ loff_t len) -+{ -+ loff_t err; -+ -+ lockdep_off(); -+ err = vfs_clone_file_range(src, 0, dst, 0, len, /*remap_flags*/0); -+ lockdep_on(); -+ -+ return err; -+} -+ -+/* copy_file_range(2) is a systemcall */ -+static inline ssize_t vfsub_copy_file_range(struct file *src, loff_t src_pos, -+ struct file *dst, loff_t dst_pos, -+ size_t len, unsigned int flags) -+{ -+ ssize_t ssz; -+ -+ lockdep_off(); -+ ssz = vfs_copy_file_range(src, src_pos, dst, dst_pos, len, flags); -+ lockdep_on(); -+ -+ return ssz; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static inline loff_t vfsub_llseek(struct file *file, loff_t offset, int origin) -+{ -+ loff_t err; -+ -+ lockdep_off(); -+ err = vfs_llseek(file, offset, origin); -+ lockdep_on(); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode); -+int vfsub_sio_rmdir(struct inode *dir, struct path *path); -+int vfsub_sio_notify_change(struct path *path, struct iattr *ia, -+ struct inode **delegated_inode); -+int vfsub_notify_change(struct path *path, struct iattr *ia, -+ struct inode **delegated_inode); -+int vfsub_unlink(struct inode *dir, struct path *path, -+ struct inode **delegated_inode, int force); -+ -+static inline int vfsub_getattr(const struct path *path, struct kstat *st) -+{ -+ return vfs_getattr(path, st, STATX_BASIC_STATS, AT_STATX_SYNC_AS_STAT); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static inline int vfsub_setxattr(struct dentry *dentry, const char *name, -+ const void *value, size_t size, int flags) -+{ -+ int err; -+ -+ lockdep_off(); -+ err = vfs_setxattr(dentry, name, value, size, flags); -+ lockdep_on(); -+ -+ return err; -+} -+ -+static inline int vfsub_removexattr(struct dentry *dentry, const char *name) -+{ -+ int err; -+ -+ lockdep_off(); -+ err = vfs_removexattr(dentry, name); -+ lockdep_on(); -+ -+ return err; -+} -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_VFSUB_H__ */ -diff -Nurp linux-5.6.3/fs/aufs/whout.c linux-5.6.3-aufs/fs/aufs/whout.c ---- linux-5.6.3/fs/aufs/whout.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/whout.c 2020-04-10 12:40:52.193049549 +0300 -@@ -0,0 +1,1049 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * whiteout for logical deletion and opaque directory -+ */ -+ -+#include "aufs.h" -+ -+#define WH_MASK 0444 -+ -+/* -+ * If a directory contains this file, then it is opaque. We start with the -+ * .wh. flag so that it is blocked by lookup. -+ */ -+static struct qstr diropq_name = QSTR_INIT(AUFS_WH_DIROPQ, -+ sizeof(AUFS_WH_DIROPQ) - 1); -+ -+/* -+ * generate whiteout name, which is NOT terminated by NULL. -+ * @name: original d_name.name -+ * @len: original d_name.len -+ * @wh: whiteout qstr -+ * returns zero when succeeds, otherwise error. -+ * succeeded value as wh->name should be freed by kfree(). -+ */ -+int au_wh_name_alloc(struct qstr *wh, const struct qstr *name) -+{ -+ char *p; -+ -+ if (unlikely(name->len > PATH_MAX - AUFS_WH_PFX_LEN)) -+ return -ENAMETOOLONG; -+ -+ wh->len = name->len + AUFS_WH_PFX_LEN; -+ p = kmalloc(wh->len, GFP_NOFS); -+ wh->name = p; -+ if (p) { -+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN); -+ memcpy(p + AUFS_WH_PFX_LEN, name->name, name->len); -+ /* smp_mb(); */ -+ return 0; -+ } -+ return -ENOMEM; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * test if the @wh_name exists under @h_parent. -+ * @try_sio specifies the necessary of super-io. -+ */ -+int au_wh_test(struct dentry *h_parent, struct qstr *wh_name, int try_sio) -+{ -+ int err; -+ struct dentry *wh_dentry; -+ -+ if (!try_sio) -+ wh_dentry = vfsub_lkup_one(wh_name, h_parent); -+ else -+ wh_dentry = au_sio_lkup_one(wh_name, h_parent); -+ err = PTR_ERR(wh_dentry); -+ if (IS_ERR(wh_dentry)) { -+ if (err == -ENAMETOOLONG) -+ err = 0; -+ goto out; -+ } -+ -+ err = 0; -+ if (d_is_negative(wh_dentry)) -+ goto out_wh; /* success */ -+ -+ err = 1; -+ if (d_is_reg(wh_dentry)) -+ goto out_wh; /* success */ -+ -+ err = -EIO; -+ AuIOErr("%pd Invalid whiteout entry type 0%o.\n", -+ wh_dentry, d_inode(wh_dentry)->i_mode); -+ -+out_wh: -+ dput(wh_dentry); -+out: -+ return err; -+} -+ -+/* -+ * test if the @h_dentry sets opaque or not. -+ */ -+int au_diropq_test(struct dentry *h_dentry) -+{ -+ int err; -+ struct inode *h_dir; -+ -+ h_dir = d_inode(h_dentry); -+ err = au_wh_test(h_dentry, &diropq_name, -+ au_test_h_perm_sio(h_dir, MAY_EXEC)); -+ return err; -+} -+ -+/* -+ * returns a negative dentry whose name is unique and temporary. -+ */ -+struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br, -+ struct qstr *prefix) -+{ -+ struct dentry *dentry; -+ int i; -+ char defname[NAME_MAX - AUFS_MAX_NAMELEN + DNAME_INLINE_LEN + 1], -+ *name, *p; -+ /* strict atomic_t is unnecessary here */ -+ static unsigned short cnt; -+ struct qstr qs; -+ -+ BUILD_BUG_ON(sizeof(cnt) * 2 > AUFS_WH_TMP_LEN); -+ -+ name = defname; -+ qs.len = sizeof(defname) - DNAME_INLINE_LEN + prefix->len - 1; -+ if (unlikely(prefix->len > DNAME_INLINE_LEN)) { -+ dentry = ERR_PTR(-ENAMETOOLONG); -+ if (unlikely(qs.len > NAME_MAX)) -+ goto out; -+ dentry = ERR_PTR(-ENOMEM); -+ name = kmalloc(qs.len + 1, GFP_NOFS); -+ if (unlikely(!name)) -+ goto out; -+ } -+ -+ /* doubly whiteout-ed */ -+ memcpy(name, AUFS_WH_PFX AUFS_WH_PFX, AUFS_WH_PFX_LEN * 2); -+ p = name + AUFS_WH_PFX_LEN * 2; -+ memcpy(p, prefix->name, prefix->len); -+ p += prefix->len; -+ *p++ = '.'; -+ AuDebugOn(name + qs.len + 1 - p <= AUFS_WH_TMP_LEN); -+ -+ qs.name = name; -+ for (i = 0; i < 3; i++) { -+ sprintf(p, "%.*x", AUFS_WH_TMP_LEN, cnt++); -+ dentry = au_sio_lkup_one(&qs, h_parent); -+ if (IS_ERR(dentry) || d_is_negative(dentry)) -+ goto out_name; -+ dput(dentry); -+ } -+ /* pr_warn("could not get random name\n"); */ -+ dentry = ERR_PTR(-EEXIST); -+ AuDbg("%.*s\n", AuLNPair(&qs)); -+ BUG(); -+ -+out_name: -+ if (name != defname) -+ au_kfree_try_rcu(name); -+out: -+ AuTraceErrPtr(dentry); -+ return dentry; -+} -+ -+/* -+ * rename the @h_dentry on @br to the whiteouted temporary name. -+ */ -+int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br) -+{ -+ int err; -+ struct path h_path = { -+ .mnt = au_br_mnt(br) -+ }; -+ struct inode *h_dir, *delegated; -+ struct dentry *h_parent; -+ -+ h_parent = h_dentry->d_parent; /* dir inode is locked */ -+ h_dir = d_inode(h_parent); -+ IMustLock(h_dir); -+ -+ h_path.dentry = au_whtmp_lkup(h_parent, br, &h_dentry->d_name); -+ err = PTR_ERR(h_path.dentry); -+ if (IS_ERR(h_path.dentry)) -+ goto out; -+ -+ /* under the same dir, no need to lock_rename() */ -+ delegated = NULL; -+ err = vfsub_rename(h_dir, h_dentry, h_dir, &h_path, &delegated, -+ /*flags*/0); -+ AuTraceErr(err); -+ if (unlikely(err == -EWOULDBLOCK)) { -+ pr_warn("cannot retry for NFSv4 delegation" -+ " for an internal rename\n"); -+ iput(delegated); -+ } -+ dput(h_path.dentry); -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+/* -+ * functions for removing a whiteout -+ */ -+ -+static int do_unlink_wh(struct inode *h_dir, struct path *h_path) -+{ -+ int err, force; -+ struct inode *delegated; -+ -+ /* -+ * forces superio when the dir has a sticky bit. -+ * this may be a violation of unix fs semantics. -+ */ -+ force = (h_dir->i_mode & S_ISVTX) -+ && !uid_eq(current_fsuid(), d_inode(h_path->dentry)->i_uid); -+ delegated = NULL; -+ err = vfsub_unlink(h_dir, h_path, &delegated, force); -+ if (unlikely(err == -EWOULDBLOCK)) { -+ pr_warn("cannot retry for NFSv4 delegation" -+ " for an internal unlink\n"); -+ iput(delegated); -+ } -+ return err; -+} -+ -+int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path, -+ struct dentry *dentry) -+{ -+ int err; -+ -+ err = do_unlink_wh(h_dir, h_path); -+ if (!err && dentry) -+ au_set_dbwh(dentry, -1); -+ -+ return err; -+} -+ -+static int unlink_wh_name(struct dentry *h_parent, struct qstr *wh, -+ struct au_branch *br) -+{ -+ int err; -+ struct path h_path = { -+ .mnt = au_br_mnt(br) -+ }; -+ -+ err = 0; -+ h_path.dentry = vfsub_lkup_one(wh, h_parent); -+ if (IS_ERR(h_path.dentry)) -+ err = PTR_ERR(h_path.dentry); -+ else { -+ if (d_is_reg(h_path.dentry)) -+ err = do_unlink_wh(d_inode(h_parent), &h_path); -+ dput(h_path.dentry); -+ } -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+/* -+ * initialize/clean whiteout for a branch -+ */ -+ -+static void au_wh_clean(struct inode *h_dir, struct path *whpath, -+ const int isdir) -+{ -+ int err; -+ struct inode *delegated; -+ -+ if (d_is_negative(whpath->dentry)) -+ return; -+ -+ if (isdir) -+ err = vfsub_rmdir(h_dir, whpath); -+ else { -+ delegated = NULL; -+ err = vfsub_unlink(h_dir, whpath, &delegated, /*force*/0); -+ if (unlikely(err == -EWOULDBLOCK)) { -+ pr_warn("cannot retry for NFSv4 delegation" -+ " for an internal unlink\n"); -+ iput(delegated); -+ } -+ } -+ if (unlikely(err)) -+ pr_warn("failed removing %pd (%d), ignored.\n", -+ whpath->dentry, err); -+} -+ -+static int test_linkable(struct dentry *h_root) -+{ -+ struct inode *h_dir = d_inode(h_root); -+ -+ if (h_dir->i_op->link) -+ return 0; -+ -+ pr_err("%pd (%s) doesn't support link(2), use noplink and rw+nolwh\n", -+ h_root, au_sbtype(h_root->d_sb)); -+ return -ENOSYS; /* the branch doesn't have its ->link() */ -+} -+ -+/* todo: should this mkdir be done in /sbin/mount.aufs helper? */ -+static int au_whdir(struct inode *h_dir, struct path *path) -+{ -+ int err; -+ -+ err = -EEXIST; -+ if (d_is_negative(path->dentry)) { -+ int mode = 0700; -+ -+ if (au_test_nfs(path->dentry->d_sb)) -+ mode |= 0111; -+ err = vfsub_mkdir(h_dir, path, mode); -+ } else if (d_is_dir(path->dentry)) -+ err = 0; -+ else -+ pr_err("unknown %pd exists\n", path->dentry); -+ -+ return err; -+} -+ -+struct au_wh_base { -+ const struct qstr *name; -+ struct dentry *dentry; -+}; -+ -+static void au_wh_init_ro(struct inode *h_dir, struct au_wh_base base[], -+ struct path *h_path) -+{ -+ h_path->dentry = base[AuBrWh_BASE].dentry; -+ au_wh_clean(h_dir, h_path, /*isdir*/0); -+ h_path->dentry = base[AuBrWh_PLINK].dentry; -+ au_wh_clean(h_dir, h_path, /*isdir*/1); -+ h_path->dentry = base[AuBrWh_ORPH].dentry; -+ au_wh_clean(h_dir, h_path, /*isdir*/1); -+} -+ -+/* -+ * returns tri-state, -+ * minus: error, caller should print the message -+ * zero: success -+ * plus: error, caller should NOT print the message -+ */ -+static int au_wh_init_rw_nolink(struct dentry *h_root, struct au_wbr *wbr, -+ int do_plink, struct au_wh_base base[], -+ struct path *h_path) -+{ -+ int err; -+ struct inode *h_dir; -+ -+ h_dir = d_inode(h_root); -+ h_path->dentry = base[AuBrWh_BASE].dentry; -+ au_wh_clean(h_dir, h_path, /*isdir*/0); -+ h_path->dentry = base[AuBrWh_PLINK].dentry; -+ if (do_plink) { -+ err = test_linkable(h_root); -+ if (unlikely(err)) { -+ err = 1; -+ goto out; -+ } -+ -+ err = au_whdir(h_dir, h_path); -+ if (unlikely(err)) -+ goto out; -+ wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry); -+ } else -+ au_wh_clean(h_dir, h_path, /*isdir*/1); -+ h_path->dentry = base[AuBrWh_ORPH].dentry; -+ err = au_whdir(h_dir, h_path); -+ if (unlikely(err)) -+ goto out; -+ wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry); -+ -+out: -+ return err; -+} -+ -+/* -+ * for the moment, aufs supports the branch filesystem which does not support -+ * link(2). testing on FAT which does not support i_op->setattr() fully either, -+ * copyup failed. finally, such filesystem will not be used as the writable -+ * branch. -+ * -+ * returns tri-state, see above. -+ */ -+static int au_wh_init_rw(struct dentry *h_root, struct au_wbr *wbr, -+ int do_plink, struct au_wh_base base[], -+ struct path *h_path) -+{ -+ int err; -+ struct inode *h_dir; -+ -+ WbrWhMustWriteLock(wbr); -+ -+ err = test_linkable(h_root); -+ if (unlikely(err)) { -+ err = 1; -+ goto out; -+ } -+ -+ /* -+ * todo: should this create be done in /sbin/mount.aufs helper? -+ */ -+ err = -EEXIST; -+ h_dir = d_inode(h_root); -+ if (d_is_negative(base[AuBrWh_BASE].dentry)) { -+ h_path->dentry = base[AuBrWh_BASE].dentry; -+ err = vfsub_create(h_dir, h_path, WH_MASK, /*want_excl*/true); -+ } else if (d_is_reg(base[AuBrWh_BASE].dentry)) -+ err = 0; -+ else -+ pr_err("unknown %pd2 exists\n", base[AuBrWh_BASE].dentry); -+ if (unlikely(err)) -+ goto out; -+ -+ h_path->dentry = base[AuBrWh_PLINK].dentry; -+ if (do_plink) { -+ err = au_whdir(h_dir, h_path); -+ if (unlikely(err)) -+ goto out; -+ wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry); -+ } else -+ au_wh_clean(h_dir, h_path, /*isdir*/1); -+ wbr->wbr_whbase = dget(base[AuBrWh_BASE].dentry); -+ -+ h_path->dentry = base[AuBrWh_ORPH].dentry; -+ err = au_whdir(h_dir, h_path); -+ if (unlikely(err)) -+ goto out; -+ wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry); -+ -+out: -+ return err; -+} -+ -+/* -+ * initialize the whiteout base file/dir for @br. -+ */ -+int au_wh_init(struct au_branch *br, struct super_block *sb) -+{ -+ int err, i; -+ const unsigned char do_plink -+ = !!au_opt_test(au_mntflags(sb), PLINK); -+ struct inode *h_dir; -+ struct path path = br->br_path; -+ struct dentry *h_root = path.dentry; -+ struct au_wbr *wbr = br->br_wbr; -+ static const struct qstr base_name[] = { -+ [AuBrWh_BASE] = QSTR_INIT(AUFS_BASE_NAME, -+ sizeof(AUFS_BASE_NAME) - 1), -+ [AuBrWh_PLINK] = QSTR_INIT(AUFS_PLINKDIR_NAME, -+ sizeof(AUFS_PLINKDIR_NAME) - 1), -+ [AuBrWh_ORPH] = QSTR_INIT(AUFS_ORPHDIR_NAME, -+ sizeof(AUFS_ORPHDIR_NAME) - 1) -+ }; -+ struct au_wh_base base[] = { -+ [AuBrWh_BASE] = { -+ .name = base_name + AuBrWh_BASE, -+ .dentry = NULL -+ }, -+ [AuBrWh_PLINK] = { -+ .name = base_name + AuBrWh_PLINK, -+ .dentry = NULL -+ }, -+ [AuBrWh_ORPH] = { -+ .name = base_name + AuBrWh_ORPH, -+ .dentry = NULL -+ } -+ }; -+ -+ if (wbr) -+ WbrWhMustWriteLock(wbr); -+ -+ for (i = 0; i < AuBrWh_Last; i++) { -+ /* doubly whiteouted */ -+ struct dentry *d; -+ -+ d = au_wh_lkup(h_root, (void *)base[i].name, br); -+ err = PTR_ERR(d); -+ if (IS_ERR(d)) -+ goto out; -+ -+ base[i].dentry = d; -+ AuDebugOn(wbr -+ && wbr->wbr_wh[i] -+ && wbr->wbr_wh[i] != base[i].dentry); -+ } -+ -+ if (wbr) -+ for (i = 0; i < AuBrWh_Last; i++) { -+ dput(wbr->wbr_wh[i]); -+ wbr->wbr_wh[i] = NULL; -+ } -+ -+ err = 0; -+ if (!au_br_writable(br->br_perm)) { -+ h_dir = d_inode(h_root); -+ au_wh_init_ro(h_dir, base, &path); -+ } else if (!au_br_wh_linkable(br->br_perm)) { -+ err = au_wh_init_rw_nolink(h_root, wbr, do_plink, base, &path); -+ if (err > 0) -+ goto out; -+ else if (err) -+ goto out_err; -+ } else { -+ err = au_wh_init_rw(h_root, wbr, do_plink, base, &path); -+ if (err > 0) -+ goto out; -+ else if (err) -+ goto out_err; -+ } -+ goto out; /* success */ -+ -+out_err: -+ pr_err("an error(%d) on the writable branch %pd(%s)\n", -+ err, h_root, au_sbtype(h_root->d_sb)); -+out: -+ for (i = 0; i < AuBrWh_Last; i++) -+ dput(base[i].dentry); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+/* -+ * whiteouts are all hard-linked usually. -+ * when its link count reaches a ceiling, we create a new whiteout base -+ * asynchronously. -+ */ -+ -+struct reinit_br_wh { -+ struct super_block *sb; -+ struct au_branch *br; -+}; -+ -+static void reinit_br_wh(void *arg) -+{ -+ int err; -+ aufs_bindex_t bindex; -+ struct path h_path; -+ struct reinit_br_wh *a = arg; -+ struct au_wbr *wbr; -+ struct inode *dir, *delegated; -+ struct dentry *h_root; -+ struct au_hinode *hdir; -+ -+ err = 0; -+ wbr = a->br->br_wbr; -+ /* big aufs lock */ -+ si_noflush_write_lock(a->sb); -+ if (!au_br_writable(a->br->br_perm)) -+ goto out; -+ bindex = au_br_index(a->sb, a->br->br_id); -+ if (unlikely(bindex < 0)) -+ goto out; -+ -+ di_read_lock_parent(a->sb->s_root, AuLock_IR); -+ dir = d_inode(a->sb->s_root); -+ hdir = au_hi(dir, bindex); -+ h_root = au_h_dptr(a->sb->s_root, bindex); -+ AuDebugOn(h_root != au_br_dentry(a->br)); -+ -+ au_hn_inode_lock_nested(hdir, AuLsc_I_PARENT); -+ wbr_wh_write_lock(wbr); -+ err = au_h_verify(wbr->wbr_whbase, au_opt_udba(a->sb), hdir->hi_inode, -+ h_root, a->br); -+ if (!err) { -+ h_path.dentry = wbr->wbr_whbase; -+ h_path.mnt = au_br_mnt(a->br); -+ delegated = NULL; -+ err = vfsub_unlink(hdir->hi_inode, &h_path, &delegated, -+ /*force*/0); -+ if (unlikely(err == -EWOULDBLOCK)) { -+ pr_warn("cannot retry for NFSv4 delegation" -+ " for an internal unlink\n"); -+ iput(delegated); -+ } -+ } else { -+ pr_warn("%pd is moved, ignored\n", wbr->wbr_whbase); -+ err = 0; -+ } -+ dput(wbr->wbr_whbase); -+ wbr->wbr_whbase = NULL; -+ if (!err) -+ err = au_wh_init(a->br, a->sb); -+ wbr_wh_write_unlock(wbr); -+ au_hn_inode_unlock(hdir); -+ di_read_unlock(a->sb->s_root, AuLock_IR); -+ if (!err) -+ au_fhsm_wrote(a->sb, bindex, /*force*/0); -+ -+out: -+ if (wbr) -+ atomic_dec(&wbr->wbr_wh_running); -+ au_lcnt_dec(&a->br->br_count); -+ si_write_unlock(a->sb); -+ au_nwt_done(&au_sbi(a->sb)->si_nowait); -+ au_kfree_rcu(a); -+ if (unlikely(err)) -+ AuIOErr("err %d\n", err); -+} -+ -+static void kick_reinit_br_wh(struct super_block *sb, struct au_branch *br) -+{ -+ int do_dec, wkq_err; -+ struct reinit_br_wh *arg; -+ -+ do_dec = 1; -+ if (atomic_inc_return(&br->br_wbr->wbr_wh_running) != 1) -+ goto out; -+ -+ /* ignore ENOMEM */ -+ arg = kmalloc(sizeof(*arg), GFP_NOFS); -+ if (arg) { -+ /* -+ * dec(wh_running), kfree(arg) and dec(br_count) -+ * in reinit function -+ */ -+ arg->sb = sb; -+ arg->br = br; -+ au_lcnt_inc(&br->br_count); -+ wkq_err = au_wkq_nowait(reinit_br_wh, arg, sb, /*flags*/0); -+ if (unlikely(wkq_err)) { -+ atomic_dec(&br->br_wbr->wbr_wh_running); -+ au_lcnt_dec(&br->br_count); -+ au_kfree_rcu(arg); -+ } -+ do_dec = 0; -+ } -+ -+out: -+ if (do_dec) -+ atomic_dec(&br->br_wbr->wbr_wh_running); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * create the whiteout @wh. -+ */ -+static int link_or_create_wh(struct super_block *sb, aufs_bindex_t bindex, -+ struct dentry *wh) -+{ -+ int err; -+ struct path h_path = { -+ .dentry = wh -+ }; -+ struct au_branch *br; -+ struct au_wbr *wbr; -+ struct dentry *h_parent; -+ struct inode *h_dir, *delegated; -+ -+ h_parent = wh->d_parent; /* dir inode is locked */ -+ h_dir = d_inode(h_parent); -+ IMustLock(h_dir); -+ -+ br = au_sbr(sb, bindex); -+ h_path.mnt = au_br_mnt(br); -+ wbr = br->br_wbr; -+ wbr_wh_read_lock(wbr); -+ if (wbr->wbr_whbase) { -+ delegated = NULL; -+ err = vfsub_link(wbr->wbr_whbase, h_dir, &h_path, &delegated); -+ if (unlikely(err == -EWOULDBLOCK)) { -+ pr_warn("cannot retry for NFSv4 delegation" -+ " for an internal link\n"); -+ iput(delegated); -+ } -+ if (!err || err != -EMLINK) -+ goto out; -+ -+ /* link count full. re-initialize br_whbase. */ -+ kick_reinit_br_wh(sb, br); -+ } -+ -+ /* return this error in this context */ -+ err = vfsub_create(h_dir, &h_path, WH_MASK, /*want_excl*/true); -+ if (!err) -+ au_fhsm_wrote(sb, bindex, /*force*/0); -+ -+out: -+ wbr_wh_read_unlock(wbr); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * create or remove the diropq. -+ */ -+static struct dentry *do_diropq(struct dentry *dentry, aufs_bindex_t bindex, -+ unsigned int flags) -+{ -+ struct dentry *opq_dentry, *h_dentry; -+ struct super_block *sb; -+ struct au_branch *br; -+ int err; -+ -+ sb = dentry->d_sb; -+ br = au_sbr(sb, bindex); -+ h_dentry = au_h_dptr(dentry, bindex); -+ opq_dentry = vfsub_lkup_one(&diropq_name, h_dentry); -+ if (IS_ERR(opq_dentry)) -+ goto out; -+ -+ if (au_ftest_diropq(flags, CREATE)) { -+ err = link_or_create_wh(sb, bindex, opq_dentry); -+ if (!err) { -+ au_set_dbdiropq(dentry, bindex); -+ goto out; /* success */ -+ } -+ } else { -+ struct path tmp = { -+ .dentry = opq_dentry, -+ .mnt = au_br_mnt(br) -+ }; -+ err = do_unlink_wh(au_h_iptr(d_inode(dentry), bindex), &tmp); -+ if (!err) -+ au_set_dbdiropq(dentry, -1); -+ } -+ dput(opq_dentry); -+ opq_dentry = ERR_PTR(err); -+ -+out: -+ return opq_dentry; -+} -+ -+struct do_diropq_args { -+ struct dentry **errp; -+ struct dentry *dentry; -+ aufs_bindex_t bindex; -+ unsigned int flags; -+}; -+ -+static void call_do_diropq(void *args) -+{ -+ struct do_diropq_args *a = args; -+ *a->errp = do_diropq(a->dentry, a->bindex, a->flags); -+} -+ -+struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex, -+ unsigned int flags) -+{ -+ struct dentry *diropq, *h_dentry; -+ -+ h_dentry = au_h_dptr(dentry, bindex); -+ if (!au_test_h_perm_sio(d_inode(h_dentry), MAY_EXEC | MAY_WRITE)) -+ diropq = do_diropq(dentry, bindex, flags); -+ else { -+ int wkq_err; -+ struct do_diropq_args args = { -+ .errp = &diropq, -+ .dentry = dentry, -+ .bindex = bindex, -+ .flags = flags -+ }; -+ -+ wkq_err = au_wkq_wait(call_do_diropq, &args); -+ if (unlikely(wkq_err)) -+ diropq = ERR_PTR(wkq_err); -+ } -+ -+ return diropq; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * lookup whiteout dentry. -+ * @h_parent: lower parent dentry which must exist and be locked -+ * @base_name: name of dentry which will be whiteouted -+ * returns dentry for whiteout. -+ */ -+struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name, -+ struct au_branch *br) -+{ -+ int err; -+ struct qstr wh_name; -+ struct dentry *wh_dentry; -+ -+ err = au_wh_name_alloc(&wh_name, base_name); -+ wh_dentry = ERR_PTR(err); -+ if (!err) { -+ wh_dentry = vfsub_lkup_one(&wh_name, h_parent); -+ au_kfree_try_rcu(wh_name.name); -+ } -+ return wh_dentry; -+} -+ -+/* -+ * link/create a whiteout for @dentry on @bindex. -+ */ -+struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex, -+ struct dentry *h_parent) -+{ -+ struct dentry *wh_dentry; -+ struct super_block *sb; -+ int err; -+ -+ sb = dentry->d_sb; -+ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, au_sbr(sb, bindex)); -+ if (!IS_ERR(wh_dentry) && d_is_negative(wh_dentry)) { -+ err = link_or_create_wh(sb, bindex, wh_dentry); -+ if (!err) { -+ au_set_dbwh(dentry, bindex); -+ au_fhsm_wrote(sb, bindex, /*force*/0); -+ } else { -+ dput(wh_dentry); -+ wh_dentry = ERR_PTR(err); -+ } -+ } -+ -+ return wh_dentry; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* Delete all whiteouts in this directory on branch bindex. */ -+static int del_wh_children(struct dentry *h_dentry, struct au_nhash *whlist, -+ aufs_bindex_t bindex, struct au_branch *br) -+{ -+ int err; -+ unsigned long ul, n; -+ struct qstr wh_name; -+ char *p; -+ struct hlist_head *head; -+ struct au_vdir_wh *pos; -+ struct au_vdir_destr *str; -+ -+ err = -ENOMEM; -+ p = (void *)__get_free_page(GFP_NOFS); -+ wh_name.name = p; -+ if (unlikely(!wh_name.name)) -+ goto out; -+ -+ err = 0; -+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN); -+ p += AUFS_WH_PFX_LEN; -+ n = whlist->nh_num; -+ head = whlist->nh_head; -+ for (ul = 0; !err && ul < n; ul++, head++) { -+ hlist_for_each_entry(pos, head, wh_hash) { -+ if (pos->wh_bindex != bindex) -+ continue; -+ -+ str = &pos->wh_str; -+ if (str->len + AUFS_WH_PFX_LEN <= PATH_MAX) { -+ memcpy(p, str->name, str->len); -+ wh_name.len = AUFS_WH_PFX_LEN + str->len; -+ err = unlink_wh_name(h_dentry, &wh_name, br); -+ if (!err) -+ continue; -+ break; -+ } -+ AuIOErr("whiteout name too long %.*s\n", -+ str->len, str->name); -+ err = -EIO; -+ break; -+ } -+ } -+ free_page((unsigned long)wh_name.name); -+ -+out: -+ return err; -+} -+ -+struct del_wh_children_args { -+ int *errp; -+ struct dentry *h_dentry; -+ struct au_nhash *whlist; -+ aufs_bindex_t bindex; -+ struct au_branch *br; -+}; -+ -+static void call_del_wh_children(void *args) -+{ -+ struct del_wh_children_args *a = args; -+ *a->errp = del_wh_children(a->h_dentry, a->whlist, a->bindex, a->br); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp) -+{ -+ struct au_whtmp_rmdir *whtmp; -+ int err; -+ unsigned int rdhash; -+ -+ SiMustAnyLock(sb); -+ -+ whtmp = kzalloc(sizeof(*whtmp), gfp); -+ if (unlikely(!whtmp)) { -+ whtmp = ERR_PTR(-ENOMEM); -+ goto out; -+ } -+ -+ /* no estimation for dir size */ -+ rdhash = au_sbi(sb)->si_rdhash; -+ if (!rdhash) -+ rdhash = AUFS_RDHASH_DEF; -+ err = au_nhash_alloc(&whtmp->whlist, rdhash, gfp); -+ if (unlikely(err)) { -+ au_kfree_rcu(whtmp); -+ whtmp = ERR_PTR(err); -+ } -+ -+out: -+ return whtmp; -+} -+ -+void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp) -+{ -+ if (whtmp->br) -+ au_lcnt_dec(&whtmp->br->br_count); -+ dput(whtmp->wh_dentry); -+ iput(whtmp->dir); -+ au_nhash_wh_free(&whtmp->whlist); -+ au_kfree_rcu(whtmp); -+} -+ -+/* -+ * rmdir the whiteouted temporary named dir @h_dentry. -+ * @whlist: whiteouted children. -+ */ -+int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex, -+ struct dentry *wh_dentry, struct au_nhash *whlist) -+{ -+ int err; -+ unsigned int h_nlink; -+ struct path h_tmp; -+ struct inode *wh_inode, *h_dir; -+ struct au_branch *br; -+ -+ h_dir = d_inode(wh_dentry->d_parent); /* dir inode is locked */ -+ IMustLock(h_dir); -+ -+ br = au_sbr(dir->i_sb, bindex); -+ wh_inode = d_inode(wh_dentry); -+ inode_lock_nested(wh_inode, AuLsc_I_CHILD); -+ -+ /* -+ * someone else might change some whiteouts while we were sleeping. -+ * it means this whlist may have an obsoleted entry. -+ */ -+ if (!au_test_h_perm_sio(wh_inode, MAY_EXEC | MAY_WRITE)) -+ err = del_wh_children(wh_dentry, whlist, bindex, br); -+ else { -+ int wkq_err; -+ struct del_wh_children_args args = { -+ .errp = &err, -+ .h_dentry = wh_dentry, -+ .whlist = whlist, -+ .bindex = bindex, -+ .br = br -+ }; -+ -+ wkq_err = au_wkq_wait(call_del_wh_children, &args); -+ if (unlikely(wkq_err)) -+ err = wkq_err; -+ } -+ inode_unlock(wh_inode); -+ -+ if (!err) { -+ h_tmp.dentry = wh_dentry; -+ h_tmp.mnt = au_br_mnt(br); -+ h_nlink = h_dir->i_nlink; -+ err = vfsub_rmdir(h_dir, &h_tmp); -+ /* some fs doesn't change the parent nlink in some cases */ -+ h_nlink -= h_dir->i_nlink; -+ } -+ -+ if (!err) { -+ if (au_ibtop(dir) == bindex) { -+ /* todo: dir->i_mutex is necessary */ -+ au_cpup_attr_timesizes(dir); -+ if (h_nlink) -+ vfsub_drop_nlink(dir); -+ } -+ return 0; /* success */ -+ } -+ -+ pr_warn("failed removing %pd(%d), ignored\n", wh_dentry, err); -+ return err; -+} -+ -+static void call_rmdir_whtmp(void *args) -+{ -+ int err; -+ aufs_bindex_t bindex; -+ struct au_whtmp_rmdir *a = args; -+ struct super_block *sb; -+ struct dentry *h_parent; -+ struct inode *h_dir; -+ struct au_hinode *hdir; -+ -+ /* rmdir by nfsd may cause deadlock with this i_mutex */ -+ /* inode_lock(a->dir); */ -+ err = -EROFS; -+ sb = a->dir->i_sb; -+ si_read_lock(sb, !AuLock_FLUSH); -+ if (!au_br_writable(a->br->br_perm)) -+ goto out; -+ bindex = au_br_index(sb, a->br->br_id); -+ if (unlikely(bindex < 0)) -+ goto out; -+ -+ err = -EIO; -+ ii_write_lock_parent(a->dir); -+ h_parent = dget_parent(a->wh_dentry); -+ h_dir = d_inode(h_parent); -+ hdir = au_hi(a->dir, bindex); -+ err = vfsub_mnt_want_write(au_br_mnt(a->br)); -+ if (unlikely(err)) -+ goto out_mnt; -+ au_hn_inode_lock_nested(hdir, AuLsc_I_PARENT); -+ err = au_h_verify(a->wh_dentry, au_opt_udba(sb), h_dir, h_parent, -+ a->br); -+ if (!err) -+ err = au_whtmp_rmdir(a->dir, bindex, a->wh_dentry, &a->whlist); -+ au_hn_inode_unlock(hdir); -+ vfsub_mnt_drop_write(au_br_mnt(a->br)); -+ -+out_mnt: -+ dput(h_parent); -+ ii_write_unlock(a->dir); -+out: -+ /* inode_unlock(a->dir); */ -+ au_whtmp_rmdir_free(a); -+ si_read_unlock(sb); -+ au_nwt_done(&au_sbi(sb)->si_nowait); -+ if (unlikely(err)) -+ AuIOErr("err %d\n", err); -+} -+ -+void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex, -+ struct dentry *wh_dentry, struct au_whtmp_rmdir *args) -+{ -+ int wkq_err; -+ struct super_block *sb; -+ -+ IMustLock(dir); -+ -+ /* all post-process will be done in do_rmdir_whtmp(). */ -+ sb = dir->i_sb; -+ args->dir = au_igrab(dir); -+ args->br = au_sbr(sb, bindex); -+ au_lcnt_inc(&args->br->br_count); -+ args->wh_dentry = dget(wh_dentry); -+ wkq_err = au_wkq_nowait(call_rmdir_whtmp, args, sb, /*flags*/0); -+ if (unlikely(wkq_err)) { -+ pr_warn("rmdir error %pd (%d), ignored\n", wh_dentry, wkq_err); -+ au_whtmp_rmdir_free(args); -+ } -+} -diff -Nurp linux-5.6.3/fs/aufs/whout.h linux-5.6.3-aufs/fs/aufs/whout.h ---- linux-5.6.3/fs/aufs/whout.h 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/whout.h 2020-04-10 12:40:52.193049549 +0300 -@@ -0,0 +1,73 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * whiteout for logical deletion and opaque directory -+ */ -+ -+#ifndef __AUFS_WHOUT_H__ -+#define __AUFS_WHOUT_H__ -+ -+#ifdef __KERNEL__ -+ -+#include "dir.h" -+ -+/* whout.c */ -+int au_wh_name_alloc(struct qstr *wh, const struct qstr *name); -+int au_wh_test(struct dentry *h_parent, struct qstr *wh_name, int try_sio); -+int au_diropq_test(struct dentry *h_dentry); -+struct au_branch; -+struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br, -+ struct qstr *prefix); -+int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br); -+int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path, -+ struct dentry *dentry); -+int au_wh_init(struct au_branch *br, struct super_block *sb); -+ -+/* diropq flags */ -+#define AuDiropq_CREATE 1 -+#define au_ftest_diropq(flags, name) ((flags) & AuDiropq_##name) -+#define au_fset_diropq(flags, name) \ -+ do { (flags) |= AuDiropq_##name; } while (0) -+#define au_fclr_diropq(flags, name) \ -+ do { (flags) &= ~AuDiropq_##name; } while (0) -+ -+struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex, -+ unsigned int flags); -+struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name, -+ struct au_branch *br); -+struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex, -+ struct dentry *h_parent); -+ -+/* real rmdir for the whiteout-ed dir */ -+struct au_whtmp_rmdir { -+ struct inode *dir; -+ struct au_branch *br; -+ struct dentry *wh_dentry; -+ struct au_nhash whlist; -+}; -+ -+struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp); -+void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp); -+int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex, -+ struct dentry *wh_dentry, struct au_nhash *whlist); -+void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex, -+ struct dentry *wh_dentry, struct au_whtmp_rmdir *args); -+ -+/* ---------------------------------------------------------------------- */ -+ -+static inline struct dentry *au_diropq_create(struct dentry *dentry, -+ aufs_bindex_t bindex) -+{ -+ return au_diropq_sio(dentry, bindex, AuDiropq_CREATE); -+} -+ -+static inline int au_diropq_remove(struct dentry *dentry, aufs_bindex_t bindex) -+{ -+ return PTR_ERR(au_diropq_sio(dentry, bindex, !AuDiropq_CREATE)); -+} -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_WHOUT_H__ */ -diff -Nurp linux-5.6.3/fs/aufs/wkq.c linux-5.6.3-aufs/fs/aufs/wkq.c ---- linux-5.6.3/fs/aufs/wkq.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/wkq.c 2020-04-10 12:40:52.193049549 +0300 -@@ -0,0 +1,359 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * workqueue for asynchronous/super-io operations -+ * todo: try new credential scheme -+ */ -+ -+#include -+#include "aufs.h" -+ -+/* internal workqueue named AUFS_WKQ_NAME */ -+ -+static struct workqueue_struct *au_wkq; -+ -+struct au_wkinfo { -+ struct work_struct wk; -+ struct kobject *kobj; -+ -+ unsigned int flags; /* see wkq.h */ -+ -+ au_wkq_func_t func; -+ void *args; -+ -+#ifdef CONFIG_LOCKDEP -+ int dont_check; -+ struct held_lock **hlock; -+#endif -+ -+ struct completion *comp; -+}; -+ -+/* ---------------------------------------------------------------------- */ -+/* -+ * Aufs passes some operations to the workqueue such as the internal copyup. -+ * This scheme looks rather unnatural for LOCKDEP debugging feature, since the -+ * job run by workqueue depends upon the locks acquired in the other task. -+ * Delegating a small operation to the workqueue, aufs passes its lockdep -+ * information too. And the job in the workqueue restores the info in order to -+ * pretend as if it acquired those locks. This is just to make LOCKDEP work -+ * correctly and expectedly. -+ */ -+ -+#ifndef CONFIG_LOCKDEP -+AuStubInt0(au_wkq_lockdep_alloc, struct au_wkinfo *wkinfo); -+AuStubVoid(au_wkq_lockdep_free, struct au_wkinfo *wkinfo); -+AuStubVoid(au_wkq_lockdep_pre, struct au_wkinfo *wkinfo); -+AuStubVoid(au_wkq_lockdep_post, struct au_wkinfo *wkinfo); -+AuStubVoid(au_wkq_lockdep_init, struct au_wkinfo *wkinfo); -+#else -+static void au_wkq_lockdep_init(struct au_wkinfo *wkinfo) -+{ -+ wkinfo->hlock = NULL; -+ wkinfo->dont_check = 0; -+} -+ -+/* -+ * 1: matched -+ * 0: unmatched -+ */ -+static int au_wkq_lockdep_test(struct lock_class_key *key, const char *name) -+{ -+ static DEFINE_SPINLOCK(spin); -+ static struct { -+ char *name; -+ struct lock_class_key *key; -+ } a[] = { -+ { .name = "&sbinfo->si_rwsem" }, -+ { .name = "&finfo->fi_rwsem" }, -+ { .name = "&dinfo->di_rwsem" }, -+ { .name = "&iinfo->ii_rwsem" } -+ }; -+ static int set; -+ int i; -+ -+ /* lockless read from 'set.' see below */ -+ if (set == ARRAY_SIZE(a)) { -+ for (i = 0; i < ARRAY_SIZE(a); i++) -+ if (a[i].key == key) -+ goto match; -+ goto unmatch; -+ } -+ -+ spin_lock(&spin); -+ if (set) -+ for (i = 0; i < ARRAY_SIZE(a); i++) -+ if (a[i].key == key) { -+ spin_unlock(&spin); -+ goto match; -+ } -+ for (i = 0; i < ARRAY_SIZE(a); i++) { -+ if (a[i].key) { -+ if (unlikely(a[i].key == key)) { /* rare but possible */ -+ spin_unlock(&spin); -+ goto match; -+ } else -+ continue; -+ } -+ if (strstr(a[i].name, name)) { -+ /* -+ * the order of these three lines is important for the -+ * lockless read above. -+ */ -+ a[i].key = key; -+ spin_unlock(&spin); -+ set++; -+ /* AuDbg("%d, %s\n", set, name); */ -+ goto match; -+ } -+ } -+ spin_unlock(&spin); -+ goto unmatch; -+ -+match: -+ return 1; -+unmatch: -+ return 0; -+} -+ -+static int au_wkq_lockdep_alloc(struct au_wkinfo *wkinfo) -+{ -+ int err, n; -+ struct task_struct *curr; -+ struct held_lock **hl, *held_locks, *p; -+ -+ err = 0; -+ curr = current; -+ wkinfo->dont_check = lockdep_recursing(curr); -+ if (wkinfo->dont_check) -+ goto out; -+ n = curr->lockdep_depth; -+ if (!n) -+ goto out; -+ -+ err = -ENOMEM; -+ wkinfo->hlock = kmalloc_array(n + 1, sizeof(*wkinfo->hlock), GFP_NOFS); -+ if (unlikely(!wkinfo->hlock)) -+ goto out; -+ -+ err = 0; -+#if 0 /* left for debugging */ -+ if (0 && au_debug_test()) -+ lockdep_print_held_locks(curr); -+#endif -+ held_locks = curr->held_locks; -+ hl = wkinfo->hlock; -+ while (n--) { -+ p = held_locks++; -+ if (au_wkq_lockdep_test(p->instance->key, p->instance->name)) -+ *hl++ = p; -+ } -+ *hl = NULL; -+ -+out: -+ return err; -+} -+ -+static void au_wkq_lockdep_free(struct au_wkinfo *wkinfo) -+{ -+ au_kfree_try_rcu(wkinfo->hlock); -+} -+ -+static void au_wkq_lockdep_pre(struct au_wkinfo *wkinfo) -+{ -+ struct held_lock *p, **hl = wkinfo->hlock; -+ int subclass; -+ -+ if (wkinfo->dont_check) -+ lockdep_off(); -+ if (!hl) -+ return; -+ while ((p = *hl++)) { /* assignment */ -+ subclass = lockdep_hlock_class(p)->subclass; -+ /* AuDbg("%s, %d\n", p->instance->name, subclass); */ -+ if (p->read) -+ rwsem_acquire_read(p->instance, subclass, 0, -+ /*p->acquire_ip*/_RET_IP_); -+ else -+ rwsem_acquire(p->instance, subclass, 0, -+ /*p->acquire_ip*/_RET_IP_); -+ } -+} -+ -+static void au_wkq_lockdep_post(struct au_wkinfo *wkinfo) -+{ -+ struct held_lock *p, **hl = wkinfo->hlock; -+ -+ if (wkinfo->dont_check) -+ lockdep_on(); -+ if (!hl) -+ return; -+ while ((p = *hl++)) /* assignment */ -+ rwsem_release(p->instance, /*p->acquire_ip*/_RET_IP_); -+} -+#endif -+ -+static void wkq_func(struct work_struct *wk) -+{ -+ struct au_wkinfo *wkinfo = container_of(wk, struct au_wkinfo, wk); -+ -+ AuDebugOn(!uid_eq(current_fsuid(), GLOBAL_ROOT_UID)); -+ AuDebugOn(rlimit(RLIMIT_FSIZE) != RLIM_INFINITY); -+ -+ au_wkq_lockdep_pre(wkinfo); -+ wkinfo->func(wkinfo->args); -+ au_wkq_lockdep_post(wkinfo); -+ if (au_ftest_wkq(wkinfo->flags, WAIT)) -+ complete(wkinfo->comp); -+ else { -+ kobject_put(wkinfo->kobj); -+ module_put(THIS_MODULE); /* todo: ?? */ -+ au_kfree_rcu(wkinfo); -+ } -+} -+ -+/* -+ * Since struct completion is large, try allocating it dynamically. -+ */ -+#define AuWkqCompDeclare(name) struct completion *comp = NULL -+ -+static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp) -+{ -+ *comp = kmalloc(sizeof(**comp), GFP_NOFS); -+ if (*comp) { -+ init_completion(*comp); -+ wkinfo->comp = *comp; -+ return 0; -+ } -+ return -ENOMEM; -+} -+ -+static void au_wkq_comp_free(struct completion *comp) -+{ -+ au_kfree_rcu(comp); -+} -+ -+static void au_wkq_run(struct au_wkinfo *wkinfo) -+{ -+ if (au_ftest_wkq(wkinfo->flags, NEST)) { -+ if (au_wkq_test()) { -+ AuWarn1("wkq from wkq, unless silly-rename on NFS," -+ " due to a dead dir by UDBA," -+ " or async xino write?\n"); -+ AuDebugOn(au_ftest_wkq(wkinfo->flags, WAIT)); -+ } -+ } else -+ au_dbg_verify_kthread(); -+ -+ if (au_ftest_wkq(wkinfo->flags, WAIT)) { -+ INIT_WORK_ONSTACK(&wkinfo->wk, wkq_func); -+ queue_work(au_wkq, &wkinfo->wk); -+ } else { -+ INIT_WORK(&wkinfo->wk, wkq_func); -+ schedule_work(&wkinfo->wk); -+ } -+} -+ -+/* -+ * Be careful. It is easy to make deadlock happen. -+ * processA: lock, wkq and wait -+ * processB: wkq and wait, lock in wkq -+ * --> deadlock -+ */ -+int au_wkq_do_wait(unsigned int flags, au_wkq_func_t func, void *args) -+{ -+ int err; -+ AuWkqCompDeclare(comp); -+ struct au_wkinfo wkinfo = { -+ .flags = flags, -+ .func = func, -+ .args = args -+ }; -+ -+ err = au_wkq_comp_alloc(&wkinfo, &comp); -+ if (unlikely(err)) -+ goto out; -+ err = au_wkq_lockdep_alloc(&wkinfo); -+ if (unlikely(err)) -+ goto out_comp; -+ if (!err) { -+ au_wkq_run(&wkinfo); -+ /* no timeout, no interrupt */ -+ wait_for_completion(wkinfo.comp); -+ } -+ au_wkq_lockdep_free(&wkinfo); -+ -+out_comp: -+ au_wkq_comp_free(comp); -+out: -+ destroy_work_on_stack(&wkinfo.wk); -+ return err; -+} -+ -+/* -+ * Note: dget/dput() in func for aufs dentries are not supported. It will be a -+ * problem in a concurrent umounting. -+ */ -+int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb, -+ unsigned int flags) -+{ -+ int err; -+ struct au_wkinfo *wkinfo; -+ -+ atomic_inc(&au_sbi(sb)->si_nowait.nw_len); -+ -+ /* -+ * wkq_func() must free this wkinfo. -+ * it highly depends upon the implementation of workqueue. -+ */ -+ err = 0; -+ wkinfo = kmalloc(sizeof(*wkinfo), GFP_NOFS); -+ if (wkinfo) { -+ wkinfo->kobj = &au_sbi(sb)->si_kobj; -+ wkinfo->flags = flags & ~AuWkq_WAIT; -+ wkinfo->func = func; -+ wkinfo->args = args; -+ wkinfo->comp = NULL; -+ au_wkq_lockdep_init(wkinfo); -+ kobject_get(wkinfo->kobj); -+ __module_get(THIS_MODULE); /* todo: ?? */ -+ -+ au_wkq_run(wkinfo); -+ } else { -+ err = -ENOMEM; -+ au_nwt_done(&au_sbi(sb)->si_nowait); -+ } -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+void au_nwt_init(struct au_nowait_tasks *nwt) -+{ -+ atomic_set(&nwt->nw_len, 0); -+ /* smp_mb(); */ /* atomic_set */ -+ init_waitqueue_head(&nwt->nw_wq); -+} -+ -+void au_wkq_fin(void) -+{ -+ destroy_workqueue(au_wkq); -+} -+ -+int __init au_wkq_init(void) -+{ -+ int err; -+ -+ err = 0; -+ au_wkq = alloc_workqueue(AUFS_WKQ_NAME, 0, WQ_DFL_ACTIVE); -+ if (IS_ERR(au_wkq)) -+ err = PTR_ERR(au_wkq); -+ else if (!au_wkq) -+ err = -ENOMEM; -+ -+ return err; -+} -diff -Nurp linux-5.6.3/fs/aufs/wkq.h linux-5.6.3-aufs/fs/aufs/wkq.h ---- linux-5.6.3/fs/aufs/wkq.h 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/wkq.h 2020-04-10 12:40:52.193049549 +0300 -@@ -0,0 +1,76 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * workqueue for asynchronous/super-io operations -+ * todo: try new credentials management scheme -+ */ -+ -+#ifndef __AUFS_WKQ_H__ -+#define __AUFS_WKQ_H__ -+ -+#ifdef __KERNEL__ -+ -+#include -+ -+struct super_block; -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * in the next operation, wait for the 'nowait' tasks in system-wide workqueue -+ */ -+struct au_nowait_tasks { -+ atomic_t nw_len; -+ wait_queue_head_t nw_wq; -+}; -+ -+/* ---------------------------------------------------------------------- */ -+ -+typedef void (*au_wkq_func_t)(void *args); -+ -+/* wkq flags */ -+#define AuWkq_WAIT 1 -+#define AuWkq_NEST (1 << 1) -+#define au_ftest_wkq(flags, name) ((flags) & AuWkq_##name) -+#define au_fset_wkq(flags, name) \ -+ do { (flags) |= AuWkq_##name; } while (0) -+#define au_fclr_wkq(flags, name) \ -+ do { (flags) &= ~AuWkq_##name; } while (0) -+ -+/* wkq.c */ -+int au_wkq_do_wait(unsigned int flags, au_wkq_func_t func, void *args); -+int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb, -+ unsigned int flags); -+void au_nwt_init(struct au_nowait_tasks *nwt); -+int __init au_wkq_init(void); -+void au_wkq_fin(void); -+ -+/* ---------------------------------------------------------------------- */ -+ -+static inline int au_wkq_test(void) -+{ -+ return current->flags & PF_WQ_WORKER; -+} -+ -+static inline int au_wkq_wait(au_wkq_func_t func, void *args) -+{ -+ return au_wkq_do_wait(AuWkq_WAIT, func, args); -+} -+ -+static inline void au_nwt_done(struct au_nowait_tasks *nwt) -+{ -+ if (atomic_dec_and_test(&nwt->nw_len)) -+ wake_up_all(&nwt->nw_wq); -+} -+ -+static inline int au_nwt_flush(struct au_nowait_tasks *nwt) -+{ -+ wait_event(nwt->nw_wq, !atomic_read(&nwt->nw_len)); -+ return 0; -+} -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_WKQ_H__ */ -diff -Nurp linux-5.6.3/fs/aufs/xattr.c linux-5.6.3-aufs/fs/aufs/xattr.c ---- linux-5.6.3/fs/aufs/xattr.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/xattr.c 2020-04-10 12:40:52.193049549 +0300 -@@ -0,0 +1,343 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2014-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * handling xattr functions -+ */ -+ -+#include -+#include -+#include -+#include "aufs.h" -+ -+static int au_xattr_ignore(int err, char *name, unsigned int ignore_flags) -+{ -+ if (!ignore_flags) -+ goto out; -+ switch (err) { -+ case -ENOMEM: -+ case -EDQUOT: -+ goto out; -+ } -+ -+ if ((ignore_flags & AuBrAttr_ICEX) == AuBrAttr_ICEX) { -+ err = 0; -+ goto out; -+ } -+ -+#define cmp(brattr, prefix) do { \ -+ if (!strncmp(name, XATTR_##prefix##_PREFIX, \ -+ XATTR_##prefix##_PREFIX_LEN)) { \ -+ if (ignore_flags & AuBrAttr_ICEX_##brattr) \ -+ err = 0; \ -+ goto out; \ -+ } \ -+ } while (0) -+ -+ cmp(SEC, SECURITY); -+ cmp(SYS, SYSTEM); -+ cmp(TR, TRUSTED); -+ cmp(USR, USER); -+#undef cmp -+ -+ if (ignore_flags & AuBrAttr_ICEX_OTH) -+ err = 0; -+ -+out: -+ return err; -+} -+ -+static const int au_xattr_out_of_list = AuBrAttr_ICEX_OTH << 1; -+ -+static int au_do_cpup_xattr(struct dentry *h_dst, struct dentry *h_src, -+ char *name, char **buf, unsigned int ignore_flags, -+ unsigned int verbose) -+{ -+ int err; -+ ssize_t ssz; -+ struct inode *h_idst; -+ -+ ssz = vfs_getxattr_alloc(h_src, name, buf, 0, GFP_NOFS); -+ err = ssz; -+ if (unlikely(err <= 0)) { -+ if (err == -ENODATA -+ || (err == -EOPNOTSUPP -+ && ((ignore_flags & au_xattr_out_of_list) -+ || (au_test_nfs_noacl(d_inode(h_src)) -+ && (!strcmp(name, XATTR_NAME_POSIX_ACL_ACCESS) -+ || !strcmp(name, -+ XATTR_NAME_POSIX_ACL_DEFAULT)))) -+ )) -+ err = 0; -+ if (err && (verbose || au_debug_test())) -+ pr_err("%s, err %d\n", name, err); -+ goto out; -+ } -+ -+ /* unlock it temporary */ -+ h_idst = d_inode(h_dst); -+ inode_unlock(h_idst); -+ err = vfsub_setxattr(h_dst, name, *buf, ssz, /*flags*/0); -+ inode_lock_nested(h_idst, AuLsc_I_CHILD2); -+ if (unlikely(err)) { -+ if (verbose || au_debug_test()) -+ pr_err("%s, err %d\n", name, err); -+ err = au_xattr_ignore(err, name, ignore_flags); -+ } -+ -+out: -+ return err; -+} -+ -+int au_cpup_xattr(struct dentry *h_dst, struct dentry *h_src, int ignore_flags, -+ unsigned int verbose) -+{ -+ int err, unlocked, acl_access, acl_default; -+ ssize_t ssz; -+ struct inode *h_isrc, *h_idst; -+ char *value, *p, *o, *e; -+ -+ /* try stopping to update the source inode while we are referencing */ -+ /* there should not be the parent-child relationship between them */ -+ h_isrc = d_inode(h_src); -+ h_idst = d_inode(h_dst); -+ inode_unlock(h_idst); -+ inode_lock_shared_nested(h_isrc, AuLsc_I_CHILD); -+ inode_lock_nested(h_idst, AuLsc_I_CHILD2); -+ unlocked = 0; -+ -+ /* some filesystems don't list POSIX ACL, for example tmpfs */ -+ ssz = vfs_listxattr(h_src, NULL, 0); -+ err = ssz; -+ if (unlikely(err < 0)) { -+ AuTraceErr(err); -+ if (err == -ENODATA -+ || err == -EOPNOTSUPP) -+ err = 0; /* ignore */ -+ goto out; -+ } -+ -+ err = 0; -+ p = NULL; -+ o = NULL; -+ if (ssz) { -+ err = -ENOMEM; -+ p = kmalloc(ssz, GFP_NOFS); -+ o = p; -+ if (unlikely(!p)) -+ goto out; -+ err = vfs_listxattr(h_src, p, ssz); -+ } -+ inode_unlock_shared(h_isrc); -+ unlocked = 1; -+ AuDbg("err %d, ssz %zd\n", err, ssz); -+ if (unlikely(err < 0)) -+ goto out_free; -+ -+ err = 0; -+ e = p + ssz; -+ value = NULL; -+ acl_access = 0; -+ acl_default = 0; -+ while (!err && p < e) { -+ acl_access |= !strncmp(p, XATTR_NAME_POSIX_ACL_ACCESS, -+ sizeof(XATTR_NAME_POSIX_ACL_ACCESS) - 1); -+ acl_default |= !strncmp(p, XATTR_NAME_POSIX_ACL_DEFAULT, -+ sizeof(XATTR_NAME_POSIX_ACL_DEFAULT) -+ - 1); -+ err = au_do_cpup_xattr(h_dst, h_src, p, &value, ignore_flags, -+ verbose); -+ p += strlen(p) + 1; -+ } -+ AuTraceErr(err); -+ ignore_flags |= au_xattr_out_of_list; -+ if (!err && !acl_access) { -+ err = au_do_cpup_xattr(h_dst, h_src, -+ XATTR_NAME_POSIX_ACL_ACCESS, &value, -+ ignore_flags, verbose); -+ AuTraceErr(err); -+ } -+ if (!err && !acl_default) { -+ err = au_do_cpup_xattr(h_dst, h_src, -+ XATTR_NAME_POSIX_ACL_DEFAULT, &value, -+ ignore_flags, verbose); -+ AuTraceErr(err); -+ } -+ -+ au_kfree_try_rcu(value); -+ -+out_free: -+ au_kfree_try_rcu(o); -+out: -+ if (!unlocked) -+ inode_unlock_shared(h_isrc); -+ AuTraceErr(err); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int au_smack_reentering(struct super_block *sb) -+{ -+#if IS_ENABLED(CONFIG_SECURITY_SMACK) -+ /* -+ * as a part of lookup, smack_d_instantiate() is called, and it calls -+ * i_op->getxattr(). ouch. -+ */ -+ return si_pid_test(sb); -+#else -+ return 0; -+#endif -+} -+ -+enum { -+ AU_XATTR_LIST, -+ AU_XATTR_GET -+}; -+ -+struct au_lgxattr { -+ int type; -+ union { -+ struct { -+ char *list; -+ size_t size; -+ } list; -+ struct { -+ const char *name; -+ void *value; -+ size_t size; -+ } get; -+ } u; -+}; -+ -+static ssize_t au_lgxattr(struct dentry *dentry, struct au_lgxattr *arg) -+{ -+ ssize_t err; -+ int reenter; -+ struct path h_path; -+ struct super_block *sb; -+ -+ sb = dentry->d_sb; -+ reenter = au_smack_reentering(sb); -+ if (!reenter) { -+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM); -+ if (unlikely(err)) -+ goto out; -+ } -+ err = au_h_path_getattr(dentry, /*force*/1, &h_path, reenter); -+ if (unlikely(err)) -+ goto out_si; -+ if (unlikely(!h_path.dentry)) -+ /* illegally overlapped or something */ -+ goto out_di; /* pretending success */ -+ -+ /* always topmost entry only */ -+ switch (arg->type) { -+ case AU_XATTR_LIST: -+ err = vfs_listxattr(h_path.dentry, -+ arg->u.list.list, arg->u.list.size); -+ break; -+ case AU_XATTR_GET: -+ AuDebugOn(d_is_negative(h_path.dentry)); -+ err = vfs_getxattr(h_path.dentry, -+ arg->u.get.name, arg->u.get.value, -+ arg->u.get.size); -+ break; -+ } -+ -+out_di: -+ if (!reenter) -+ di_read_unlock(dentry, AuLock_IR); -+out_si: -+ if (!reenter) -+ si_read_unlock(sb); -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+ssize_t aufs_listxattr(struct dentry *dentry, char *list, size_t size) -+{ -+ struct au_lgxattr arg = { -+ .type = AU_XATTR_LIST, -+ .u.list = { -+ .list = list, -+ .size = size -+ }, -+ }; -+ -+ return au_lgxattr(dentry, &arg); -+} -+ -+static ssize_t au_getxattr(struct dentry *dentry, -+ struct inode *inode __maybe_unused, -+ const char *name, void *value, size_t size) -+{ -+ struct au_lgxattr arg = { -+ .type = AU_XATTR_GET, -+ .u.get = { -+ .name = name, -+ .value = value, -+ .size = size -+ }, -+ }; -+ -+ return au_lgxattr(dentry, &arg); -+} -+ -+static int au_setxattr(struct dentry *dentry, struct inode *inode, -+ const char *name, const void *value, size_t size, -+ int flags) -+{ -+ struct au_sxattr arg = { -+ .type = AU_XATTR_SET, -+ .u.set = { -+ .name = name, -+ .value = value, -+ .size = size, -+ .flags = flags -+ }, -+ }; -+ -+ return au_sxattr(dentry, inode, &arg); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int au_xattr_get(const struct xattr_handler *handler, -+ struct dentry *dentry, struct inode *inode, -+ const char *name, void *buffer, size_t size) -+{ -+ return au_getxattr(dentry, inode, name, buffer, size); -+} -+ -+static int au_xattr_set(const struct xattr_handler *handler, -+ struct dentry *dentry, struct inode *inode, -+ const char *name, const void *value, size_t size, -+ int flags) -+{ -+ return au_setxattr(dentry, inode, name, value, size, flags); -+} -+ -+static const struct xattr_handler au_xattr_handler = { -+ .name = "", -+ .prefix = "", -+ .get = au_xattr_get, -+ .set = au_xattr_set -+}; -+ -+static const struct xattr_handler *au_xattr_handlers[] = { -+#ifdef CONFIG_FS_POSIX_ACL -+ &posix_acl_access_xattr_handler, -+ &posix_acl_default_xattr_handler, -+#endif -+ &au_xattr_handler, /* must be last */ -+ NULL -+}; -+ -+void au_xattr_init(struct super_block *sb) -+{ -+ sb->s_xattr = au_xattr_handlers; -+} -diff -Nurp linux-5.6.3/fs/aufs/xino.c linux-5.6.3-aufs/fs/aufs/xino.c ---- linux-5.6.3/fs/aufs/xino.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/fs/aufs/xino.c 2020-04-10 12:40:52.193049549 +0300 -@@ -0,0 +1,1952 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * external inode number translation table and bitmap -+ * -+ * things to consider -+ * - the lifetime -+ * + au_xino object -+ * + XINO files (xino, xib, xigen) -+ * + dynamic debugfs entries (xiN) -+ * + static debugfs entries (xib, xigen) -+ * + static sysfs entry (xi_path) -+ * - several entry points to handle them. -+ * + mount(2) without xino option (default) -+ * + mount(2) with xino option -+ * + mount(2) with noxino option -+ * + umount(2) -+ * + remount with add/del branches -+ * + remount with xino/noxino options -+ */ -+ -+#include -+#include -+#include "aufs.h" -+ -+static aufs_bindex_t sbr_find_shared(struct super_block *sb, aufs_bindex_t btop, -+ aufs_bindex_t bbot, -+ struct super_block *h_sb) -+{ -+ /* todo: try binary-search if the branches are many */ -+ for (; btop <= bbot; btop++) -+ if (h_sb == au_sbr_sb(sb, btop)) -+ return btop; -+ return -1; -+} -+ -+/* -+ * find another branch who is on the same filesystem of the specified -+ * branch{@btgt}. search until @bbot. -+ */ -+static aufs_bindex_t is_sb_shared(struct super_block *sb, aufs_bindex_t btgt, -+ aufs_bindex_t bbot) -+{ -+ aufs_bindex_t bindex; -+ struct super_block *tgt_sb; -+ -+ tgt_sb = au_sbr_sb(sb, btgt); -+ bindex = sbr_find_shared(sb, /*btop*/0, btgt - 1, tgt_sb); -+ if (bindex < 0) -+ bindex = sbr_find_shared(sb, btgt + 1, bbot, tgt_sb); -+ -+ return bindex; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * stop unnecessary notify events at creating xino files -+ */ -+ -+aufs_bindex_t au_xi_root(struct super_block *sb, struct dentry *dentry) -+{ -+ aufs_bindex_t bfound, bindex, bbot; -+ struct dentry *parent; -+ struct au_branch *br; -+ -+ bfound = -1; -+ parent = dentry->d_parent; /* safe d_parent access */ -+ bbot = au_sbbot(sb); -+ for (bindex = 0; bindex <= bbot; bindex++) { -+ br = au_sbr(sb, bindex); -+ if (au_br_dentry(br) == parent) { -+ bfound = bindex; -+ break; -+ } -+ } -+ -+ AuDbg("bfound b%d\n", bfound); -+ return bfound; -+} -+ -+struct au_xino_lock_dir { -+ struct au_hinode *hdir; -+ struct dentry *parent; -+ struct inode *dir; -+}; -+ -+static struct dentry *au_dget_parent_lock(struct dentry *dentry, -+ unsigned int lsc) -+{ -+ struct dentry *parent; -+ struct inode *dir; -+ -+ parent = dget_parent(dentry); -+ dir = d_inode(parent); -+ inode_lock_nested(dir, lsc); -+#if 0 /* it should not happen */ -+ spin_lock(&dentry->d_lock); -+ if (unlikely(dentry->d_parent != parent)) { -+ spin_unlock(&dentry->d_lock); -+ inode_unlock(dir); -+ dput(parent); -+ parent = NULL; -+ goto out; -+ } -+ spin_unlock(&dentry->d_lock); -+ -+out: -+#endif -+ return parent; -+} -+ -+static void au_xino_lock_dir(struct super_block *sb, struct path *xipath, -+ struct au_xino_lock_dir *ldir) -+{ -+ aufs_bindex_t bindex; -+ -+ ldir->hdir = NULL; -+ bindex = au_xi_root(sb, xipath->dentry); -+ if (bindex >= 0) { -+ /* rw branch root */ -+ ldir->hdir = au_hi(d_inode(sb->s_root), bindex); -+ au_hn_inode_lock_nested(ldir->hdir, AuLsc_I_PARENT); -+ } else { -+ /* other */ -+ ldir->parent = au_dget_parent_lock(xipath->dentry, -+ AuLsc_I_PARENT); -+ ldir->dir = d_inode(ldir->parent); -+ } -+} -+ -+static void au_xino_unlock_dir(struct au_xino_lock_dir *ldir) -+{ -+ if (ldir->hdir) -+ au_hn_inode_unlock(ldir->hdir); -+ else { -+ inode_unlock(ldir->dir); -+ dput(ldir->parent); -+ } -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * create and set a new xino file -+ */ -+struct file *au_xino_create(struct super_block *sb, char *fpath, int silent, -+ int wbrtop) -+{ -+ struct file *file; -+ struct dentry *h_parent, *d; -+ struct inode *h_dir, *inode; -+ int err; -+ static DEFINE_MUTEX(mtx); -+ -+ /* -+ * at mount-time, and the xino file is the default path, -+ * hnotify is disabled so we have no notify events to ignore. -+ * when a user specified the xino, we cannot get au_hdir to be ignored. -+ */ -+ if (!wbrtop) -+ mutex_lock(&mtx); -+ file = vfsub_filp_open(fpath, O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE -+ /* | __FMODE_NONOTIFY */, -+ 0666); -+ if (IS_ERR(file)) { -+ if (!wbrtop) -+ mutex_unlock(&mtx); -+ if (!silent) -+ pr_err("open %s(%ld)\n", fpath, PTR_ERR(file)); -+ return file; -+ } -+ -+ /* keep file count */ -+ err = 0; -+ d = file->f_path.dentry; -+ h_parent = au_dget_parent_lock(d, AuLsc_I_PARENT); -+ if (!wbrtop) -+ mutex_unlock(&mtx); -+ /* mnt_want_write() is unnecessary here */ -+ h_dir = d_inode(h_parent); -+ inode = file_inode(file); -+ /* no delegation since it is just created */ -+ if (inode->i_nlink) -+ err = vfsub_unlink(h_dir, &file->f_path, /*delegated*/NULL, -+ /*force*/0); -+ inode_unlock(h_dir); -+ dput(h_parent); -+ if (unlikely(err)) { -+ if (!silent) -+ pr_err("unlink %s(%d)\n", fpath, err); -+ goto out; -+ } -+ -+ err = -EINVAL; -+ if (unlikely(sb == d->d_sb)) { -+ if (!silent) -+ pr_err("%s must be outside\n", fpath); -+ goto out; -+ } -+ if (unlikely(au_test_fs_bad_xino(d->d_sb))) { -+ if (!silent) -+ pr_err("xino doesn't support %s(%s)\n", -+ fpath, au_sbtype(d->d_sb)); -+ goto out; -+ } -+ return file; /* success */ -+ -+out: -+ fput(file); -+ file = ERR_PTR(err); -+ return file; -+} -+ -+/* -+ * create a new xinofile at the same place/path as @base. -+ */ -+struct file *au_xino_create2(struct super_block *sb, struct path *base, -+ struct file *copy_src) -+{ -+ struct file *file; -+ struct dentry *dentry, *parent; -+ struct inode *dir, *delegated; -+ struct qstr *name; -+ struct path path; -+ int err, do_unlock; -+ struct au_xino_lock_dir ldir; -+ -+ do_unlock = 1; -+ au_xino_lock_dir(sb, base, &ldir); -+ dentry = base->dentry; -+ parent = dentry->d_parent; /* dir inode is locked */ -+ dir = d_inode(parent); -+ IMustLock(dir); -+ -+ name = &dentry->d_name; -+ path.dentry = vfsub_lookup_one_len(name->name, parent, name->len); -+ if (IS_ERR(path.dentry)) { -+ file = (void *)path.dentry; -+ pr_err("%pd lookup err %ld\n", dentry, PTR_ERR(path.dentry)); -+ goto out; -+ } -+ -+ /* no need to mnt_want_write() since we call dentry_open() later */ -+ err = vfs_create(dir, path.dentry, 0666, NULL); -+ if (unlikely(err)) { -+ file = ERR_PTR(err); -+ pr_err("%pd create err %d\n", dentry, err); -+ goto out_dput; -+ } -+ -+ path.mnt = base->mnt; -+ file = vfsub_dentry_open(&path, -+ O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE -+ /* | __FMODE_NONOTIFY */); -+ if (IS_ERR(file)) { -+ pr_err("%pd open err %ld\n", dentry, PTR_ERR(file)); -+ goto out_dput; -+ } -+ -+ delegated = NULL; -+ err = vfsub_unlink(dir, &file->f_path, &delegated, /*force*/0); -+ au_xino_unlock_dir(&ldir); -+ do_unlock = 0; -+ if (unlikely(err == -EWOULDBLOCK)) { -+ pr_warn("cannot retry for NFSv4 delegation" -+ " for an internal unlink\n"); -+ iput(delegated); -+ } -+ if (unlikely(err)) { -+ pr_err("%pd unlink err %d\n", dentry, err); -+ goto out_fput; -+ } -+ -+ if (copy_src) { -+ /* no one can touch copy_src xino */ -+ err = au_copy_file(file, copy_src, vfsub_f_size_read(copy_src)); -+ if (unlikely(err)) { -+ pr_err("%pd copy err %d\n", dentry, err); -+ goto out_fput; -+ } -+ } -+ goto out_dput; /* success */ -+ -+out_fput: -+ fput(file); -+ file = ERR_PTR(err); -+out_dput: -+ dput(path.dentry); -+out: -+ if (do_unlock) -+ au_xino_unlock_dir(&ldir); -+ return file; -+} -+ -+struct file *au_xino_file1(struct au_xino *xi) -+{ -+ struct file *file; -+ unsigned int u, nfile; -+ -+ file = NULL; -+ nfile = xi->xi_nfile; -+ for (u = 0; u < nfile; u++) { -+ file = xi->xi_file[u]; -+ if (file) -+ break; -+ } -+ -+ return file; -+} -+ -+static int au_xino_file_set(struct au_xino *xi, int idx, struct file *file) -+{ -+ int err; -+ struct file *f; -+ void *p; -+ -+ if (file) -+ get_file(file); -+ -+ err = 0; -+ f = NULL; -+ if (idx < xi->xi_nfile) { -+ f = xi->xi_file[idx]; -+ if (f) -+ fput(f); -+ } else { -+ p = au_kzrealloc(xi->xi_file, -+ sizeof(*xi->xi_file) * xi->xi_nfile, -+ sizeof(*xi->xi_file) * (idx + 1), -+ GFP_NOFS, /*may_shrink*/0); -+ if (p) { -+ MtxMustLock(&xi->xi_mtx); -+ xi->xi_file = p; -+ xi->xi_nfile = idx + 1; -+ } else { -+ err = -ENOMEM; -+ if (file) -+ fput(file); -+ goto out; -+ } -+ } -+ xi->xi_file[idx] = file; -+ -+out: -+ return err; -+} -+ -+/* -+ * if @xinew->xi is not set, then create new xigen file. -+ */ -+struct file *au_xi_new(struct super_block *sb, struct au_xi_new *xinew) -+{ -+ struct file *file; -+ int err; -+ -+ SiMustAnyLock(sb); -+ -+ file = au_xino_create2(sb, xinew->base, xinew->copy_src); -+ if (IS_ERR(file)) { -+ err = PTR_ERR(file); -+ pr_err("%s[%d], err %d\n", -+ xinew->xi ? "xino" : "xigen", -+ xinew->idx, err); -+ goto out; -+ } -+ -+ if (xinew->xi) -+ err = au_xino_file_set(xinew->xi, xinew->idx, file); -+ else { -+ BUG(); -+ /* todo: make xigen file an array */ -+ /* err = au_xigen_file_set(sb, xinew->idx, file); */ -+ } -+ fput(file); -+ if (unlikely(err)) -+ file = ERR_PTR(err); -+ -+out: -+ return file; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * truncate xino files -+ */ -+static int au_xino_do_trunc(struct super_block *sb, aufs_bindex_t bindex, -+ int idx, struct kstatfs *st) -+{ -+ int err; -+ blkcnt_t blocks; -+ struct file *file, *new_xino; -+ struct au_xi_new xinew = { -+ .idx = idx -+ }; -+ -+ err = 0; -+ xinew.xi = au_sbr(sb, bindex)->br_xino; -+ file = au_xino_file(xinew.xi, idx); -+ if (!file) -+ goto out; -+ -+ xinew.base = &file->f_path; -+ err = vfs_statfs(xinew.base, st); -+ if (unlikely(err)) { -+ AuErr1("statfs err %d, ignored\n", err); -+ err = 0; -+ goto out; -+ } -+ -+ blocks = file_inode(file)->i_blocks; -+ pr_info("begin truncating xino(b%d-%d), ib%llu, %llu/%llu free blks\n", -+ bindex, idx, (u64)blocks, st->f_bfree, st->f_blocks); -+ -+ xinew.copy_src = file; -+ new_xino = au_xi_new(sb, &xinew); -+ if (IS_ERR(new_xino)) { -+ err = PTR_ERR(new_xino); -+ pr_err("xino(b%d-%d), err %d, ignored\n", bindex, idx, err); -+ goto out; -+ } -+ -+ err = vfs_statfs(&new_xino->f_path, st); -+ if (!err) -+ pr_info("end truncating xino(b%d-%d), ib%llu, %llu/%llu free blks\n", -+ bindex, idx, (u64)file_inode(new_xino)->i_blocks, -+ st->f_bfree, st->f_blocks); -+ else { -+ AuErr1("statfs err %d, ignored\n", err); -+ err = 0; -+ } -+ -+out: -+ return err; -+} -+ -+int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex, int idx_begin) -+{ -+ int err, i; -+ unsigned long jiffy; -+ aufs_bindex_t bbot; -+ struct kstatfs *st; -+ struct au_branch *br; -+ struct au_xino *xi; -+ -+ err = -ENOMEM; -+ st = kmalloc(sizeof(*st), GFP_NOFS); -+ if (unlikely(!st)) -+ goto out; -+ -+ err = -EINVAL; -+ bbot = au_sbbot(sb); -+ if (unlikely(bindex < 0 || bbot < bindex)) -+ goto out_st; -+ -+ err = 0; -+ jiffy = jiffies; -+ br = au_sbr(sb, bindex); -+ xi = br->br_xino; -+ for (i = idx_begin; !err && i < xi->xi_nfile; i++) -+ err = au_xino_do_trunc(sb, bindex, i, st); -+ if (!err) -+ au_sbi(sb)->si_xino_jiffy = jiffy; -+ -+out_st: -+ au_kfree_rcu(st); -+out: -+ return err; -+} -+ -+struct xino_do_trunc_args { -+ struct super_block *sb; -+ struct au_branch *br; -+ int idx; -+}; -+ -+static void xino_do_trunc(void *_args) -+{ -+ struct xino_do_trunc_args *args = _args; -+ struct super_block *sb; -+ struct au_branch *br; -+ struct inode *dir; -+ int err, idx; -+ aufs_bindex_t bindex; -+ -+ err = 0; -+ sb = args->sb; -+ dir = d_inode(sb->s_root); -+ br = args->br; -+ idx = args->idx; -+ -+ si_noflush_write_lock(sb); -+ ii_read_lock_parent(dir); -+ bindex = au_br_index(sb, br->br_id); -+ err = au_xino_trunc(sb, bindex, idx); -+ ii_read_unlock(dir); -+ if (unlikely(err)) -+ pr_warn("err b%d, (%d)\n", bindex, err); -+ atomic_dec(&br->br_xino->xi_truncating); -+ au_lcnt_dec(&br->br_count); -+ si_write_unlock(sb); -+ au_nwt_done(&au_sbi(sb)->si_nowait); -+ au_kfree_rcu(args); -+} -+ -+/* -+ * returns the index in the xi_file array whose corresponding file is necessary -+ * to truncate, or -1 which means no need to truncate. -+ */ -+static int xino_trunc_test(struct super_block *sb, struct au_branch *br) -+{ -+ int err; -+ unsigned int u; -+ struct kstatfs st; -+ struct au_sbinfo *sbinfo; -+ struct au_xino *xi; -+ struct file *file; -+ -+ /* todo: si_xino_expire and the ratio should be customizable */ -+ sbinfo = au_sbi(sb); -+ if (time_before(jiffies, -+ sbinfo->si_xino_jiffy + sbinfo->si_xino_expire)) -+ return -1; -+ -+ /* truncation border */ -+ xi = br->br_xino; -+ for (u = 0; u < xi->xi_nfile; u++) { -+ file = au_xino_file(xi, u); -+ if (!file) -+ continue; -+ -+ err = vfs_statfs(&file->f_path, &st); -+ if (unlikely(err)) { -+ AuErr1("statfs err %d, ignored\n", err); -+ return -1; -+ } -+ if (div64_u64(st.f_bfree * 100, st.f_blocks) -+ >= AUFS_XINO_DEF_TRUNC) -+ return u; -+ } -+ -+ return -1; -+} -+ -+static void xino_try_trunc(struct super_block *sb, struct au_branch *br) -+{ -+ int idx; -+ struct xino_do_trunc_args *args; -+ int wkq_err; -+ -+ idx = xino_trunc_test(sb, br); -+ if (idx < 0) -+ return; -+ -+ if (atomic_inc_return(&br->br_xino->xi_truncating) > 1) -+ goto out; -+ -+ /* lock and kfree() will be called in trunc_xino() */ -+ args = kmalloc(sizeof(*args), GFP_NOFS); -+ if (unlikely(!args)) { -+ AuErr1("no memory\n"); -+ goto out; -+ } -+ -+ au_lcnt_inc(&br->br_count); -+ args->sb = sb; -+ args->br = br; -+ args->idx = idx; -+ wkq_err = au_wkq_nowait(xino_do_trunc, args, sb, /*flags*/0); -+ if (!wkq_err) -+ return; /* success */ -+ -+ pr_err("wkq %d\n", wkq_err); -+ au_lcnt_dec(&br->br_count); -+ au_kfree_rcu(args); -+ -+out: -+ atomic_dec(&br->br_xino->xi_truncating); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct au_xi_calc { -+ int idx; -+ loff_t pos; -+}; -+ -+static void au_xi_calc(struct super_block *sb, ino_t h_ino, -+ struct au_xi_calc *calc) -+{ -+ loff_t maxent; -+ -+ maxent = au_xi_maxent(sb); -+ calc->idx = div64_u64_rem(h_ino, maxent, &calc->pos); -+ calc->pos *= sizeof(ino_t); -+} -+ -+static int au_xino_do_new_async(struct super_block *sb, struct au_branch *br, -+ struct au_xi_calc *calc) -+{ -+ int err; -+ struct file *file; -+ struct au_xino *xi = br->br_xino; -+ struct au_xi_new xinew = { -+ .xi = xi -+ }; -+ -+ SiMustAnyLock(sb); -+ -+ err = 0; -+ if (!xi) -+ goto out; -+ -+ mutex_lock(&xi->xi_mtx); -+ file = au_xino_file(xi, calc->idx); -+ if (file) -+ goto out_mtx; -+ -+ file = au_xino_file(xi, /*idx*/-1); -+ AuDebugOn(!file); -+ xinew.idx = calc->idx; -+ xinew.base = &file->f_path; -+ /* xinew.copy_src = NULL; */ -+ file = au_xi_new(sb, &xinew); -+ if (IS_ERR(file)) -+ err = PTR_ERR(file); -+ -+out_mtx: -+ mutex_unlock(&xi->xi_mtx); -+out: -+ return err; -+} -+ -+struct au_xino_do_new_async_args { -+ struct super_block *sb; -+ struct au_branch *br; -+ struct au_xi_calc calc; -+ ino_t ino; -+}; -+ -+struct au_xi_writing { -+ struct hlist_bl_node node; -+ ino_t h_ino, ino; -+}; -+ -+static int au_xino_do_write(vfs_writef_t write, struct file *file, -+ struct au_xi_calc *calc, ino_t ino); -+ -+static void au_xino_call_do_new_async(void *args) -+{ -+ struct au_xino_do_new_async_args *a = args; -+ struct au_branch *br; -+ struct super_block *sb; -+ struct au_sbinfo *sbi; -+ struct inode *root; -+ struct file *file; -+ struct au_xi_writing *del, *p; -+ struct hlist_bl_head *hbl; -+ struct hlist_bl_node *pos; -+ int err; -+ -+ br = a->br; -+ sb = a->sb; -+ sbi = au_sbi(sb); -+ si_noflush_read_lock(sb); -+ root = d_inode(sb->s_root); -+ ii_read_lock_child(root); -+ err = au_xino_do_new_async(sb, br, &a->calc); -+ if (unlikely(err)) { -+ AuIOErr("err %d\n", err); -+ goto out; -+ } -+ -+ file = au_xino_file(br->br_xino, a->calc.idx); -+ AuDebugOn(!file); -+ err = au_xino_do_write(sbi->si_xwrite, file, &a->calc, a->ino); -+ if (unlikely(err)) { -+ AuIOErr("err %d\n", err); -+ goto out; -+ } -+ -+ del = NULL; -+ hbl = &br->br_xino->xi_writing; -+ hlist_bl_lock(hbl); -+ au_hbl_for_each(pos, hbl) { -+ p = container_of(pos, struct au_xi_writing, node); -+ if (p->ino == a->ino) { -+ del = p; -+ hlist_bl_del(&p->node); -+ break; -+ } -+ } -+ hlist_bl_unlock(hbl); -+ au_kfree_rcu(del); -+ -+out: -+ au_lcnt_dec(&br->br_count); -+ ii_read_unlock(root); -+ si_read_unlock(sb); -+ au_nwt_done(&sbi->si_nowait); -+ au_kfree_rcu(a); -+} -+ -+/* -+ * create a new xino file asynchronously -+ */ -+static int au_xino_new_async(struct super_block *sb, struct au_branch *br, -+ struct au_xi_calc *calc, ino_t ino) -+{ -+ int err; -+ struct au_xino_do_new_async_args *arg; -+ -+ err = -ENOMEM; -+ arg = kmalloc(sizeof(*arg), GFP_NOFS); -+ if (unlikely(!arg)) -+ goto out; -+ -+ arg->sb = sb; -+ arg->br = br; -+ arg->calc = *calc; -+ arg->ino = ino; -+ au_lcnt_inc(&br->br_count); -+ err = au_wkq_nowait(au_xino_call_do_new_async, arg, sb, AuWkq_NEST); -+ if (unlikely(err)) { -+ pr_err("wkq %d\n", err); -+ au_lcnt_dec(&br->br_count); -+ au_kfree_rcu(arg); -+ } -+ -+out: -+ return err; -+} -+ -+/* -+ * read @ino from xinofile for the specified branch{@sb, @bindex} -+ * at the position of @h_ino. -+ */ -+int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, -+ ino_t *ino) -+{ -+ int err; -+ ssize_t sz; -+ struct au_xi_calc calc; -+ struct au_sbinfo *sbinfo; -+ struct file *file; -+ struct au_xino *xi; -+ struct hlist_bl_head *hbl; -+ struct hlist_bl_node *pos; -+ struct au_xi_writing *p; -+ -+ *ino = 0; -+ if (!au_opt_test(au_mntflags(sb), XINO)) -+ return 0; /* no xino */ -+ -+ err = 0; -+ au_xi_calc(sb, h_ino, &calc); -+ xi = au_sbr(sb, bindex)->br_xino; -+ file = au_xino_file(xi, calc.idx); -+ if (!file) { -+ hbl = &xi->xi_writing; -+ hlist_bl_lock(hbl); -+ au_hbl_for_each(pos, hbl) { -+ p = container_of(pos, struct au_xi_writing, node); -+ if (p->h_ino == h_ino) { -+ AuDbg("hi%llu, i%llu, found\n", -+ (u64)p->h_ino, (u64)p->ino); -+ *ino = p->ino; -+ break; -+ } -+ } -+ hlist_bl_unlock(hbl); -+ return 0; -+ } else if (vfsub_f_size_read(file) < calc.pos + sizeof(*ino)) -+ return 0; /* no xino */ -+ -+ sbinfo = au_sbi(sb); -+ sz = xino_fread(sbinfo->si_xread, file, ino, sizeof(*ino), &calc.pos); -+ if (sz == sizeof(*ino)) -+ return 0; /* success */ -+ -+ err = sz; -+ if (unlikely(sz >= 0)) { -+ err = -EIO; -+ AuIOErr("xino read error (%zd)\n", sz); -+ } -+ return err; -+} -+ -+static int au_xino_do_write(vfs_writef_t write, struct file *file, -+ struct au_xi_calc *calc, ino_t ino) -+{ -+ ssize_t sz; -+ -+ sz = xino_fwrite(write, file, &ino, sizeof(ino), &calc->pos); -+ if (sz == sizeof(ino)) -+ return 0; /* success */ -+ -+ AuIOErr("write failed (%zd)\n", sz); -+ return -EIO; -+} -+ -+/* -+ * write @ino to the xinofile for the specified branch{@sb, @bindex} -+ * at the position of @h_ino. -+ * even if @ino is zero, it is written to the xinofile and means no entry. -+ * if the size of the xino file on a specific filesystem exceeds the watermark, -+ * try truncating it. -+ */ -+int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, -+ ino_t ino) -+{ -+ int err; -+ unsigned int mnt_flags; -+ struct au_xi_calc calc; -+ struct file *file; -+ struct au_branch *br; -+ struct au_xino *xi; -+ struct au_xi_writing *p; -+ -+ SiMustAnyLock(sb); -+ -+ mnt_flags = au_mntflags(sb); -+ if (!au_opt_test(mnt_flags, XINO)) -+ return 0; -+ -+ au_xi_calc(sb, h_ino, &calc); -+ br = au_sbr(sb, bindex); -+ xi = br->br_xino; -+ file = au_xino_file(xi, calc.idx); -+ if (!file) { -+ /* store the inum pair into the list */ -+ p = kmalloc(sizeof(*p), GFP_NOFS | __GFP_NOFAIL); -+ p->h_ino = h_ino; -+ p->ino = ino; -+ au_hbl_add(&p->node, &xi->xi_writing); -+ -+ /* create and write a new xino file asynchronously */ -+ err = au_xino_new_async(sb, br, &calc, ino); -+ if (!err) -+ return 0; /* success */ -+ goto out; -+ } -+ -+ err = au_xino_do_write(au_sbi(sb)->si_xwrite, file, &calc, ino); -+ if (!err) { -+ br = au_sbr(sb, bindex); -+ if (au_opt_test(mnt_flags, TRUNC_XINO) -+ && au_test_fs_trunc_xino(au_br_sb(br))) -+ xino_try_trunc(sb, br); -+ return 0; /* success */ -+ } -+ -+out: -+ AuIOErr("write failed (%d)\n", err); -+ return -EIO; -+} -+ -+static ssize_t xino_fread_wkq(vfs_readf_t func, struct file *file, void *buf, -+ size_t size, loff_t *pos); -+ -+/* todo: unnecessary to support mmap_sem since kernel-space? */ -+ssize_t xino_fread(vfs_readf_t func, struct file *file, void *kbuf, size_t size, -+ loff_t *pos) -+{ -+ ssize_t err; -+ mm_segment_t oldfs; -+ union { -+ void *k; -+ char __user *u; -+ } buf; -+ int i; -+ const int prevent_endless = 10; -+ -+ i = 0; -+ buf.k = kbuf; -+ oldfs = get_fs(); -+ set_fs(KERNEL_DS); -+ do { -+ err = func(file, buf.u, size, pos); -+ if (err == -EINTR -+ && !au_wkq_test() -+ && fatal_signal_pending(current)) { -+ set_fs(oldfs); -+ err = xino_fread_wkq(func, file, kbuf, size, pos); -+ BUG_ON(err == -EINTR); -+ oldfs = get_fs(); -+ set_fs(KERNEL_DS); -+ } -+ } while (i++ < prevent_endless -+ && (err == -EAGAIN || err == -EINTR)); -+ set_fs(oldfs); -+ -+#if 0 /* reserved for future use */ -+ if (err > 0) -+ fsnotify_access(file->f_path.dentry); -+#endif -+ -+ return err; -+} -+ -+struct xino_fread_args { -+ ssize_t *errp; -+ vfs_readf_t func; -+ struct file *file; -+ void *buf; -+ size_t size; -+ loff_t *pos; -+}; -+ -+static void call_xino_fread(void *args) -+{ -+ struct xino_fread_args *a = args; -+ *a->errp = xino_fread(a->func, a->file, a->buf, a->size, a->pos); -+} -+ -+static ssize_t xino_fread_wkq(vfs_readf_t func, struct file *file, void *buf, -+ size_t size, loff_t *pos) -+{ -+ ssize_t err; -+ int wkq_err; -+ struct xino_fread_args args = { -+ .errp = &err, -+ .func = func, -+ .file = file, -+ .buf = buf, -+ .size = size, -+ .pos = pos -+ }; -+ -+ wkq_err = au_wkq_wait(call_xino_fread, &args); -+ if (unlikely(wkq_err)) -+ err = wkq_err; -+ -+ return err; -+} -+ -+static ssize_t xino_fwrite_wkq(vfs_writef_t func, struct file *file, void *buf, -+ size_t size, loff_t *pos); -+ -+static ssize_t do_xino_fwrite(vfs_writef_t func, struct file *file, void *kbuf, -+ size_t size, loff_t *pos) -+{ -+ ssize_t err; -+ mm_segment_t oldfs; -+ union { -+ void *k; -+ const char __user *u; -+ } buf; -+ int i; -+ const int prevent_endless = 10; -+ -+ i = 0; -+ buf.k = kbuf; -+ oldfs = get_fs(); -+ set_fs(KERNEL_DS); -+ do { -+ err = func(file, buf.u, size, pos); -+ if (err == -EINTR -+ && !au_wkq_test() -+ && fatal_signal_pending(current)) { -+ set_fs(oldfs); -+ err = xino_fwrite_wkq(func, file, kbuf, size, pos); -+ BUG_ON(err == -EINTR); -+ oldfs = get_fs(); -+ set_fs(KERNEL_DS); -+ } -+ } while (i++ < prevent_endless -+ && (err == -EAGAIN || err == -EINTR)); -+ set_fs(oldfs); -+ -+#if 0 /* reserved for future use */ -+ if (err > 0) -+ fsnotify_modify(file->f_path.dentry); -+#endif -+ -+ return err; -+} -+ -+struct do_xino_fwrite_args { -+ ssize_t *errp; -+ vfs_writef_t func; -+ struct file *file; -+ void *buf; -+ size_t size; -+ loff_t *pos; -+}; -+ -+static void call_do_xino_fwrite(void *args) -+{ -+ struct do_xino_fwrite_args *a = args; -+ *a->errp = do_xino_fwrite(a->func, a->file, a->buf, a->size, a->pos); -+} -+ -+static ssize_t xino_fwrite_wkq(vfs_writef_t func, struct file *file, void *buf, -+ size_t size, loff_t *pos) -+{ -+ ssize_t err; -+ int wkq_err; -+ struct do_xino_fwrite_args args = { -+ .errp = &err, -+ .func = func, -+ .file = file, -+ .buf = buf, -+ .size = size, -+ .pos = pos -+ }; -+ -+ /* -+ * it breaks RLIMIT_FSIZE and normal user's limit, -+ * users should care about quota and real 'filesystem full.' -+ */ -+ wkq_err = au_wkq_wait(call_do_xino_fwrite, &args); -+ if (unlikely(wkq_err)) -+ err = wkq_err; -+ -+ return err; -+} -+ -+ssize_t xino_fwrite(vfs_writef_t func, struct file *file, void *buf, -+ size_t size, loff_t *pos) -+{ -+ ssize_t err; -+ -+ if (rlimit(RLIMIT_FSIZE) == RLIM_INFINITY) { -+ lockdep_off(); -+ err = do_xino_fwrite(func, file, buf, size, pos); -+ lockdep_on(); -+ } else { -+ lockdep_off(); -+ err = xino_fwrite_wkq(func, file, buf, size, pos); -+ lockdep_on(); -+ } -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * inode number bitmap -+ */ -+static const int page_bits = (int)PAGE_SIZE * BITS_PER_BYTE; -+static ino_t xib_calc_ino(unsigned long pindex, int bit) -+{ -+ ino_t ino; -+ -+ AuDebugOn(bit < 0 || page_bits <= bit); -+ ino = AUFS_FIRST_INO + pindex * page_bits + bit; -+ return ino; -+} -+ -+static void xib_calc_bit(ino_t ino, unsigned long *pindex, int *bit) -+{ -+ AuDebugOn(ino < AUFS_FIRST_INO); -+ ino -= AUFS_FIRST_INO; -+ *pindex = ino / page_bits; -+ *bit = ino % page_bits; -+} -+ -+static int xib_pindex(struct super_block *sb, unsigned long pindex) -+{ -+ int err; -+ loff_t pos; -+ ssize_t sz; -+ struct au_sbinfo *sbinfo; -+ struct file *xib; -+ unsigned long *p; -+ -+ sbinfo = au_sbi(sb); -+ MtxMustLock(&sbinfo->si_xib_mtx); -+ AuDebugOn(pindex > ULONG_MAX / PAGE_SIZE -+ || !au_opt_test(sbinfo->si_mntflags, XINO)); -+ -+ if (pindex == sbinfo->si_xib_last_pindex) -+ return 0; -+ -+ xib = sbinfo->si_xib; -+ p = sbinfo->si_xib_buf; -+ pos = sbinfo->si_xib_last_pindex; -+ pos *= PAGE_SIZE; -+ sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos); -+ if (unlikely(sz != PAGE_SIZE)) -+ goto out; -+ -+ pos = pindex; -+ pos *= PAGE_SIZE; -+ if (vfsub_f_size_read(xib) >= pos + PAGE_SIZE) -+ sz = xino_fread(sbinfo->si_xread, xib, p, PAGE_SIZE, &pos); -+ else { -+ memset(p, 0, PAGE_SIZE); -+ sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos); -+ } -+ if (sz == PAGE_SIZE) { -+ sbinfo->si_xib_last_pindex = pindex; -+ return 0; /* success */ -+ } -+ -+out: -+ AuIOErr1("write failed (%zd)\n", sz); -+ err = sz; -+ if (sz >= 0) -+ err = -EIO; -+ return err; -+} -+ -+static void au_xib_clear_bit(struct inode *inode) -+{ -+ int err, bit; -+ unsigned long pindex; -+ struct super_block *sb; -+ struct au_sbinfo *sbinfo; -+ -+ AuDebugOn(inode->i_nlink); -+ -+ sb = inode->i_sb; -+ xib_calc_bit(inode->i_ino, &pindex, &bit); -+ AuDebugOn(page_bits <= bit); -+ sbinfo = au_sbi(sb); -+ mutex_lock(&sbinfo->si_xib_mtx); -+ err = xib_pindex(sb, pindex); -+ if (!err) { -+ clear_bit(bit, sbinfo->si_xib_buf); -+ sbinfo->si_xib_next_bit = bit; -+ } -+ mutex_unlock(&sbinfo->si_xib_mtx); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * truncate a xino bitmap file -+ */ -+ -+/* todo: slow */ -+static int do_xib_restore(struct super_block *sb, struct file *file, void *page) -+{ -+ int err, bit; -+ ssize_t sz; -+ unsigned long pindex; -+ loff_t pos, pend; -+ struct au_sbinfo *sbinfo; -+ vfs_readf_t func; -+ ino_t *ino; -+ unsigned long *p; -+ -+ err = 0; -+ sbinfo = au_sbi(sb); -+ MtxMustLock(&sbinfo->si_xib_mtx); -+ p = sbinfo->si_xib_buf; -+ func = sbinfo->si_xread; -+ pend = vfsub_f_size_read(file); -+ pos = 0; -+ while (pos < pend) { -+ sz = xino_fread(func, file, page, PAGE_SIZE, &pos); -+ err = sz; -+ if (unlikely(sz <= 0)) -+ goto out; -+ -+ err = 0; -+ for (ino = page; sz > 0; ino++, sz -= sizeof(ino)) { -+ if (unlikely(*ino < AUFS_FIRST_INO)) -+ continue; -+ -+ xib_calc_bit(*ino, &pindex, &bit); -+ AuDebugOn(page_bits <= bit); -+ err = xib_pindex(sb, pindex); -+ if (!err) -+ set_bit(bit, p); -+ else -+ goto out; -+ } -+ } -+ -+out: -+ return err; -+} -+ -+static int xib_restore(struct super_block *sb) -+{ -+ int err, i; -+ unsigned int nfile; -+ aufs_bindex_t bindex, bbot; -+ void *page; -+ struct au_branch *br; -+ struct au_xino *xi; -+ struct file *file; -+ -+ err = -ENOMEM; -+ page = (void *)__get_free_page(GFP_NOFS); -+ if (unlikely(!page)) -+ goto out; -+ -+ err = 0; -+ bbot = au_sbbot(sb); -+ for (bindex = 0; !err && bindex <= bbot; bindex++) -+ if (!bindex || is_sb_shared(sb, bindex, bindex - 1) < 0) { -+ br = au_sbr(sb, bindex); -+ xi = br->br_xino; -+ nfile = xi->xi_nfile; -+ for (i = 0; i < nfile; i++) { -+ file = au_xino_file(xi, i); -+ if (file) -+ err = do_xib_restore(sb, file, page); -+ } -+ } else -+ AuDbg("skip shared b%d\n", bindex); -+ free_page((unsigned long)page); -+ -+out: -+ return err; -+} -+ -+int au_xib_trunc(struct super_block *sb) -+{ -+ int err; -+ ssize_t sz; -+ loff_t pos; -+ struct au_sbinfo *sbinfo; -+ unsigned long *p; -+ struct file *file; -+ -+ SiMustWriteLock(sb); -+ -+ err = 0; -+ sbinfo = au_sbi(sb); -+ if (!au_opt_test(sbinfo->si_mntflags, XINO)) -+ goto out; -+ -+ file = sbinfo->si_xib; -+ if (vfsub_f_size_read(file) <= PAGE_SIZE) -+ goto out; -+ -+ file = au_xino_create2(sb, &sbinfo->si_xib->f_path, NULL); -+ err = PTR_ERR(file); -+ if (IS_ERR(file)) -+ goto out; -+ fput(sbinfo->si_xib); -+ sbinfo->si_xib = file; -+ -+ p = sbinfo->si_xib_buf; -+ memset(p, 0, PAGE_SIZE); -+ pos = 0; -+ sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xib, p, PAGE_SIZE, &pos); -+ if (unlikely(sz != PAGE_SIZE)) { -+ err = sz; -+ AuIOErr("err %d\n", err); -+ if (sz >= 0) -+ err = -EIO; -+ goto out; -+ } -+ -+ mutex_lock(&sbinfo->si_xib_mtx); -+ /* mnt_want_write() is unnecessary here */ -+ err = xib_restore(sb); -+ mutex_unlock(&sbinfo->si_xib_mtx); -+ -+out: -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct au_xino *au_xino_alloc(unsigned int nfile) -+{ -+ struct au_xino *xi; -+ -+ xi = kzalloc(sizeof(*xi), GFP_NOFS); -+ if (unlikely(!xi)) -+ goto out; -+ xi->xi_nfile = nfile; -+ xi->xi_file = kcalloc(nfile, sizeof(*xi->xi_file), GFP_NOFS); -+ if (unlikely(!xi->xi_file)) -+ goto out_free; -+ -+ xi->xi_nondir.total = 8; /* initial size */ -+ xi->xi_nondir.array = kcalloc(xi->xi_nondir.total, sizeof(ino_t), -+ GFP_NOFS); -+ if (unlikely(!xi->xi_nondir.array)) -+ goto out_file; -+ -+ spin_lock_init(&xi->xi_nondir.spin); -+ init_waitqueue_head(&xi->xi_nondir.wqh); -+ mutex_init(&xi->xi_mtx); -+ INIT_HLIST_BL_HEAD(&xi->xi_writing); -+ atomic_set(&xi->xi_truncating, 0); -+ kref_init(&xi->xi_kref); -+ goto out; /* success */ -+ -+out_file: -+ au_kfree_try_rcu(xi->xi_file); -+out_free: -+ au_kfree_rcu(xi); -+ xi = NULL; -+out: -+ return xi; -+} -+ -+static int au_xino_init(struct au_branch *br, int idx, struct file *file) -+{ -+ int err; -+ struct au_xino *xi; -+ -+ err = 0; -+ xi = au_xino_alloc(idx + 1); -+ if (unlikely(!xi)) { -+ err = -ENOMEM; -+ goto out; -+ } -+ -+ if (file) -+ get_file(file); -+ xi->xi_file[idx] = file; -+ AuDebugOn(br->br_xino); -+ br->br_xino = xi; -+ -+out: -+ return err; -+} -+ -+static void au_xino_release(struct kref *kref) -+{ -+ struct au_xino *xi; -+ int i; -+ unsigned long ul; -+ struct hlist_bl_head *hbl; -+ struct hlist_bl_node *pos, *n; -+ struct au_xi_writing *p; -+ -+ xi = container_of(kref, struct au_xino, xi_kref); -+ for (i = 0; i < xi->xi_nfile; i++) -+ if (xi->xi_file[i]) -+ fput(xi->xi_file[i]); -+ for (i = xi->xi_nondir.total - 1; i >= 0; i--) -+ AuDebugOn(xi->xi_nondir.array[i]); -+ mutex_destroy(&xi->xi_mtx); -+ hbl = &xi->xi_writing; -+ ul = au_hbl_count(hbl); -+ if (unlikely(ul)) { -+ pr_warn("xi_writing %lu\n", ul); -+ hlist_bl_lock(hbl); -+ hlist_bl_for_each_entry_safe(p, pos, n, hbl, node) { -+ hlist_bl_del(&p->node); -+ au_kfree_rcu(p); -+ } -+ hlist_bl_unlock(hbl); -+ } -+ au_kfree_try_rcu(xi->xi_file); -+ au_kfree_try_rcu(xi->xi_nondir.array); -+ au_kfree_rcu(xi); -+} -+ -+int au_xino_put(struct au_branch *br) -+{ -+ int ret; -+ struct au_xino *xi; -+ -+ ret = 0; -+ xi = br->br_xino; -+ if (xi) { -+ br->br_xino = NULL; -+ ret = kref_put(&xi->xi_kref, au_xino_release); -+ } -+ -+ return ret; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * xino mount option handlers -+ */ -+ -+/* xino bitmap */ -+static void xino_clear_xib(struct super_block *sb) -+{ -+ struct au_sbinfo *sbinfo; -+ -+ SiMustWriteLock(sb); -+ -+ sbinfo = au_sbi(sb); -+ /* unnecessary to clear sbinfo->si_xread and ->si_xwrite */ -+ if (sbinfo->si_xib) -+ fput(sbinfo->si_xib); -+ sbinfo->si_xib = NULL; -+ if (sbinfo->si_xib_buf) -+ free_page((unsigned long)sbinfo->si_xib_buf); -+ sbinfo->si_xib_buf = NULL; -+} -+ -+static int au_xino_set_xib(struct super_block *sb, struct path *path) -+{ -+ int err; -+ loff_t pos; -+ struct au_sbinfo *sbinfo; -+ struct file *file; -+ struct super_block *xi_sb; -+ -+ SiMustWriteLock(sb); -+ -+ sbinfo = au_sbi(sb); -+ file = au_xino_create2(sb, path, sbinfo->si_xib); -+ err = PTR_ERR(file); -+ if (IS_ERR(file)) -+ goto out; -+ if (sbinfo->si_xib) -+ fput(sbinfo->si_xib); -+ sbinfo->si_xib = file; -+ sbinfo->si_xread = vfs_readf(file); -+ sbinfo->si_xwrite = vfs_writef(file); -+ xi_sb = file_inode(file)->i_sb; -+ sbinfo->si_ximaxent = xi_sb->s_maxbytes; -+ if (unlikely(sbinfo->si_ximaxent < PAGE_SIZE)) { -+ err = -EIO; -+ pr_err("s_maxbytes(%llu) on %s is too small\n", -+ (u64)sbinfo->si_ximaxent, au_sbtype(xi_sb)); -+ goto out_unset; -+ } -+ sbinfo->si_ximaxent /= sizeof(ino_t); -+ -+ err = -ENOMEM; -+ if (!sbinfo->si_xib_buf) -+ sbinfo->si_xib_buf = (void *)get_zeroed_page(GFP_NOFS); -+ if (unlikely(!sbinfo->si_xib_buf)) -+ goto out_unset; -+ -+ sbinfo->si_xib_last_pindex = 0; -+ sbinfo->si_xib_next_bit = 0; -+ if (vfsub_f_size_read(file) < PAGE_SIZE) { -+ pos = 0; -+ err = xino_fwrite(sbinfo->si_xwrite, file, sbinfo->si_xib_buf, -+ PAGE_SIZE, &pos); -+ if (unlikely(err != PAGE_SIZE)) -+ goto out_free; -+ } -+ err = 0; -+ goto out; /* success */ -+ -+out_free: -+ if (sbinfo->si_xib_buf) -+ free_page((unsigned long)sbinfo->si_xib_buf); -+ sbinfo->si_xib_buf = NULL; -+ if (err >= 0) -+ err = -EIO; -+out_unset: -+ fput(sbinfo->si_xib); -+ sbinfo->si_xib = NULL; -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+/* xino for each branch */ -+static void xino_clear_br(struct super_block *sb) -+{ -+ aufs_bindex_t bindex, bbot; -+ struct au_branch *br; -+ -+ bbot = au_sbbot(sb); -+ for (bindex = 0; bindex <= bbot; bindex++) { -+ br = au_sbr(sb, bindex); -+ AuDebugOn(!br); -+ au_xino_put(br); -+ } -+} -+ -+static void au_xino_set_br_shared(struct super_block *sb, struct au_branch *br, -+ aufs_bindex_t bshared) -+{ -+ struct au_branch *brshared; -+ -+ brshared = au_sbr(sb, bshared); -+ AuDebugOn(!brshared->br_xino); -+ AuDebugOn(!brshared->br_xino->xi_file); -+ if (br->br_xino != brshared->br_xino) { -+ au_xino_get(brshared); -+ au_xino_put(br); -+ br->br_xino = brshared->br_xino; -+ } -+} -+ -+struct au_xino_do_set_br { -+ vfs_writef_t writef; -+ struct au_branch *br; -+ ino_t h_ino; -+ aufs_bindex_t bshared; -+}; -+ -+static int au_xino_do_set_br(struct super_block *sb, struct path *path, -+ struct au_xino_do_set_br *args) -+{ -+ int err; -+ struct au_xi_calc calc; -+ struct file *file; -+ struct au_branch *br; -+ struct au_xi_new xinew = { -+ .base = path -+ }; -+ -+ br = args->br; -+ xinew.xi = br->br_xino; -+ au_xi_calc(sb, args->h_ino, &calc); -+ xinew.copy_src = au_xino_file(xinew.xi, calc.idx); -+ if (args->bshared >= 0) -+ /* shared xino */ -+ au_xino_set_br_shared(sb, br, args->bshared); -+ else if (!xinew.xi) { -+ /* new xino */ -+ err = au_xino_init(br, calc.idx, xinew.copy_src); -+ if (unlikely(err)) -+ goto out; -+ } -+ -+ /* force re-creating */ -+ xinew.xi = br->br_xino; -+ xinew.idx = calc.idx; -+ mutex_lock(&xinew.xi->xi_mtx); -+ file = au_xi_new(sb, &xinew); -+ mutex_unlock(&xinew.xi->xi_mtx); -+ err = PTR_ERR(file); -+ if (IS_ERR(file)) -+ goto out; -+ AuDebugOn(!file); -+ -+ err = au_xino_do_write(args->writef, file, &calc, AUFS_ROOT_INO); -+ if (unlikely(err)) -+ au_xino_put(br); -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+static int au_xino_set_br(struct super_block *sb, struct path *path) -+{ -+ int err; -+ aufs_bindex_t bindex, bbot; -+ struct au_xino_do_set_br args; -+ struct inode *inode; -+ -+ SiMustWriteLock(sb); -+ -+ bbot = au_sbbot(sb); -+ inode = d_inode(sb->s_root); -+ args.writef = au_sbi(sb)->si_xwrite; -+ for (bindex = 0; bindex <= bbot; bindex++) { -+ args.h_ino = au_h_iptr(inode, bindex)->i_ino; -+ args.br = au_sbr(sb, bindex); -+ args.bshared = is_sb_shared(sb, bindex, bindex - 1); -+ err = au_xino_do_set_br(sb, path, &args); -+ if (unlikely(err)) -+ break; -+ } -+ -+ AuTraceErr(err); -+ return err; -+} -+ -+void au_xino_clr(struct super_block *sb) -+{ -+ struct au_sbinfo *sbinfo; -+ -+ au_xigen_clr(sb); -+ xino_clear_xib(sb); -+ xino_clear_br(sb); -+ dbgaufs_brs_del(sb, 0); -+ sbinfo = au_sbi(sb); -+ /* lvalue, do not call au_mntflags() */ -+ au_opt_clr(sbinfo->si_mntflags, XINO); -+} -+ -+int au_xino_set(struct super_block *sb, struct au_opt_xino *xiopt, int remount) -+{ -+ int err, skip; -+ struct dentry *dentry, *parent, *cur_dentry, *cur_parent; -+ struct qstr *dname, *cur_name; -+ struct file *cur_xino; -+ struct au_sbinfo *sbinfo; -+ struct path *path, *cur_path; -+ -+ SiMustWriteLock(sb); -+ -+ err = 0; -+ sbinfo = au_sbi(sb); -+ path = &xiopt->file->f_path; -+ dentry = path->dentry; -+ parent = dget_parent(dentry); -+ if (remount) { -+ skip = 0; -+ cur_xino = sbinfo->si_xib; -+ if (cur_xino) { -+ cur_path = &cur_xino->f_path; -+ cur_dentry = cur_path->dentry; -+ cur_parent = dget_parent(cur_dentry); -+ cur_name = &cur_dentry->d_name; -+ dname = &dentry->d_name; -+ skip = (cur_parent == parent -+ && au_qstreq(dname, cur_name)); -+ dput(cur_parent); -+ } -+ if (skip) -+ goto out; -+ } -+ -+ au_opt_set(sbinfo->si_mntflags, XINO); -+ err = au_xino_set_xib(sb, path); -+ /* si_x{read,write} are set */ -+ if (!err) -+ err = au_xigen_set(sb, path); -+ if (!err) -+ err = au_xino_set_br(sb, path); -+ if (!err) { -+ dbgaufs_brs_add(sb, 0, /*topdown*/1); -+ goto out; /* success */ -+ } -+ -+ /* reset all */ -+ AuIOErr("failed setting xino(%d).\n", err); -+ au_xino_clr(sb); -+ -+out: -+ dput(parent); -+ return err; -+} -+ -+/* -+ * create a xinofile at the default place/path. -+ */ -+struct file *au_xino_def(struct super_block *sb) -+{ -+ struct file *file; -+ char *page, *p; -+ struct au_branch *br; -+ struct super_block *h_sb; -+ struct path path; -+ aufs_bindex_t bbot, bindex, bwr; -+ -+ br = NULL; -+ bbot = au_sbbot(sb); -+ bwr = -1; -+ for (bindex = 0; bindex <= bbot; bindex++) { -+ br = au_sbr(sb, bindex); -+ if (au_br_writable(br->br_perm) -+ && !au_test_fs_bad_xino(au_br_sb(br))) { -+ bwr = bindex; -+ break; -+ } -+ } -+ -+ if (bwr >= 0) { -+ file = ERR_PTR(-ENOMEM); -+ page = (void *)__get_free_page(GFP_NOFS); -+ if (unlikely(!page)) -+ goto out; -+ path.mnt = au_br_mnt(br); -+ path.dentry = au_h_dptr(sb->s_root, bwr); -+ p = d_path(&path, page, PATH_MAX - sizeof(AUFS_XINO_FNAME)); -+ file = (void *)p; -+ if (!IS_ERR(p)) { -+ strcat(p, "/" AUFS_XINO_FNAME); -+ AuDbg("%s\n", p); -+ file = au_xino_create(sb, p, /*silent*/0, /*wbrtop*/1); -+ } -+ free_page((unsigned long)page); -+ } else { -+ file = au_xino_create(sb, AUFS_XINO_DEFPATH, /*silent*/0, -+ /*wbrtop*/0); -+ if (IS_ERR(file)) -+ goto out; -+ h_sb = file->f_path.dentry->d_sb; -+ if (unlikely(au_test_fs_bad_xino(h_sb))) { -+ pr_err("xino doesn't support %s(%s)\n", -+ AUFS_XINO_DEFPATH, au_sbtype(h_sb)); -+ fput(file); -+ file = ERR_PTR(-EINVAL); -+ } -+ } -+ -+out: -+ return file; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * initialize the xinofile for the specified branch @br -+ * at the place/path where @base_file indicates. -+ * test whether another branch is on the same filesystem or not, -+ * if found then share the xinofile with another branch. -+ */ -+int au_xino_init_br(struct super_block *sb, struct au_branch *br, ino_t h_ino, -+ struct path *base) -+{ -+ int err; -+ struct au_xino_do_set_br args = { -+ .h_ino = h_ino, -+ .br = br -+ }; -+ -+ args.writef = au_sbi(sb)->si_xwrite; -+ args.bshared = sbr_find_shared(sb, /*btop*/0, au_sbbot(sb), -+ au_br_sb(br)); -+ err = au_xino_do_set_br(sb, base, &args); -+ if (unlikely(err)) -+ au_xino_put(br); -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * get an unused inode number from bitmap -+ */ -+ino_t au_xino_new_ino(struct super_block *sb) -+{ -+ ino_t ino; -+ unsigned long *p, pindex, ul, pend; -+ struct au_sbinfo *sbinfo; -+ struct file *file; -+ int free_bit, err; -+ -+ if (!au_opt_test(au_mntflags(sb), XINO)) -+ return iunique(sb, AUFS_FIRST_INO); -+ -+ sbinfo = au_sbi(sb); -+ mutex_lock(&sbinfo->si_xib_mtx); -+ p = sbinfo->si_xib_buf; -+ free_bit = sbinfo->si_xib_next_bit; -+ if (free_bit < page_bits && !test_bit(free_bit, p)) -+ goto out; /* success */ -+ free_bit = find_first_zero_bit(p, page_bits); -+ if (free_bit < page_bits) -+ goto out; /* success */ -+ -+ pindex = sbinfo->si_xib_last_pindex; -+ for (ul = pindex - 1; ul < ULONG_MAX; ul--) { -+ err = xib_pindex(sb, ul); -+ if (unlikely(err)) -+ goto out_err; -+ free_bit = find_first_zero_bit(p, page_bits); -+ if (free_bit < page_bits) -+ goto out; /* success */ -+ } -+ -+ file = sbinfo->si_xib; -+ pend = vfsub_f_size_read(file) / PAGE_SIZE; -+ for (ul = pindex + 1; ul <= pend; ul++) { -+ err = xib_pindex(sb, ul); -+ if (unlikely(err)) -+ goto out_err; -+ free_bit = find_first_zero_bit(p, page_bits); -+ if (free_bit < page_bits) -+ goto out; /* success */ -+ } -+ BUG(); -+ -+out: -+ set_bit(free_bit, p); -+ sbinfo->si_xib_next_bit = free_bit + 1; -+ pindex = sbinfo->si_xib_last_pindex; -+ mutex_unlock(&sbinfo->si_xib_mtx); -+ ino = xib_calc_ino(pindex, free_bit); -+ AuDbg("i%lu\n", (unsigned long)ino); -+ return ino; -+out_err: -+ mutex_unlock(&sbinfo->si_xib_mtx); -+ AuDbg("i0\n"); -+ return 0; -+} -+ -+/* for s_op->delete_inode() */ -+void au_xino_delete_inode(struct inode *inode, const int unlinked) -+{ -+ int err; -+ unsigned int mnt_flags; -+ aufs_bindex_t bindex, bbot, bi; -+ unsigned char try_trunc; -+ struct au_iinfo *iinfo; -+ struct super_block *sb; -+ struct au_hinode *hi; -+ struct inode *h_inode; -+ struct au_branch *br; -+ vfs_writef_t xwrite; -+ struct au_xi_calc calc; -+ struct file *file; -+ -+ AuDebugOn(au_is_bad_inode(inode)); -+ -+ sb = inode->i_sb; -+ mnt_flags = au_mntflags(sb); -+ if (!au_opt_test(mnt_flags, XINO) -+ || inode->i_ino == AUFS_ROOT_INO) -+ return; -+ -+ if (unlinked) { -+ au_xigen_inc(inode); -+ au_xib_clear_bit(inode); -+ } -+ -+ iinfo = au_ii(inode); -+ bindex = iinfo->ii_btop; -+ if (bindex < 0) -+ return; -+ -+ xwrite = au_sbi(sb)->si_xwrite; -+ try_trunc = !!au_opt_test(mnt_flags, TRUNC_XINO); -+ hi = au_hinode(iinfo, bindex); -+ bbot = iinfo->ii_bbot; -+ for (; bindex <= bbot; bindex++, hi++) { -+ h_inode = hi->hi_inode; -+ if (!h_inode -+ || (!unlinked && h_inode->i_nlink)) -+ continue; -+ -+ /* inode may not be revalidated */ -+ bi = au_br_index(sb, hi->hi_id); -+ if (bi < 0) -+ continue; -+ -+ br = au_sbr(sb, bi); -+ au_xi_calc(sb, h_inode->i_ino, &calc); -+ file = au_xino_file(br->br_xino, calc.idx); -+ if (IS_ERR_OR_NULL(file)) -+ continue; -+ -+ err = au_xino_do_write(xwrite, file, &calc, /*ino*/0); -+ if (!err && try_trunc -+ && au_test_fs_trunc_xino(au_br_sb(br))) -+ xino_try_trunc(sb, br); -+ } -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int au_xinondir_find(struct au_xino *xi, ino_t h_ino) -+{ -+ int found, total, i; -+ -+ found = -1; -+ total = xi->xi_nondir.total; -+ for (i = 0; i < total; i++) { -+ if (xi->xi_nondir.array[i] != h_ino) -+ continue; -+ found = i; -+ break; -+ } -+ -+ return found; -+} -+ -+static int au_xinondir_expand(struct au_xino *xi) -+{ -+ int err, sz; -+ ino_t *p; -+ -+ BUILD_BUG_ON(KMALLOC_MAX_SIZE > INT_MAX); -+ -+ err = -ENOMEM; -+ sz = xi->xi_nondir.total * sizeof(ino_t); -+ if (unlikely(sz > KMALLOC_MAX_SIZE / 2)) -+ goto out; -+ p = au_kzrealloc(xi->xi_nondir.array, sz, sz << 1, GFP_ATOMIC, -+ /*may_shrink*/0); -+ if (p) { -+ xi->xi_nondir.array = p; -+ xi->xi_nondir.total <<= 1; -+ AuDbg("xi_nondir.total %d\n", xi->xi_nondir.total); -+ err = 0; -+ } -+ -+out: -+ return err; -+} -+ -+void au_xinondir_leave(struct super_block *sb, aufs_bindex_t bindex, -+ ino_t h_ino, int idx) -+{ -+ struct au_xino *xi; -+ -+ AuDebugOn(!au_opt_test(au_mntflags(sb), XINO)); -+ xi = au_sbr(sb, bindex)->br_xino; -+ AuDebugOn(idx < 0 || xi->xi_nondir.total <= idx); -+ -+ spin_lock(&xi->xi_nondir.spin); -+ AuDebugOn(xi->xi_nondir.array[idx] != h_ino); -+ xi->xi_nondir.array[idx] = 0; -+ spin_unlock(&xi->xi_nondir.spin); -+ wake_up_all(&xi->xi_nondir.wqh); -+} -+ -+int au_xinondir_enter(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, -+ int *idx) -+{ -+ int err, found, empty; -+ struct au_xino *xi; -+ -+ err = 0; -+ *idx = -1; -+ if (!au_opt_test(au_mntflags(sb), XINO)) -+ goto out; /* no xino */ -+ -+ xi = au_sbr(sb, bindex)->br_xino; -+ -+again: -+ spin_lock(&xi->xi_nondir.spin); -+ found = au_xinondir_find(xi, h_ino); -+ if (found == -1) { -+ empty = au_xinondir_find(xi, /*h_ino*/0); -+ if (empty == -1) { -+ empty = xi->xi_nondir.total; -+ err = au_xinondir_expand(xi); -+ if (unlikely(err)) -+ goto out_unlock; -+ } -+ xi->xi_nondir.array[empty] = h_ino; -+ *idx = empty; -+ } else { -+ spin_unlock(&xi->xi_nondir.spin); -+ wait_event(xi->xi_nondir.wqh, -+ xi->xi_nondir.array[found] != h_ino); -+ goto again; -+ } -+ -+out_unlock: -+ spin_unlock(&xi->xi_nondir.spin); -+out: -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+int au_xino_path(struct seq_file *seq, struct file *file) -+{ -+ int err; -+ -+ err = au_seq_path(seq, &file->f_path); -+ if (unlikely(err)) -+ goto out; -+ -+#define Deleted "\\040(deleted)" -+ seq->count -= sizeof(Deleted) - 1; -+ AuDebugOn(memcmp(seq->buf + seq->count, Deleted, -+ sizeof(Deleted) - 1)); -+#undef Deleted -+ -+out: -+ return err; -+} -diff -Nurp linux-5.6.3/fs/dcache.c linux-5.6.3-aufs/fs/dcache.c ---- linux-5.6.3/fs/dcache.c 2020-03-30 01:25:41.000000000 +0300 -+++ linux-5.6.3-aufs/fs/dcache.c 2020-04-10 12:40:52.194049596 +0300 -@@ -1266,7 +1266,7 @@ enum d_walk_ret { - * - * The @enter() callbacks are called with d_lock held. - */ --static void d_walk(struct dentry *parent, void *data, -+void d_walk(struct dentry *parent, void *data, - enum d_walk_ret (*enter)(void *, struct dentry *)) - { - struct dentry *this_parent; -diff -Nurp linux-5.6.3/fs/fcntl.c linux-5.6.3-aufs/fs/fcntl.c ---- linux-5.6.3/fs/fcntl.c 2020-03-30 01:25:41.000000000 +0300 -+++ linux-5.6.3-aufs/fs/fcntl.c 2020-04-10 12:40:52.194049596 +0300 -@@ -32,7 +32,7 @@ - - #define SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | O_DIRECT | O_NOATIME) - --static int setfl(int fd, struct file * filp, unsigned long arg) -+int setfl(int fd, struct file *filp, unsigned long arg) - { - struct inode * inode = file_inode(filp); - int error = 0; -@@ -63,6 +63,8 @@ static int setfl(int fd, struct file * f - - if (filp->f_op->check_flags) - error = filp->f_op->check_flags(arg); -+ if (!error && filp->f_op->setfl) -+ error = filp->f_op->setfl(filp, arg); - if (error) - return error; - -diff -Nurp linux-5.6.3/fs/inode.c linux-5.6.3-aufs/fs/inode.c ---- linux-5.6.3/fs/inode.c 2020-03-30 01:25:41.000000000 +0300 -+++ linux-5.6.3-aufs/fs/inode.c 2020-04-10 12:40:52.194049596 +0300 -@@ -1688,7 +1688,7 @@ EXPORT_SYMBOL(generic_update_time); - * This does the actual work of updating an inodes time or version. Must have - * had called mnt_want_write() before calling this. - */ --static int update_time(struct inode *inode, struct timespec64 *time, int flags) -+int update_time(struct inode *inode, struct timespec64 *time, int flags) - { - if (inode->i_op->update_time) - return inode->i_op->update_time(inode, time, flags); -diff -Nurp linux-5.6.3/fs/Kconfig linux-5.6.3-aufs/fs/Kconfig ---- linux-5.6.3/fs/Kconfig 2020-03-30 01:25:41.000000000 +0300 -+++ linux-5.6.3-aufs/fs/Kconfig 2020-04-10 13:14:44.904937004 +0300 -@@ -122,6 +122,7 @@ source "fs/quota/Kconfig" - source "fs/autofs/Kconfig" - source "fs/fuse/Kconfig" - source "fs/overlayfs/Kconfig" -+source "fs/aufs/Kconfig" - - menu "Caches" - -diff -Nurp linux-5.6.3/fs/Makefile linux-5.6.3-aufs/fs/Makefile ---- linux-5.6.3/fs/Makefile 2020-03-30 01:25:41.000000000 +0300 -+++ linux-5.6.3-aufs/fs/Makefile 2020-04-10 13:13:53.450534347 +0300 -@@ -111,6 +111,7 @@ obj-$(CONFIG_AUTOFS_FS) += autofs/ - obj-$(CONFIG_ADFS_FS) += adfs/ - obj-$(CONFIG_FUSE_FS) += fuse/ - obj-$(CONFIG_OVERLAY_FS) += overlayfs/ -+obj-$(CONFIG_AUFS_FS) += aufs/ - obj-$(CONFIG_ORANGEFS_FS) += orangefs/ - obj-$(CONFIG_UDF_FS) += udf/ - obj-$(CONFIG_SUN_OPENPROMFS) += openpromfs/ -diff -Nurp linux-5.6.3/fs/namespace.c linux-5.6.3-aufs/fs/namespace.c ---- linux-5.6.3/fs/namespace.c 2020-03-30 01:25:41.000000000 +0300 -+++ linux-5.6.3-aufs/fs/namespace.c 2020-04-10 12:40:52.194049596 +0300 -@@ -776,6 +776,12 @@ static inline int check_mnt(struct mount - return mnt->mnt_ns == current->nsproxy->mnt_ns; - } - -+/* for aufs, CONFIG_AUFS_BR_FUSE */ -+int is_current_mnt_ns(struct vfsmount *mnt) -+{ -+ return check_mnt(real_mount(mnt)); -+} -+ - /* - * vfsmount lock must be held for write - */ -diff -Nurp linux-5.6.3/fs/proc/base.c linux-5.6.3-aufs/fs/proc/base.c ---- linux-5.6.3/fs/proc/base.c 2020-03-30 01:25:41.000000000 +0300 -+++ linux-5.6.3-aufs/fs/proc/base.c 2020-04-10 12:40:52.194049596 +0300 -@@ -2128,7 +2128,7 @@ static int map_files_get_link(struct den - rc = -ENOENT; - vma = find_exact_vma(mm, vm_start, vm_end); - if (vma && vma->vm_file) { -- *path = vma->vm_file->f_path; -+ *path = vma_pr_or_file(vma)->f_path; - path_get(path); - rc = 0; - } -diff -Nurp linux-5.6.3/fs/proc/nommu.c linux-5.6.3-aufs/fs/proc/nommu.c ---- linux-5.6.3/fs/proc/nommu.c 2020-03-30 01:25:41.000000000 +0300 -+++ linux-5.6.3-aufs/fs/proc/nommu.c 2020-04-10 12:40:52.194049596 +0300 -@@ -41,7 +41,10 @@ static int nommu_region_show(struct seq_ - file = region->vm_file; - - if (file) { -- struct inode *inode = file_inode(region->vm_file); -+ struct inode *inode; -+ -+ file = vmr_pr_or_file(region); -+ inode = file_inode(file); - dev = inode->i_sb->s_dev; - ino = inode->i_ino; - } -diff -Nurp linux-5.6.3/fs/proc/task_mmu.c linux-5.6.3-aufs/fs/proc/task_mmu.c ---- linux-5.6.3/fs/proc/task_mmu.c 2020-03-30 01:25:41.000000000 +0300 -+++ linux-5.6.3-aufs/fs/proc/task_mmu.c 2020-04-10 12:40:52.194049596 +0300 -@@ -309,7 +309,10 @@ show_map_vma(struct seq_file *m, struct - const char *name = NULL; - - if (file) { -- struct inode *inode = file_inode(vma->vm_file); -+ struct inode *inode; -+ -+ file = vma_pr_or_file(vma); -+ inode = file_inode(file); - dev = inode->i_sb->s_dev; - ino = inode->i_ino; - pgoff = ((loff_t)vma->vm_pgoff) << PAGE_SHIFT; -@@ -1819,7 +1822,7 @@ static int show_numa_map(struct seq_file - struct proc_maps_private *proc_priv = &numa_priv->proc_maps; - struct vm_area_struct *vma = v; - struct numa_maps *md = &numa_priv->md; -- struct file *file = vma->vm_file; -+ struct file *file = vma_pr_or_file(vma); - struct mm_struct *mm = vma->vm_mm; - struct mempolicy *pol; - char buffer[64]; -diff -Nurp linux-5.6.3/fs/proc/task_nommu.c linux-5.6.3-aufs/fs/proc/task_nommu.c ---- linux-5.6.3/fs/proc/task_nommu.c 2020-03-30 01:25:41.000000000 +0300 -+++ linux-5.6.3-aufs/fs/proc/task_nommu.c 2020-04-10 12:40:52.194049596 +0300 -@@ -155,7 +155,10 @@ static int nommu_vma_show(struct seq_fil - file = vma->vm_file; - - if (file) { -- struct inode *inode = file_inode(vma->vm_file); -+ struct inode *inode; -+ -+ file = vma_pr_or_file(vma); -+ inode = file_inode(file); - dev = inode->i_sb->s_dev; - ino = inode->i_ino; - pgoff = (loff_t)vma->vm_pgoff << PAGE_SHIFT; -diff -Nurp linux-5.6.3/fs/read_write.c linux-5.6.3-aufs/fs/read_write.c ---- linux-5.6.3/fs/read_write.c 2020-03-30 01:25:41.000000000 +0300 -+++ linux-5.6.3-aufs/fs/read_write.c 2020-04-10 12:40:52.194049596 +0300 -@@ -498,6 +498,28 @@ static ssize_t __vfs_write(struct file * - return -EINVAL; - } - -+vfs_readf_t vfs_readf(struct file *file) -+{ -+ const struct file_operations *fop = file->f_op; -+ -+ if (fop->read) -+ return fop->read; -+ if (fop->read_iter) -+ return new_sync_read; -+ return ERR_PTR(-ENOSYS); /* doesn't have ->read(|_iter)() op */ -+} -+ -+vfs_writef_t vfs_writef(struct file *file) -+{ -+ const struct file_operations *fop = file->f_op; -+ -+ if (fop->write) -+ return fop->write; -+ if (fop->write_iter) -+ return new_sync_write; -+ return ERR_PTR(-ENOSYS); /* doesn't have ->write(|_iter)() op */ -+} -+ - ssize_t __kernel_write(struct file *file, const void *buf, size_t count, loff_t *pos) - { - mm_segment_t old_fs; -diff -Nurp linux-5.6.3/fs/splice.c linux-5.6.3-aufs/fs/splice.c ---- linux-5.6.3/fs/splice.c 2020-03-30 01:25:41.000000000 +0300 -+++ linux-5.6.3-aufs/fs/splice.c 2020-04-10 12:40:52.194049596 +0300 -@@ -849,8 +849,8 @@ EXPORT_SYMBOL(generic_splice_sendpage); - /* - * Attempt to initiate a splice from pipe to file. - */ --static long do_splice_from(struct pipe_inode_info *pipe, struct file *out, -- loff_t *ppos, size_t len, unsigned int flags) -+long do_splice_from(struct pipe_inode_info *pipe, struct file *out, -+ loff_t *ppos, size_t len, unsigned int flags) - { - ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, - loff_t *, size_t, unsigned int); -@@ -866,9 +866,9 @@ static long do_splice_from(struct pipe_i - /* - * Attempt to initiate a splice from a file to a pipe. - */ --static long do_splice_to(struct file *in, loff_t *ppos, -- struct pipe_inode_info *pipe, size_t len, -- unsigned int flags) -+long do_splice_to(struct file *in, loff_t *ppos, -+ struct pipe_inode_info *pipe, size_t len, -+ unsigned int flags) - { - ssize_t (*splice_read)(struct file *, loff_t *, - struct pipe_inode_info *, size_t, unsigned int); -diff -Nurp linux-5.6.3/fs/sync.c linux-5.6.3-aufs/fs/sync.c ---- linux-5.6.3/fs/sync.c 2020-03-30 01:25:41.000000000 +0300 -+++ linux-5.6.3-aufs/fs/sync.c 2020-04-10 12:40:52.194049596 +0300 -@@ -28,7 +28,7 @@ - * wait == 1 case since in that case write_inode() functions do - * sync_dirty_buffer() and thus effectively write one block at a time. - */ --static int __sync_filesystem(struct super_block *sb, int wait) -+int __sync_filesystem(struct super_block *sb, int wait) - { - if (wait) - sync_inodes_sb(sb); -diff -Nurp linux-5.6.3/include/linux/fs.h linux-5.6.3-aufs/include/linux/fs.h ---- linux-5.6.3/include/linux/fs.h 2020-03-30 01:25:41.000000000 +0300 -+++ linux-5.6.3-aufs/include/linux/fs.h 2020-04-10 12:40:52.195049643 +0300 -@@ -1350,6 +1350,7 @@ extern void fasync_free(struct fasync_st - /* can be called from interrupts */ - extern void kill_fasync(struct fasync_struct **, int, int); - -+extern int setfl(int fd, struct file *filp, unsigned long arg); - extern void __f_setown(struct file *filp, struct pid *, enum pid_type, int force); - extern int f_setown(struct file *filp, unsigned long arg, int force); - extern void f_delown(struct file *filp); -@@ -1842,6 +1843,7 @@ struct file_operations { - ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int); - unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); - int (*check_flags)(int); -+ int (*setfl)(struct file *, unsigned long); - int (*flock) (struct file *, int, struct file_lock *); - ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int); - ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int); -@@ -1912,6 +1914,12 @@ ssize_t rw_copy_check_uvector(int type, - struct iovec *fast_pointer, - struct iovec **ret_pointer); - -+typedef ssize_t (*vfs_readf_t)(struct file *, char __user *, size_t, loff_t *); -+typedef ssize_t (*vfs_writef_t)(struct file *, const char __user *, size_t, -+ loff_t *); -+vfs_readf_t vfs_readf(struct file *file); -+vfs_writef_t vfs_writef(struct file *file); -+ - extern ssize_t __vfs_read(struct file *, char __user *, size_t, loff_t *); - extern ssize_t vfs_read(struct file *, char __user *, size_t, loff_t *); - extern ssize_t vfs_write(struct file *, const char __user *, size_t, loff_t *); -@@ -2344,6 +2352,7 @@ extern int current_umask(void); - extern void ihold(struct inode * inode); - extern void iput(struct inode *); - extern int generic_update_time(struct inode *, struct timespec64 *, int); -+extern int update_time(struct inode *, struct timespec64 *, int); - - /* /sys/fs */ - extern struct kobject *fs_kobj; -@@ -2628,6 +2637,7 @@ static inline bool sb_is_blkdev_sb(struc - return false; - } - #endif -+extern int __sync_filesystem(struct super_block *, int); - extern int sync_filesystem(struct super_block *); - extern const struct file_operations def_blk_fops; - extern const struct file_operations def_chr_fops; -diff -Nurp linux-5.6.3/include/linux/lockdep.h linux-5.6.3-aufs/include/linux/lockdep.h ---- linux-5.6.3/include/linux/lockdep.h 2020-03-30 01:25:41.000000000 +0300 -+++ linux-5.6.3-aufs/include/linux/lockdep.h 2020-04-10 12:40:52.195049643 +0300 -@@ -331,6 +331,8 @@ static inline int lockdep_match_key(stru - return lock->key == key; - } - -+struct lock_class *lockdep_hlock_class(struct held_lock *hlock); -+ - /* - * Acquire a lock. - * -@@ -472,6 +474,7 @@ struct lockdep_map { }; - - #define lockdep_depth(tsk) (0) - -+#define lockdep_is_held(lock) (1) - #define lockdep_is_held_type(l, r) (1) - - #define lockdep_assert_held(l) do { (void)(l); } while (0) -diff -Nurp linux-5.6.3/include/linux/mm.h linux-5.6.3-aufs/include/linux/mm.h ---- linux-5.6.3/include/linux/mm.h 2020-03-30 01:25:41.000000000 +0300 -+++ linux-5.6.3-aufs/include/linux/mm.h 2020-04-10 12:40:52.195049643 +0300 -@@ -1487,6 +1487,28 @@ static inline void unmap_shared_mapping_ - unmap_mapping_range(mapping, holebegin, holelen, 0); - } - -+extern void vma_do_file_update_time(struct vm_area_struct *, const char[], int); -+extern struct file *vma_do_pr_or_file(struct vm_area_struct *, const char[], -+ int); -+extern void vma_do_get_file(struct vm_area_struct *, const char[], int); -+extern void vma_do_fput(struct vm_area_struct *, const char[], int); -+ -+#define vma_file_update_time(vma) vma_do_file_update_time(vma, __func__, \ -+ __LINE__) -+#define vma_pr_or_file(vma) vma_do_pr_or_file(vma, __func__, \ -+ __LINE__) -+#define vma_get_file(vma) vma_do_get_file(vma, __func__, __LINE__) -+#define vma_fput(vma) vma_do_fput(vma, __func__, __LINE__) -+ -+#ifndef CONFIG_MMU -+extern struct file *vmr_do_pr_or_file(struct vm_region *, const char[], int); -+extern void vmr_do_fput(struct vm_region *, const char[], int); -+ -+#define vmr_pr_or_file(region) vmr_do_pr_or_file(region, __func__, \ -+ __LINE__) -+#define vmr_fput(region) vmr_do_fput(region, __func__, __LINE__) -+#endif /* !CONFIG_MMU */ -+ - extern int access_process_vm(struct task_struct *tsk, unsigned long addr, - void *buf, int len, unsigned int gup_flags); - extern int access_remote_vm(struct mm_struct *mm, unsigned long addr, -diff -Nurp linux-5.6.3/include/linux/mm_types.h linux-5.6.3-aufs/include/linux/mm_types.h ---- linux-5.6.3/include/linux/mm_types.h 2020-03-30 01:25:41.000000000 +0300 -+++ linux-5.6.3-aufs/include/linux/mm_types.h 2020-04-10 12:40:52.195049643 +0300 -@@ -267,6 +267,7 @@ struct vm_region { - unsigned long vm_top; /* region allocated to here */ - unsigned long vm_pgoff; /* the offset in vm_file corresponding to vm_start */ - struct file *vm_file; /* the backing file or NULL */ -+ struct file *vm_prfile; /* the virtual backing file or NULL */ - - int vm_usage; /* region usage count (access under nommu_region_sem) */ - bool vm_icache_flushed : 1; /* true if the icache has been flushed for -@@ -346,6 +347,7 @@ struct vm_area_struct { - unsigned long vm_pgoff; /* Offset (within vm_file) in PAGE_SIZE - units */ - struct file * vm_file; /* File we map to (can be NULL). */ -+ struct file *vm_prfile; /* shadow of vm_file */ - void * vm_private_data; /* was vm_pte (shared mem) */ - - #ifdef CONFIG_SWAP -diff -Nurp linux-5.6.3/include/linux/mnt_namespace.h linux-5.6.3-aufs/include/linux/mnt_namespace.h ---- linux-5.6.3/include/linux/mnt_namespace.h 2020-03-30 01:25:41.000000000 +0300 -+++ linux-5.6.3-aufs/include/linux/mnt_namespace.h 2020-04-10 12:40:52.195049643 +0300 -@@ -6,11 +6,14 @@ - struct mnt_namespace; - struct fs_struct; - struct user_namespace; -+struct vfsmount; - - extern struct mnt_namespace *copy_mnt_ns(unsigned long, struct mnt_namespace *, - struct user_namespace *, struct fs_struct *); - extern void put_mnt_ns(struct mnt_namespace *ns); - -+extern int is_current_mnt_ns(struct vfsmount *mnt); -+ - extern const struct file_operations proc_mounts_operations; - extern const struct file_operations proc_mountinfo_operations; - extern const struct file_operations proc_mountstats_operations; -diff -Nurp linux-5.6.3/include/linux/splice.h linux-5.6.3-aufs/include/linux/splice.h ---- linux-5.6.3/include/linux/splice.h 2020-03-30 01:25:41.000000000 +0300 -+++ linux-5.6.3-aufs/include/linux/splice.h 2020-04-10 12:40:52.195049643 +0300 -@@ -87,4 +87,10 @@ extern void splice_shrink_spd(struct spl - - extern const struct pipe_buf_operations page_cache_pipe_buf_ops; - extern const struct pipe_buf_operations default_pipe_buf_ops; -+ -+extern long do_splice_from(struct pipe_inode_info *pipe, struct file *out, -+ loff_t *ppos, size_t len, unsigned int flags); -+extern long do_splice_to(struct file *in, loff_t *ppos, -+ struct pipe_inode_info *pipe, size_t len, -+ unsigned int flags); - #endif -diff -Nurp linux-5.6.3/include/uapi/linux/aufs_type.h linux-5.6.3-aufs/include/uapi/linux/aufs_type.h ---- linux-5.6.3/include/uapi/linux/aufs_type.h 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/include/uapi/linux/aufs_type.h 2020-04-10 12:40:52.195049643 +0300 -@@ -0,0 +1,439 @@ -+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+#ifndef __AUFS_TYPE_H__ -+#define __AUFS_TYPE_H__ -+ -+#define AUFS_NAME "aufs" -+ -+#ifdef __KERNEL__ -+/* -+ * define it before including all other headers. -+ * sched.h may use pr_* macros before defining "current", so define the -+ * no-current version first, and re-define later. -+ */ -+#define pr_fmt(fmt) AUFS_NAME " %s:%d: " fmt, __func__, __LINE__ -+#include -+#undef pr_fmt -+#define pr_fmt(fmt) \ -+ AUFS_NAME " %s:%d:%.*s[%d]: " fmt, __func__, __LINE__, \ -+ (int)sizeof(current->comm), current->comm, current->pid -+#include -+#else -+#include -+#include -+#include -+#endif /* __KERNEL__ */ -+ -+#define AUFS_VERSION "5.5" -+ -+/* todo? move this to linux-2.6.19/include/magic.h */ -+#define AUFS_SUPER_MAGIC ('a' << 24 | 'u' << 16 | 'f' << 8 | 's') -+ -+/* ---------------------------------------------------------------------- */ -+ -+#ifdef __KERNEL__ -+#ifdef CONFIG_AUFS_BRANCH_MAX_127 -+typedef int8_t aufs_bindex_t; -+#define AUFS_BRANCH_MAX 127 -+#else -+typedef int16_t aufs_bindex_t; -+#ifdef CONFIG_AUFS_BRANCH_MAX_511 -+#define AUFS_BRANCH_MAX 511 -+#elif defined(CONFIG_AUFS_BRANCH_MAX_1023) -+#define AUFS_BRANCH_MAX 1023 -+#elif defined(CONFIG_AUFS_BRANCH_MAX_32767) -+#define AUFS_BRANCH_MAX 32767 -+#endif -+#endif -+ -+#ifndef AUFS_BRANCH_MAX -+#error unknown CONFIG_AUFS_BRANCH_MAX value -+#endif -+#endif /* __KERNEL__ */ -+ -+/* ---------------------------------------------------------------------- */ -+ -+#define AUFS_FSTYPE AUFS_NAME -+ -+#define AUFS_ROOT_INO 2 -+#define AUFS_FIRST_INO 11 -+ -+#define AUFS_WH_PFX ".wh." -+#define AUFS_WH_PFX_LEN ((int)sizeof(AUFS_WH_PFX) - 1) -+#define AUFS_WH_TMP_LEN 4 -+/* a limit for rmdir/rename a dir and copyup */ -+#define AUFS_MAX_NAMELEN (NAME_MAX \ -+ - AUFS_WH_PFX_LEN * 2 /* doubly whiteouted */\ -+ - 1 /* dot */\ -+ - AUFS_WH_TMP_LEN) /* hex */ -+#define AUFS_XINO_FNAME "." AUFS_NAME ".xino" -+#define AUFS_XINO_DEFPATH "/tmp/" AUFS_XINO_FNAME -+#define AUFS_XINO_DEF_SEC 30 /* seconds */ -+#define AUFS_XINO_DEF_TRUNC 45 /* percentage */ -+#define AUFS_DIRWH_DEF 3 -+#define AUFS_RDCACHE_DEF 10 /* seconds */ -+#define AUFS_RDCACHE_MAX 3600 /* seconds */ -+#define AUFS_RDBLK_DEF 512 /* bytes */ -+#define AUFS_RDHASH_DEF 32 -+#define AUFS_WKQ_NAME AUFS_NAME "d" -+#define AUFS_MFS_DEF_SEC 30 /* seconds */ -+#define AUFS_MFS_MAX_SEC 3600 /* seconds */ -+#define AUFS_FHSM_CACHE_DEF_SEC 30 /* seconds */ -+#define AUFS_PLINK_WARN 50 /* number of plinks in a single bucket */ -+ -+/* pseudo-link maintenace under /proc */ -+#define AUFS_PLINK_MAINT_NAME "plink_maint" -+#define AUFS_PLINK_MAINT_DIR "fs/" AUFS_NAME -+#define AUFS_PLINK_MAINT_PATH AUFS_PLINK_MAINT_DIR "/" AUFS_PLINK_MAINT_NAME -+ -+/* dirren, renamed dir */ -+#define AUFS_DR_INFO_PFX AUFS_WH_PFX ".dr." -+#define AUFS_DR_BRHINO_NAME AUFS_WH_PFX "hino" -+/* whiteouted doubly */ -+#define AUFS_WH_DR_INFO_PFX AUFS_WH_PFX AUFS_DR_INFO_PFX -+#define AUFS_WH_DR_BRHINO AUFS_WH_PFX AUFS_DR_BRHINO_NAME -+ -+#define AUFS_DIROPQ_NAME AUFS_WH_PFX ".opq" /* whiteouted doubly */ -+#define AUFS_WH_DIROPQ AUFS_WH_PFX AUFS_DIROPQ_NAME -+ -+#define AUFS_BASE_NAME AUFS_WH_PFX AUFS_NAME -+#define AUFS_PLINKDIR_NAME AUFS_WH_PFX "plnk" -+#define AUFS_ORPHDIR_NAME AUFS_WH_PFX "orph" -+ -+/* doubly whiteouted */ -+#define AUFS_WH_BASE AUFS_WH_PFX AUFS_BASE_NAME -+#define AUFS_WH_PLINKDIR AUFS_WH_PFX AUFS_PLINKDIR_NAME -+#define AUFS_WH_ORPHDIR AUFS_WH_PFX AUFS_ORPHDIR_NAME -+ -+/* branch permissions and attributes */ -+#define AUFS_BRPERM_RW "rw" -+#define AUFS_BRPERM_RO "ro" -+#define AUFS_BRPERM_RR "rr" -+#define AUFS_BRATTR_COO_REG "coo_reg" -+#define AUFS_BRATTR_COO_ALL "coo_all" -+#define AUFS_BRATTR_FHSM "fhsm" -+#define AUFS_BRATTR_UNPIN "unpin" -+#define AUFS_BRATTR_ICEX "icex" -+#define AUFS_BRATTR_ICEX_SEC "icexsec" -+#define AUFS_BRATTR_ICEX_SYS "icexsys" -+#define AUFS_BRATTR_ICEX_TR "icextr" -+#define AUFS_BRATTR_ICEX_USR "icexusr" -+#define AUFS_BRATTR_ICEX_OTH "icexoth" -+#define AUFS_BRRATTR_WH "wh" -+#define AUFS_BRWATTR_NLWH "nolwh" -+#define AUFS_BRWATTR_MOO "moo" -+ -+#define AuBrPerm_RW 1 /* writable, hardlinkable wh */ -+#define AuBrPerm_RO (1 << 1) /* readonly */ -+#define AuBrPerm_RR (1 << 2) /* natively readonly */ -+#define AuBrPerm_Mask (AuBrPerm_RW | AuBrPerm_RO | AuBrPerm_RR) -+ -+#define AuBrAttr_COO_REG (1 << 3) /* copy-up on open */ -+#define AuBrAttr_COO_ALL (1 << 4) -+#define AuBrAttr_COO_Mask (AuBrAttr_COO_REG | AuBrAttr_COO_ALL) -+ -+#define AuBrAttr_FHSM (1 << 5) /* file-based hsm */ -+#define AuBrAttr_UNPIN (1 << 6) /* rename-able top dir of -+ branch. meaningless since -+ linux-3.18-rc1 */ -+ -+/* ignore error in copying XATTR */ -+#define AuBrAttr_ICEX_SEC (1 << 7) -+#define AuBrAttr_ICEX_SYS (1 << 8) -+#define AuBrAttr_ICEX_TR (1 << 9) -+#define AuBrAttr_ICEX_USR (1 << 10) -+#define AuBrAttr_ICEX_OTH (1 << 11) -+#define AuBrAttr_ICEX (AuBrAttr_ICEX_SEC \ -+ | AuBrAttr_ICEX_SYS \ -+ | AuBrAttr_ICEX_TR \ -+ | AuBrAttr_ICEX_USR \ -+ | AuBrAttr_ICEX_OTH) -+ -+#define AuBrRAttr_WH (1 << 12) /* whiteout-able */ -+#define AuBrRAttr_Mask AuBrRAttr_WH -+ -+#define AuBrWAttr_NoLinkWH (1 << 13) /* un-hardlinkable whiteouts */ -+#define AuBrWAttr_MOO (1 << 14) /* move-up on open */ -+#define AuBrWAttr_Mask (AuBrWAttr_NoLinkWH | AuBrWAttr_MOO) -+ -+#define AuBrAttr_CMOO_Mask (AuBrAttr_COO_Mask | AuBrWAttr_MOO) -+ -+/* #warning test userspace */ -+#ifdef __KERNEL__ -+#ifndef CONFIG_AUFS_FHSM -+#undef AuBrAttr_FHSM -+#define AuBrAttr_FHSM 0 -+#endif -+#ifndef CONFIG_AUFS_XATTR -+#undef AuBrAttr_ICEX -+#define AuBrAttr_ICEX 0 -+#undef AuBrAttr_ICEX_SEC -+#define AuBrAttr_ICEX_SEC 0 -+#undef AuBrAttr_ICEX_SYS -+#define AuBrAttr_ICEX_SYS 0 -+#undef AuBrAttr_ICEX_TR -+#define AuBrAttr_ICEX_TR 0 -+#undef AuBrAttr_ICEX_USR -+#define AuBrAttr_ICEX_USR 0 -+#undef AuBrAttr_ICEX_OTH -+#define AuBrAttr_ICEX_OTH 0 -+#endif -+#endif -+ -+/* the longest combination */ -+/* AUFS_BRATTR_ICEX and AUFS_BRATTR_ICEX_TR don't affect here */ -+#define AuBrPermStrSz sizeof(AUFS_BRPERM_RW \ -+ "+" AUFS_BRATTR_COO_REG \ -+ "+" AUFS_BRATTR_FHSM \ -+ "+" AUFS_BRATTR_UNPIN \ -+ "+" AUFS_BRATTR_ICEX_SEC \ -+ "+" AUFS_BRATTR_ICEX_SYS \ -+ "+" AUFS_BRATTR_ICEX_USR \ -+ "+" AUFS_BRATTR_ICEX_OTH \ -+ "+" AUFS_BRWATTR_NLWH) -+ -+typedef struct { -+ char a[AuBrPermStrSz]; -+} au_br_perm_str_t; -+ -+static inline int au_br_writable(int brperm) -+{ -+ return brperm & AuBrPerm_RW; -+} -+ -+static inline int au_br_whable(int brperm) -+{ -+ return brperm & (AuBrPerm_RW | AuBrRAttr_WH); -+} -+ -+static inline int au_br_wh_linkable(int brperm) -+{ -+ return !(brperm & AuBrWAttr_NoLinkWH); -+} -+ -+static inline int au_br_cmoo(int brperm) -+{ -+ return brperm & AuBrAttr_CMOO_Mask; -+} -+ -+static inline int au_br_fhsm(int brperm) -+{ -+ return brperm & AuBrAttr_FHSM; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* ioctl */ -+enum { -+ /* readdir in userspace */ -+ AuCtl_RDU, -+ AuCtl_RDU_INO, -+ -+ AuCtl_WBR_FD, /* pathconf wrapper */ -+ AuCtl_IBUSY, /* busy inode */ -+ AuCtl_MVDOWN, /* move-down */ -+ AuCtl_BR, /* info about branches */ -+ AuCtl_FHSM_FD /* connection for fhsm */ -+}; -+ -+/* borrowed from linux/include/linux/kernel.h */ -+#ifndef ALIGN -+#ifdef _GNU_SOURCE -+#define ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a)-1) -+#else -+#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) -+#endif -+#define __ALIGN_MASK(x, mask) (((x)+(mask))&~(mask)) -+#endif -+ -+/* borrowed from linux/include/linux/compiler-gcc3.h */ -+#ifndef __aligned -+#define __aligned(x) __attribute__((aligned(x))) -+#endif -+ -+#ifdef __KERNEL__ -+#ifndef __packed -+#define __packed __attribute__((packed)) -+#endif -+#endif -+ -+struct au_rdu_cookie { -+ uint64_t h_pos; -+ int16_t bindex; -+ uint8_t flags; -+ uint8_t pad; -+ uint32_t generation; -+} __aligned(8); -+ -+struct au_rdu_ent { -+ uint64_t ino; -+ int16_t bindex; -+ uint8_t type; -+ uint8_t nlen; -+ uint8_t wh; -+ char name[0]; -+} __aligned(8); -+ -+static inline int au_rdu_len(int nlen) -+{ -+ /* include the terminating NULL */ -+ return ALIGN(sizeof(struct au_rdu_ent) + nlen + 1, -+ sizeof(uint64_t)); -+} -+ -+union au_rdu_ent_ul { -+ struct au_rdu_ent __user *e; -+ uint64_t ul; -+}; -+ -+enum { -+ AufsCtlRduV_SZ, -+ AufsCtlRduV_End -+}; -+ -+struct aufs_rdu { -+ /* input */ -+ union { -+ uint64_t sz; /* AuCtl_RDU */ -+ uint64_t nent; /* AuCtl_RDU_INO */ -+ }; -+ union au_rdu_ent_ul ent; -+ uint16_t verify[AufsCtlRduV_End]; -+ -+ /* input/output */ -+ uint32_t blk; -+ -+ /* output */ -+ union au_rdu_ent_ul tail; -+ /* number of entries which were added in a single call */ -+ uint64_t rent; -+ uint8_t full; -+ uint8_t shwh; -+ -+ struct au_rdu_cookie cookie; -+} __aligned(8); -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* dirren. the branch is identified by the filename who contains this */ -+struct au_drinfo { -+ uint64_t ino; -+ union { -+ uint8_t oldnamelen; -+ uint64_t _padding; -+ }; -+ uint8_t oldname[0]; -+} __aligned(8); -+ -+struct au_drinfo_fdata { -+ uint32_t magic; -+ struct au_drinfo drinfo; -+} __aligned(8); -+ -+#define AUFS_DRINFO_MAGIC_V1 ('a' << 24 | 'd' << 16 | 'r' << 8 | 0x01) -+/* future */ -+#define AUFS_DRINFO_MAGIC_V2 ('a' << 24 | 'd' << 16 | 'r' << 8 | 0x02) -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct aufs_wbr_fd { -+ uint32_t oflags; -+ int16_t brid; -+} __aligned(8); -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct aufs_ibusy { -+ uint64_t ino, h_ino; -+ int16_t bindex; -+} __aligned(8); -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* error code for move-down */ -+/* the actual message strings are implemented in aufs-util.git */ -+enum { -+ EAU_MVDOWN_OPAQUE = 1, -+ EAU_MVDOWN_WHITEOUT, -+ EAU_MVDOWN_UPPER, -+ EAU_MVDOWN_BOTTOM, -+ EAU_MVDOWN_NOUPPER, -+ EAU_MVDOWN_NOLOWERBR, -+ EAU_Last -+}; -+ -+/* flags for move-down */ -+#define AUFS_MVDOWN_DMSG 1 -+#define AUFS_MVDOWN_OWLOWER (1 << 1) /* overwrite lower */ -+#define AUFS_MVDOWN_KUPPER (1 << 2) /* keep upper */ -+#define AUFS_MVDOWN_ROLOWER (1 << 3) /* do even if lower is RO */ -+#define AUFS_MVDOWN_ROLOWER_R (1 << 4) /* did on lower RO */ -+#define AUFS_MVDOWN_ROUPPER (1 << 5) /* do even if upper is RO */ -+#define AUFS_MVDOWN_ROUPPER_R (1 << 6) /* did on upper RO */ -+#define AUFS_MVDOWN_BRID_UPPER (1 << 7) /* upper brid */ -+#define AUFS_MVDOWN_BRID_LOWER (1 << 8) /* lower brid */ -+#define AUFS_MVDOWN_FHSM_LOWER (1 << 9) /* find fhsm attr for lower */ -+#define AUFS_MVDOWN_STFS (1 << 10) /* req. stfs */ -+#define AUFS_MVDOWN_STFS_FAILED (1 << 11) /* output: stfs is unusable */ -+#define AUFS_MVDOWN_BOTTOM (1 << 12) /* output: no more lowers */ -+ -+/* index for move-down */ -+enum { -+ AUFS_MVDOWN_UPPER, -+ AUFS_MVDOWN_LOWER, -+ AUFS_MVDOWN_NARRAY -+}; -+ -+/* -+ * additional info of move-down -+ * number of free blocks and inodes. -+ * subset of struct kstatfs, but smaller and always 64bit. -+ */ -+struct aufs_stfs { -+ uint64_t f_blocks; -+ uint64_t f_bavail; -+ uint64_t f_files; -+ uint64_t f_ffree; -+}; -+ -+struct aufs_stbr { -+ int16_t brid; /* optional input */ -+ int16_t bindex; /* output */ -+ struct aufs_stfs stfs; /* output when AUFS_MVDOWN_STFS set */ -+} __aligned(8); -+ -+struct aufs_mvdown { -+ uint32_t flags; /* input/output */ -+ struct aufs_stbr stbr[AUFS_MVDOWN_NARRAY]; /* input/output */ -+ int8_t au_errno; /* output */ -+} __aligned(8); -+ -+/* ---------------------------------------------------------------------- */ -+ -+union aufs_brinfo { -+ /* PATH_MAX may differ between kernel-space and user-space */ -+ char _spacer[4096]; -+ struct { -+ int16_t id; -+ int perm; -+ char path[0]; -+ }; -+} __aligned(8); -+ -+/* ---------------------------------------------------------------------- */ -+ -+#define AuCtlType 'A' -+#define AUFS_CTL_RDU _IOWR(AuCtlType, AuCtl_RDU, struct aufs_rdu) -+#define AUFS_CTL_RDU_INO _IOWR(AuCtlType, AuCtl_RDU_INO, struct aufs_rdu) -+#define AUFS_CTL_WBR_FD _IOW(AuCtlType, AuCtl_WBR_FD, \ -+ struct aufs_wbr_fd) -+#define AUFS_CTL_IBUSY _IOWR(AuCtlType, AuCtl_IBUSY, struct aufs_ibusy) -+#define AUFS_CTL_MVDOWN _IOWR(AuCtlType, AuCtl_MVDOWN, \ -+ struct aufs_mvdown) -+#define AUFS_CTL_BRINFO _IOW(AuCtlType, AuCtl_BR, union aufs_brinfo) -+#define AUFS_CTL_FHSM_FD _IOW(AuCtlType, AuCtl_FHSM_FD, int) -+ -+#endif /* __AUFS_TYPE_H__ */ -diff -Nurp linux-5.6.3/kernel/fork.c linux-5.6.3-aufs/kernel/fork.c ---- linux-5.6.3/kernel/fork.c 2020-03-30 01:25:41.000000000 +0300 -+++ linux-5.6.3-aufs/kernel/fork.c 2020-04-10 12:40:52.195049643 +0300 -@@ -565,7 +565,7 @@ static __latent_entropy int dup_mmap(str - struct inode *inode = file_inode(file); - struct address_space *mapping = file->f_mapping; - -- get_file(file); -+ vma_get_file(tmp); - if (tmp->vm_flags & VM_DENYWRITE) - atomic_dec(&inode->i_writecount); - i_mmap_lock_write(mapping); -diff -Nurp linux-5.6.3/kernel/locking/lockdep.c linux-5.6.3-aufs/kernel/locking/lockdep.c ---- linux-5.6.3/kernel/locking/lockdep.c 2020-03-30 01:25:41.000000000 +0300 -+++ linux-5.6.3-aufs/kernel/locking/lockdep.c 2020-04-10 12:40:52.195049643 +0300 -@@ -153,7 +153,7 @@ static - struct lock_class lock_classes[MAX_LOCKDEP_KEYS]; - static DECLARE_BITMAP(lock_classes_in_use, MAX_LOCKDEP_KEYS); - --static inline struct lock_class *hlock_class(struct held_lock *hlock) -+inline struct lock_class *lockdep_hlock_class(struct held_lock *hlock) - { - unsigned int class_idx = hlock->class_idx; - -@@ -174,6 +174,7 @@ static inline struct lock_class *hlock_c - */ - return lock_classes + class_idx; - } -+#define hlock_class(hlock) lockdep_hlock_class(hlock) - - #ifdef CONFIG_LOCK_STAT - static DEFINE_PER_CPU(struct lock_class_stats[MAX_LOCKDEP_KEYS], cpu_lock_stats); -diff -Nurp linux-5.6.3/MAINTAINERS linux-5.6.3-aufs/MAINTAINERS ---- linux-5.6.3/MAINTAINERS 2020-03-30 01:25:41.000000000 +0300 -+++ linux-5.6.3-aufs/MAINTAINERS 2020-04-10 12:40:52.187049268 +0300 -@@ -2919,6 +2919,19 @@ F: include/linux/audit.h - F: include/uapi/linux/audit.h - F: kernel/audit* - -+AUFS (advanced multi layered unification filesystem) FILESYSTEM -+M: "J. R. Okajima" -+L: aufs-users@lists.sourceforge.net (members only) -+L: linux-unionfs@vger.kernel.org -+W: http://aufs.sourceforge.net -+T: git://github.com/sfjro/aufs4-linux.git -+S: Supported -+F: Documentation/filesystems/aufs/ -+F: Documentation/ABI/testing/debugfs-aufs -+F: Documentation/ABI/testing/sysfs-aufs -+F: fs/aufs/ -+F: include/uapi/linux/aufs_type.h -+ - AUXILIARY DISPLAY DRIVERS - M: Miguel Ojeda Sandonis - S: Maintained -diff -Nurp linux-5.6.3/mm/filemap.c linux-5.6.3-aufs/mm/filemap.c ---- linux-5.6.3/mm/filemap.c 2020-03-30 01:25:41.000000000 +0300 -+++ linux-5.6.3-aufs/mm/filemap.c 2020-04-10 12:40:52.196049690 +0300 -@@ -2653,7 +2653,7 @@ vm_fault_t filemap_page_mkwrite(struct v - vm_fault_t ret = VM_FAULT_LOCKED; - - sb_start_pagefault(inode->i_sb); -- file_update_time(vmf->vma->vm_file); -+ vma_file_update_time(vmf->vma); - lock_page(page); - if (page->mapping != inode->i_mapping) { - unlock_page(page); -diff -Nurp linux-5.6.3/mm/Makefile linux-5.6.3-aufs/mm/Makefile ---- linux-5.6.3/mm/Makefile 2020-03-30 01:25:41.000000000 +0300 -+++ linux-5.6.3-aufs/mm/Makefile 2020-04-10 12:40:52.195049643 +0300 -@@ -43,7 +43,7 @@ obj-y := filemap.o mempool.o oom_kill. - mm_init.o mmu_context.o percpu.o slab_common.o \ - compaction.o vmacache.o \ - interval_tree.o list_lru.o workingset.o \ -- debug.o gup.o $(mmu-y) -+ prfile.o debug.o gup.o $(mmu-y) - - # Give 'page_alloc' its own module-parameter namespace - page-alloc-y := page_alloc.o -diff -Nurp linux-5.6.3/mm/mmap.c linux-5.6.3-aufs/mm/mmap.c ---- linux-5.6.3/mm/mmap.c 2020-03-30 01:25:41.000000000 +0300 -+++ linux-5.6.3-aufs/mm/mmap.c 2020-04-10 12:40:52.196049690 +0300 -@@ -176,7 +176,7 @@ static struct vm_area_struct *remove_vma - if (vma->vm_ops && vma->vm_ops->close) - vma->vm_ops->close(vma); - if (vma->vm_file) -- fput(vma->vm_file); -+ vma_fput(vma); - mpol_put(vma_policy(vma)); - vm_area_free(vma); - return next; -@@ -907,7 +907,7 @@ again: - if (remove_next) { - if (file) { - uprobe_munmap(next, next->vm_start, next->vm_end); -- fput(file); -+ vma_fput(vma); - } - if (next->anon_vma) - anon_vma_merge(vma, next); -@@ -1829,8 +1829,8 @@ out: - return addr; - - unmap_and_free_vma: -+ vma_fput(vma); - vma->vm_file = NULL; -- fput(file); - - /* Undo any partial mapping done by a device driver. */ - unmap_region(mm, vma, prev, vma->vm_start, vma->vm_end); -@@ -2659,7 +2659,7 @@ int __split_vma(struct mm_struct *mm, st - goto out_free_mpol; - - if (new->vm_file) -- get_file(new->vm_file); -+ vma_get_file(new); - - if (new->vm_ops && new->vm_ops->open) - new->vm_ops->open(new); -@@ -2678,7 +2678,7 @@ int __split_vma(struct mm_struct *mm, st - if (new->vm_ops && new->vm_ops->close) - new->vm_ops->close(new); - if (new->vm_file) -- fput(new->vm_file); -+ vma_fput(new); - unlink_anon_vmas(new); - out_free_mpol: - mpol_put(vma_policy(new)); -@@ -2870,7 +2870,7 @@ SYSCALL_DEFINE5(remap_file_pages, unsign - struct vm_area_struct *vma; - unsigned long populate = 0; - unsigned long ret = -EINVAL; -- struct file *file; -+ struct file *file, *prfile; - - pr_warn_once("%s (%d) uses deprecated remap_file_pages() syscall. See Documentation/vm/remap_file_pages.rst.\n", - current->comm, current->pid); -@@ -2945,10 +2945,27 @@ SYSCALL_DEFINE5(remap_file_pages, unsign - } - } - -- file = get_file(vma->vm_file); -+ vma_get_file(vma); -+ file = vma->vm_file; -+ prfile = vma->vm_prfile; - ret = do_mmap_pgoff(vma->vm_file, start, size, - prot, flags, pgoff, &populate, NULL); -+ if (!IS_ERR_VALUE(ret) && file && prfile) { -+ struct vm_area_struct *new_vma; -+ -+ new_vma = find_vma(mm, ret); -+ if (!new_vma->vm_prfile) -+ new_vma->vm_prfile = prfile; -+ if (new_vma != vma) -+ get_file(prfile); -+ } -+ /* -+ * two fput()s instead of vma_fput(vma), -+ * coz vma may not be available anymore. -+ */ - fput(file); -+ if (prfile) -+ fput(prfile); - out: - up_write(&mm->mmap_sem); - if (populate) -@@ -3239,7 +3256,7 @@ struct vm_area_struct *copy_vma(struct v - if (anon_vma_clone(new_vma, vma)) - goto out_free_mempol; - if (new_vma->vm_file) -- get_file(new_vma->vm_file); -+ vma_get_file(new_vma); - if (new_vma->vm_ops && new_vma->vm_ops->open) - new_vma->vm_ops->open(new_vma); - vma_link(mm, new_vma, prev, rb_link, rb_parent); -diff -Nurp linux-5.6.3/mm/nommu.c linux-5.6.3-aufs/mm/nommu.c ---- linux-5.6.3/mm/nommu.c 2020-03-30 01:25:41.000000000 +0300 -+++ linux-5.6.3-aufs/mm/nommu.c 2020-04-10 12:40:52.196049690 +0300 -@@ -567,7 +567,7 @@ static void __put_nommu_region(struct vm - up_write(&nommu_region_sem); - - if (region->vm_file) -- fput(region->vm_file); -+ vmr_fput(region); - - /* IO memory and memory shared directly out of the pagecache - * from ramfs/tmpfs mustn't be released here */ -@@ -699,7 +699,7 @@ static void delete_vma(struct mm_struct - if (vma->vm_ops && vma->vm_ops->close) - vma->vm_ops->close(vma); - if (vma->vm_file) -- fput(vma->vm_file); -+ vma_fput(vma); - put_nommu_region(vma->vm_region); - vm_area_free(vma); - } -@@ -1222,7 +1222,7 @@ unsigned long do_mmap(struct file *file, - goto error_just_free; - } - } -- fput(region->vm_file); -+ vmr_fput(region); - kmem_cache_free(vm_region_jar, region); - region = pregion; - result = start; -@@ -1299,10 +1299,10 @@ error_just_free: - up_write(&nommu_region_sem); - error: - if (region->vm_file) -- fput(region->vm_file); -+ vmr_fput(region); - kmem_cache_free(vm_region_jar, region); - if (vma->vm_file) -- fput(vma->vm_file); -+ vma_fput(vma); - vm_area_free(vma); - return ret; - -diff -Nurp linux-5.6.3/mm/prfile.c linux-5.6.3-aufs/mm/prfile.c ---- linux-5.6.3/mm/prfile.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.6.3-aufs/mm/prfile.c 2020-04-10 12:40:52.196049690 +0300 -@@ -0,0 +1,86 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Mainly for aufs which mmap(2) different file and wants to print different -+ * path in /proc/PID/maps. -+ * Call these functions via macros defined in linux/mm.h. -+ * -+ * See Documentation/filesystems/aufs/design/06mmap.txt -+ * -+ * Copyright (c) 2014-2020 Junjro R. Okajima -+ * Copyright (c) 2014 Ian Campbell -+ */ -+ -+#include -+#include -+#include -+ -+/* #define PRFILE_TRACE */ -+static inline void prfile_trace(struct file *f, struct file *pr, -+ const char func[], int line, const char func2[]) -+{ -+#ifdef PRFILE_TRACE -+ if (pr) -+ pr_info("%s:%d: %s, %pD2\n", func, line, func2, f); -+#endif -+} -+ -+void vma_do_file_update_time(struct vm_area_struct *vma, const char func[], -+ int line) -+{ -+ struct file *f = vma->vm_file, *pr = vma->vm_prfile; -+ -+ prfile_trace(f, pr, func, line, __func__); -+ file_update_time(f); -+ if (f && pr) -+ file_update_time(pr); -+} -+ -+struct file *vma_do_pr_or_file(struct vm_area_struct *vma, const char func[], -+ int line) -+{ -+ struct file *f = vma->vm_file, *pr = vma->vm_prfile; -+ -+ prfile_trace(f, pr, func, line, __func__); -+ return (f && pr) ? pr : f; -+} -+ -+void vma_do_get_file(struct vm_area_struct *vma, const char func[], int line) -+{ -+ struct file *f = vma->vm_file, *pr = vma->vm_prfile; -+ -+ prfile_trace(f, pr, func, line, __func__); -+ get_file(f); -+ if (f && pr) -+ get_file(pr); -+} -+ -+void vma_do_fput(struct vm_area_struct *vma, const char func[], int line) -+{ -+ struct file *f = vma->vm_file, *pr = vma->vm_prfile; -+ -+ prfile_trace(f, pr, func, line, __func__); -+ fput(f); -+ if (f && pr) -+ fput(pr); -+} -+ -+#ifndef CONFIG_MMU -+struct file *vmr_do_pr_or_file(struct vm_region *region, const char func[], -+ int line) -+{ -+ struct file *f = region->vm_file, *pr = region->vm_prfile; -+ -+ prfile_trace(f, pr, func, line, __func__); -+ return (f && pr) ? pr : f; -+} -+ -+void vmr_do_fput(struct vm_region *region, const char func[], int line) -+{ -+ struct file *f = region->vm_file, *pr = region->vm_prfile; -+ -+ prfile_trace(f, pr, func, line, __func__); -+ fput(f); -+ if (f && pr) -+ fput(pr); -+} -+#endif /* !CONFIG_MMU */ diff --git a/kernel/kernel/files/patches/mageia/fs-aufs5.patch b/kernel/kernel/files/patches/mageia/fs-aufs5.patch deleted file mode 100644 index ebbde97d..00000000 --- a/kernel/kernel/files/patches/mageia/fs-aufs5.patch +++ /dev/null @@ -1,37934 +0,0 @@ -diff -Nurp linux-5.10-rc6/Documentation/ABI/testing/debugfs-aufs linux-5.10-rc6.aufs/Documentation/ABI/testing/debugfs-aufs ---- linux-5.10-rc6/Documentation/ABI/testing/debugfs-aufs 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/Documentation/ABI/testing/debugfs-aufs 2020-12-02 21:19:51.876036518 +0200 -@@ -0,0 +1,55 @@ -+What: /debug/aufs/si_/ -+Date: March 2009 -+Contact: J. R. Okajima -+Description: -+ Under /debug/aufs, a directory named si_ is created -+ per aufs mount, where is a unique id generated -+ internally. -+ -+What: /debug/aufs/si_/plink -+Date: Apr 2013 -+Contact: J. R. Okajima -+Description: -+ It has three lines and shows the information about the -+ pseudo-link. The first line is a single number -+ representing a number of buckets. The second line is a -+ number of pseudo-links per buckets (separated by a -+ blank). The last line is a single number representing a -+ total number of psedo-links. -+ When the aufs mount option 'noplink' is specified, it -+ will show "1\n0\n0\n". -+ -+What: /debug/aufs/si_/xib -+Date: March 2009 -+Contact: J. R. Okajima -+Description: -+ It shows the consumed blocks by xib (External Inode Number -+ Bitmap), its block size and file size. -+ When the aufs mount option 'noxino' is specified, it -+ will be empty. About XINO files, see the aufs manual. -+ -+What: /debug/aufs/si_/xi0, xi1 ... xiN and xiN-N -+Date: March 2009 -+Contact: J. R. Okajima -+Description: -+ It shows the consumed blocks by xino (External Inode Number -+ Translation Table), its link count, block size and file -+ size. -+ Due to the file size limit, there may exist multiple -+ xino files per branch. In this case, "-N" is added to -+ the filename and it corresponds to the index of the -+ internal xino array. "-0" is omitted. -+ When the aufs mount option 'noxino' is specified, Those -+ entries won't exist. About XINO files, see the aufs -+ manual. -+ -+What: /debug/aufs/si_/xigen -+Date: March 2009 -+Contact: J. R. Okajima -+Description: -+ It shows the consumed blocks by xigen (External Inode -+ Generation Table), its block size and file size. -+ If CONFIG_AUFS_EXPORT is disabled, this entry will not -+ be created. -+ When the aufs mount option 'noxino' is specified, it -+ will be empty. About XINO files, see the aufs manual. -diff -Nurp linux-5.10-rc6/Documentation/ABI/testing/sysfs-aufs linux-5.10-rc6.aufs/Documentation/ABI/testing/sysfs-aufs ---- linux-5.10-rc6/Documentation/ABI/testing/sysfs-aufs 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/Documentation/ABI/testing/sysfs-aufs 2020-12-02 21:19:51.876036518 +0200 -@@ -0,0 +1,31 @@ -+What: /sys/fs/aufs/si_/ -+Date: March 2009 -+Contact: J. R. Okajima -+Description: -+ Under /sys/fs/aufs, a directory named si_ is created -+ per aufs mount, where is a unique id generated -+ internally. -+ -+What: /sys/fs/aufs/si_/br0, br1 ... brN -+Date: March 2009 -+Contact: J. R. Okajima -+Description: -+ It shows the abolute path of a member directory (which -+ is called branch) in aufs, and its permission. -+ -+What: /sys/fs/aufs/si_/brid0, brid1 ... bridN -+Date: July 2013 -+Contact: J. R. Okajima -+Description: -+ It shows the id of a member directory (which is called -+ branch) in aufs. -+ -+What: /sys/fs/aufs/si_/xi_path -+Date: March 2009 -+Contact: J. R. Okajima -+Description: -+ It shows the abolute path of XINO (External Inode Number -+ Bitmap, Translation Table and Generation Table) file -+ even if it is the default path. -+ When the aufs mount option 'noxino' is specified, it -+ will be empty. About XINO files, see the aufs manual. -diff -Nurp linux-5.10-rc6/Documentation/filesystems/aufs/design/01intro.txt linux-5.10-rc6.aufs/Documentation/filesystems/aufs/design/01intro.txt ---- linux-5.10-rc6/Documentation/filesystems/aufs/design/01intro.txt 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/Documentation/filesystems/aufs/design/01intro.txt 2020-12-02 21:19:51.876036518 +0200 -@@ -0,0 +1,158 @@ -+ -+# Copyright (C) 2005-2020 Junjiro R. Okajima -+ -+Introduction -+---------------------------------------- -+ -+aufs [ei ju: ef es] | /ey-yoo-ef-es/ | [a u f s] -+1. abbrev. for "advanced multi-layered unification filesystem". -+2. abbrev. for "another unionfs". -+3. abbrev. for "auf das" in German which means "on the" in English. -+ Ex. "Butter aufs Brot"(G) means "butter onto bread"(E). -+ But "Filesystem aufs Filesystem" is hard to understand. -+4. abbrev. for "African Urban Fashion Show". -+ -+AUFS is a filesystem with features: -+- multi layered stackable unification filesystem, the member directory -+ is called as a branch. -+- branch permission and attribute, 'readonly', 'real-readonly', -+ 'readwrite', 'whiteout-able', 'link-able whiteout', etc. and their -+ combination. -+- internal "file copy-on-write". -+- logical deletion, whiteout. -+- dynamic branch manipulation, adding, deleting and changing permission. -+- allow bypassing aufs, user's direct branch access. -+- external inode number translation table and bitmap which maintains the -+ persistent aufs inode number. -+- seekable directory, including NFS readdir. -+- file mapping, mmap and sharing pages. -+- pseudo-link, hardlink over branches. -+- loopback mounted filesystem as a branch. -+- several policies to select one among multiple writable branches. -+- revert a single systemcall when an error occurs in aufs. -+- and more... -+ -+ -+Multi Layered Stackable Unification Filesystem -+---------------------------------------------------------------------- -+Most people already knows what it is. -+It is a filesystem which unifies several directories and provides a -+merged single directory. When users access a file, the access will be -+passed/re-directed/converted (sorry, I am not sure which English word is -+correct) to the real file on the member filesystem. The member -+filesystem is called 'lower filesystem' or 'branch' and has a mode -+'readonly' and 'readwrite.' And the deletion for a file on the lower -+readonly branch is handled by creating 'whiteout' on the upper writable -+branch. -+ -+On LKML, there have been discussions about UnionMount (Jan Blunck, -+Bharata B Rao and Valerie Aurora) and Unionfs (Erez Zadok). They took -+different approaches to implement the merged-view. -+The former tries putting it into VFS, and the latter implements as a -+separate filesystem. -+(If I misunderstand about these implementations, please let me know and -+I shall correct it. Because it is a long time ago when I read their -+source files last time). -+ -+UnionMount's approach will be able to small, but may be hard to share -+branches between several UnionMount since the whiteout in it is -+implemented in the inode on branch filesystem and always -+shared. According to Bharata's post, readdir does not seems to be -+finished yet. -+There are several missing features known in this implementations such as -+- for users, the inode number may change silently. eg. copy-up. -+- link(2) may break by copy-up. -+- read(2) may get an obsoleted filedata (fstat(2) too). -+- fcntl(F_SETLK) may be broken by copy-up. -+- unnecessary copy-up may happen, for example mmap(MAP_PRIVATE) after -+ open(O_RDWR). -+ -+In linux-3.18, "overlay" filesystem (formerly known as "overlayfs") was -+merged into mainline. This is another implementation of UnionMount as a -+separated filesystem. All the limitations and known problems which -+UnionMount are equally inherited to "overlay" filesystem. -+ -+Unionfs has a longer history. When I started implementing a stackable -+filesystem (Aug 2005), it already existed. It has virtual super_block, -+inode, dentry and file objects and they have an array pointing lower -+same kind objects. After contributing many patches for Unionfs, I -+re-started my project AUFS (Jun 2006). -+ -+In AUFS, the structure of filesystem resembles to Unionfs, but I -+implemented my own ideas, approaches and enhancements and it became -+totally different one. -+ -+Comparing DM snapshot and fs based implementation -+- the number of bytes to be copied between devices is much smaller. -+- the type of filesystem must be one and only. -+- the fs must be writable, no readonly fs, even for the lower original -+ device. so the compression fs will not be usable. but if we use -+ loopback mount, we may address this issue. -+ for instance, -+ mount /cdrom/squashfs.img /sq -+ losetup /sq/ext2.img -+ losetup /somewhere/cow -+ dmsetup "snapshot /dev/loop0 /dev/loop1 ..." -+- it will be difficult (or needs more operations) to extract the -+ difference between the original device and COW. -+- DM snapshot-merge may help a lot when users try merging. in the -+ fs-layer union, users will use rsync(1). -+ -+You may want to read my old paper "Filesystems in LiveCD" -+(http://aufs.sourceforge.net/aufs2/report/sq/sq.pdf). -+ -+ -+Several characters/aspects/persona of aufs -+---------------------------------------------------------------------- -+ -+Aufs has several characters, aspects or persona. -+1. a filesystem, callee of VFS helper -+2. sub-VFS, caller of VFS helper for branches -+3. a virtual filesystem which maintains persistent inode number -+4. reader/writer of files on branches such like an application -+ -+1. Callee of VFS Helper -+As an ordinary linux filesystem, aufs is a callee of VFS. For instance, -+unlink(2) from an application reaches sys_unlink() kernel function and -+then vfs_unlink() is called. vfs_unlink() is one of VFS helper and it -+calls filesystem specific unlink operation. Actually aufs implements the -+unlink operation but it behaves like a redirector. -+ -+2. Caller of VFS Helper for Branches -+aufs_unlink() passes the unlink request to the branch filesystem as if -+it were called from VFS. So the called unlink operation of the branch -+filesystem acts as usual. As a caller of VFS helper, aufs should handle -+every necessary pre/post operation for the branch filesystem. -+- acquire the lock for the parent dir on a branch -+- lookup in a branch -+- revalidate dentry on a branch -+- mnt_want_write() for a branch -+- vfs_unlink() for a branch -+- mnt_drop_write() for a branch -+- release the lock on a branch -+ -+3. Persistent Inode Number -+One of the most important issue for a filesystem is to maintain inode -+numbers. This is particularly important to support exporting a -+filesystem via NFS. Aufs is a virtual filesystem which doesn't have a -+backend block device for its own. But some storage is necessary to -+keep and maintain the inode numbers. It may be a large space and may not -+suit to keep in memory. Aufs rents some space from its first writable -+branch filesystem (by default) and creates file(s) on it. These files -+are created by aufs internally and removed soon (currently) keeping -+opened. -+Note: Because these files are removed, they are totally gone after -+ unmounting aufs. It means the inode numbers are not persistent -+ across unmount or reboot. I have a plan to make them really -+ persistent which will be important for aufs on NFS server. -+ -+4. Read/Write Files Internally (copy-on-write) -+Because a branch can be readonly, when you write a file on it, aufs will -+"copy-up" it to the upper writable branch internally. And then write the -+originally requested thing to the file. Generally kernel doesn't -+open/read/write file actively. In aufs, even a single write may cause a -+internal "file copy". This behaviour is very similar to cp(1) command. -+ -+Some people may think it is better to pass such work to user space -+helper, instead of doing in kernel space. Actually I am still thinking -+about it. But currently I have implemented it in kernel space. -diff -Nurp linux-5.10-rc6/Documentation/filesystems/aufs/design/02struct.txt linux-5.10-rc6.aufs/Documentation/filesystems/aufs/design/02struct.txt ---- linux-5.10-rc6/Documentation/filesystems/aufs/design/02struct.txt 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/Documentation/filesystems/aufs/design/02struct.txt 2020-12-02 21:19:51.876036518 +0200 -@@ -0,0 +1,245 @@ -+ -+# Copyright (C) 2005-2020 Junjiro R. Okajima -+ -+Basic Aufs Internal Structure -+ -+Superblock/Inode/Dentry/File Objects -+---------------------------------------------------------------------- -+As like an ordinary filesystem, aufs has its own -+superblock/inode/dentry/file objects. All these objects have a -+dynamically allocated array and store the same kind of pointers to the -+lower filesystem, branch. -+For example, when you build a union with one readwrite branch and one -+readonly, mounted /au, /rw and /ro respectively. -+- /au = /rw + /ro -+- /ro/fileA exists but /rw/fileA -+ -+Aufs lookup operation finds /ro/fileA and gets dentry for that. These -+pointers are stored in a aufs dentry. The array in aufs dentry will be, -+- [0] = NULL (because /rw/fileA doesn't exist) -+- [1] = /ro/fileA -+ -+This style of an array is essentially same to the aufs -+superblock/inode/dentry/file objects. -+ -+Because aufs supports manipulating branches, ie. add/delete/change -+branches dynamically, these objects has its own generation. When -+branches are changed, the generation in aufs superblock is -+incremented. And a generation in other object are compared when it is -+accessed. When a generation in other objects are obsoleted, aufs -+refreshes the internal array. -+ -+ -+Superblock -+---------------------------------------------------------------------- -+Additionally aufs superblock has some data for policies to select one -+among multiple writable branches, XIB files, pseudo-links and kobject. -+See below in detail. -+About the policies which supports copy-down a directory, see -+wbr_policy.txt too. -+ -+ -+Branch and XINO(External Inode Number Translation Table) -+---------------------------------------------------------------------- -+Every branch has its own xino (external inode number translation table) -+file. The xino file is created and unlinked by aufs internally. When two -+members of a union exist on the same filesystem, they share the single -+xino file. -+The struct of a xino file is simple, just a sequence of aufs inode -+numbers which is indexed by the lower inode number. -+In the above sample, assume the inode number of /ro/fileA is i111 and -+aufs assigns the inode number i999 for fileA. Then aufs writes 999 as -+4(8) bytes at 111 * 4(8) bytes offset in the xino file. -+ -+When the inode numbers are not contiguous, the xino file will be sparse -+which has a hole in it and doesn't consume as much disk space as it -+might appear. If your branch filesystem consumes disk space for such -+holes, then you should specify 'xino=' option at mounting aufs. -+ -+Aufs has a mount option to free the disk blocks for such holes in XINO -+files on tmpfs or ramdisk. But it is not so effective actually. If you -+meet a problem of disk shortage due to XINO files, then you should try -+"tmpfs-ino.patch" (and "vfs-ino.patch" too) in aufs4-standalone.git. -+The patch localizes the assignment inumbers per tmpfs-mount and avoid -+the holes in XINO files. -+ -+Also a writable branch has three kinds of "whiteout bases". All these -+are existed when the branch is joined to aufs, and their names are -+whiteout-ed doubly, so that users will never see their names in aufs -+hierarchy. -+1. a regular file which will be hardlinked to all whiteouts. -+2. a directory to store a pseudo-link. -+3. a directory to store an "orphan"-ed file temporary. -+ -+1. Whiteout Base -+ When you remove a file on a readonly branch, aufs handles it as a -+ logical deletion and creates a whiteout on the upper writable branch -+ as a hardlink of this file in order not to consume inode on the -+ writable branch. -+2. Pseudo-link Dir -+ See below, Pseudo-link. -+3. Step-Parent Dir -+ When "fileC" exists on the lower readonly branch only and it is -+ opened and removed with its parent dir, and then user writes -+ something into it, then aufs copies-up fileC to this -+ directory. Because there is no other dir to store fileC. After -+ creating a file under this dir, the file is unlinked. -+ -+Because aufs supports manipulating branches, ie. add/delete/change -+dynamically, a branch has its own id. When the branch order changes, -+aufs finds the new index by searching the branch id. -+ -+ -+Pseudo-link -+---------------------------------------------------------------------- -+Assume "fileA" exists on the lower readonly branch only and it is -+hardlinked to "fileB" on the branch. When you write something to fileA, -+aufs copies-up it to the upper writable branch. Additionally aufs -+creates a hardlink under the Pseudo-link Directory of the writable -+branch. The inode of a pseudo-link is kept in aufs super_block as a -+simple list. If fileB is read after unlinking fileA, aufs returns -+filedata from the pseudo-link instead of the lower readonly -+branch. Because the pseudo-link is based upon the inode, to keep the -+inode number by xino (see above) is essentially necessary. -+ -+All the hardlinks under the Pseudo-link Directory of the writable branch -+should be restored in a proper location later. Aufs provides a utility -+to do this. The userspace helpers executed at remounting and unmounting -+aufs by default. -+During this utility is running, it puts aufs into the pseudo-link -+maintenance mode. In this mode, only the process which began the -+maintenance mode (and its child processes) is allowed to operate in -+aufs. Some other processes which are not related to the pseudo-link will -+be allowed to run too, but the rest have to return an error or wait -+until the maintenance mode ends. If a process already acquires an inode -+mutex (in VFS), it has to return an error. -+ -+ -+XIB(external inode number bitmap) -+---------------------------------------------------------------------- -+Addition to the xino file per a branch, aufs has an external inode number -+bitmap in a superblock object. It is also an internal file such like a -+xino file. -+It is a simple bitmap to mark whether the aufs inode number is in-use or -+not. -+To reduce the file I/O, aufs prepares a single memory page to cache xib. -+ -+As well as XINO files, aufs has a feature to truncate/refresh XIB to -+reduce the number of consumed disk blocks for these files. -+ -+ -+Virtual or Vertical Dir, and Readdir in Userspace -+---------------------------------------------------------------------- -+In order to support multiple layers (branches), aufs readdir operation -+constructs a virtual dir block on memory. For readdir, aufs calls -+vfs_readdir() internally for each dir on branches, merges their entries -+with eliminating the whiteout-ed ones, and sets it to file (dir) -+object. So the file object has its entry list until it is closed. The -+entry list will be updated when the file position is zero and becomes -+obsoleted. This decision is made in aufs automatically. -+ -+The dynamically allocated memory block for the name of entries has a -+unit of 512 bytes (by default) and stores the names contiguously (no -+padding). Another block for each entry is handled by kmem_cache too. -+During building dir blocks, aufs creates hash list and judging whether -+the entry is whiteouted by its upper branch or already listed. -+The merged result is cached in the corresponding inode object and -+maintained by a customizable life-time option. -+ -+Some people may call it can be a security hole or invite DoS attack -+since the opened and once readdir-ed dir (file object) holds its entry -+list and becomes a pressure for system memory. But I'd say it is similar -+to files under /proc or /sys. The virtual files in them also holds a -+memory page (generally) while they are opened. When an idea to reduce -+memory for them is introduced, it will be applied to aufs too. -+For those who really hate this situation, I've developed readdir(3) -+library which operates this merging in userspace. You just need to set -+LD_PRELOAD environment variable, and aufs will not consume no memory in -+kernel space for readdir(3). -+ -+ -+Workqueue -+---------------------------------------------------------------------- -+Aufs sometimes requires privilege access to a branch. For instance, -+in copy-up/down operation. When a user process is going to make changes -+to a file which exists in the lower readonly branch only, and the mode -+of one of ancestor directories may not be writable by a user -+process. Here aufs copy-up the file with its ancestors and they may -+require privilege to set its owner/group/mode/etc. -+This is a typical case of a application character of aufs (see -+Introduction). -+ -+Aufs uses workqueue synchronously for this case. It creates its own -+workqueue. The workqueue is a kernel thread and has privilege. Aufs -+passes the request to call mkdir or write (for example), and wait for -+its completion. This approach solves a problem of a signal handler -+simply. -+If aufs didn't adopt the workqueue and changed the privilege of the -+process, then the process may receive the unexpected SIGXFSZ or other -+signals. -+ -+Also aufs uses the system global workqueue ("events" kernel thread) too -+for asynchronous tasks, such like handling inotify/fsnotify, re-creating a -+whiteout base and etc. This is unrelated to a privilege. -+Most of aufs operation tries acquiring a rw_semaphore for aufs -+superblock at the beginning, at the same time waits for the completion -+of all queued asynchronous tasks. -+ -+ -+Whiteout -+---------------------------------------------------------------------- -+The whiteout in aufs is very similar to Unionfs's. That is represented -+by its filename. UnionMount takes an approach of a file mode, but I am -+afraid several utilities (find(1) or something) will have to support it. -+ -+Basically the whiteout represents "logical deletion" which stops aufs to -+lookup further, but also it represents "dir is opaque" which also stop -+further lookup. -+ -+In aufs, rmdir(2) and rename(2) for dir uses whiteout alternatively. -+In order to make several functions in a single systemcall to be -+revertible, aufs adopts an approach to rename a directory to a temporary -+unique whiteouted name. -+For example, in rename(2) dir where the target dir already existed, aufs -+renames the target dir to a temporary unique whiteouted name before the -+actual rename on a branch, and then handles other actions (make it opaque, -+update the attributes, etc). If an error happens in these actions, aufs -+simply renames the whiteouted name back and returns an error. If all are -+succeeded, aufs registers a function to remove the whiteouted unique -+temporary name completely and asynchronously to the system global -+workqueue. -+ -+ -+Copy-up -+---------------------------------------------------------------------- -+It is a well-known feature or concept. -+When user modifies a file on a readonly branch, aufs operate "copy-up" -+internally and makes change to the new file on the upper writable branch. -+When the trigger systemcall does not update the timestamps of the parent -+dir, aufs reverts it after copy-up. -+ -+ -+Move-down (aufs3.9 and later) -+---------------------------------------------------------------------- -+"Copy-up" is one of the essential feature in aufs. It copies a file from -+the lower readonly branch to the upper writable branch when a user -+changes something about the file. -+"Move-down" is an opposite action of copy-up. Basically this action is -+ran manually instead of automatically and internally. -+For desgin and implementation, aufs has to consider these issues. -+- whiteout for the file may exist on the lower branch. -+- ancestor directories may not exist on the lower branch. -+- diropq for the ancestor directories may exist on the upper branch. -+- free space on the lower branch will reduce. -+- another access to the file may happen during moving-down, including -+ UDBA (see "Revalidate Dentry and UDBA"). -+- the file should not be hard-linked nor pseudo-linked. they should be -+ handled by auplink utility later. -+ -+Sometimes users want to move-down a file from the upper writable branch -+to the lower readonly or writable branch. For instance, -+- the free space of the upper writable branch is going to run out. -+- create a new intermediate branch between the upper and lower branch. -+- etc. -+ -+For this purpose, use "aumvdown" command in aufs-util.git. -diff -Nurp linux-5.10-rc6/Documentation/filesystems/aufs/design/03atomic_open.txt linux-5.10-rc6.aufs/Documentation/filesystems/aufs/design/03atomic_open.txt ---- linux-5.10-rc6/Documentation/filesystems/aufs/design/03atomic_open.txt 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/Documentation/filesystems/aufs/design/03atomic_open.txt 2020-12-02 21:19:51.876036518 +0200 -@@ -0,0 +1,72 @@ -+ -+# Copyright (C) 2015-2020 Junjiro R. Okajima -+ -+Support for a branch who has its ->atomic_open() -+---------------------------------------------------------------------- -+The filesystems who implement its ->atomic_open() are not majority. For -+example NFSv4 does, and aufs should call NFSv4 ->atomic_open, -+particularly for open(O_CREAT|O_EXCL, 0400) case. Other than -+->atomic_open(), NFSv4 returns an error for this open(2). While I am not -+sure whether all filesystems who have ->atomic_open() behave like this, -+but NFSv4 surely returns the error. -+ -+In order to support ->atomic_open() for aufs, there are a few -+approaches. -+ -+A. Introduce aufs_atomic_open() -+ - calls one of VFS:do_last(), lookup_open() or atomic_open() for -+ branch fs. -+B. Introduce aufs_atomic_open() calling create, open and chmod. this is -+ an aufs user Pip Cet's approach -+ - calls aufs_create(), VFS finish_open() and notify_change(). -+ - pass fake-mode to finish_open(), and then correct the mode by -+ notify_change(). -+C. Extend aufs_open() to call branch fs's ->atomic_open() -+ - no aufs_atomic_open(). -+ - aufs_lookup() registers the TID to an aufs internal object. -+ - aufs_create() does nothing when the matching TID is registered, but -+ registers the mode. -+ - aufs_open() calls branch fs's ->atomic_open() when the matching -+ TID is registered. -+D. Extend aufs_open() to re-try branch fs's ->open() with superuser's -+ credential -+ - no aufs_atomic_open(). -+ - aufs_create() registers the TID to an internal object. this info -+ represents "this process created this file just now." -+ - when aufs gets EACCES from branch fs's ->open(), then confirm the -+ registered TID and re-try open() with superuser's credential. -+ -+Pros and cons for each approach. -+ -+A. -+ - straightforward but highly depends upon VFS internal. -+ - the atomic behavaiour is kept. -+ - some of parameters such as nameidata are hard to reproduce for -+ branch fs. -+ - large overhead. -+B. -+ - easy to implement. -+ - the atomic behavaiour is lost. -+C. -+ - the atomic behavaiour is kept. -+ - dirty and tricky. -+ - VFS checks whether the file is created correctly after calling -+ ->create(), which means this approach doesn't work. -+D. -+ - easy to implement. -+ - the atomic behavaiour is lost. -+ - to open a file with superuser's credential and give it to a user -+ process is a bad idea, since the file object keeps the credential -+ in it. It may affect LSM or something. This approach doesn't work -+ either. -+ -+The approach A is ideal, but it hard to implement. So here is a -+variation of A, which is to be implemented. -+ -+A-1. Introduce aufs_atomic_open() -+ - calls branch fs ->atomic_open() if exists. otherwise calls -+ vfs_create() and finish_open(). -+ - the demerit is that the several checks after branch fs -+ ->atomic_open() are lost. in the ordinary case, the checks are -+ done by VFS:do_last(), lookup_open() and atomic_open(). some can -+ be implemented in aufs, but not all I am afraid. -diff -Nurp linux-5.10-rc6/Documentation/filesystems/aufs/design/03lookup.txt linux-5.10-rc6.aufs/Documentation/filesystems/aufs/design/03lookup.txt ---- linux-5.10-rc6/Documentation/filesystems/aufs/design/03lookup.txt 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/Documentation/filesystems/aufs/design/03lookup.txt 2020-12-02 21:19:51.877036563 +0200 -@@ -0,0 +1,100 @@ -+ -+# Copyright (C) 2005-2020 Junjiro R. Okajima -+ -+Lookup in a Branch -+---------------------------------------------------------------------- -+Since aufs has a character of sub-VFS (see Introduction), it operates -+lookup for branches as VFS does. It may be a heavy work. But almost all -+lookup operation in aufs is the simplest case, ie. lookup only an entry -+directly connected to its parent. Digging down the directory hierarchy -+is unnecessary. VFS has a function lookup_one_len() for that use, and -+aufs calls it. -+ -+When a branch is a remote filesystem, aufs basically relies upon its -+->d_revalidate(), also aufs forces the hardest revalidate tests for -+them. -+For d_revalidate, aufs implements three levels of revalidate tests. See -+"Revalidate Dentry and UDBA" in detail. -+ -+ -+Test Only the Highest One for the Directory Permission (dirperm1 option) -+---------------------------------------------------------------------- -+Let's try case study. -+- aufs has two branches, upper readwrite and lower readonly. -+ /au = /rw + /ro -+- "dirA" exists under /ro, but /rw. and its mode is 0700. -+- user invoked "chmod a+rx /au/dirA" -+- the internal copy-up is activated and "/rw/dirA" is created and its -+ permission bits are set to world readable. -+- then "/au/dirA" becomes world readable? -+ -+In this case, /ro/dirA is still 0700 since it exists in readonly branch, -+or it may be a natively readonly filesystem. If aufs respects the lower -+branch, it should not respond readdir request from other users. But user -+allowed it by chmod. Should really aufs rejects showing the entries -+under /ro/dirA? -+ -+To be honest, I don't have a good solution for this case. So aufs -+implements 'dirperm1' and 'nodirperm1' mount options, and leave it to -+users. -+When dirperm1 is specified, aufs checks only the highest one for the -+directory permission, and shows the entries. Otherwise, as usual, checks -+every dir existing on all branches and rejects the request. -+ -+As a side effect, dirperm1 option improves the performance of aufs -+because the number of permission check is reduced when the number of -+branch is many. -+ -+ -+Revalidate Dentry and UDBA (User's Direct Branch Access) -+---------------------------------------------------------------------- -+Generally VFS helpers re-validate a dentry as a part of lookup. -+0. digging down the directory hierarchy. -+1. lock the parent dir by its i_mutex. -+2. lookup the final (child) entry. -+3. revalidate it. -+4. call the actual operation (create, unlink, etc.) -+5. unlock the parent dir -+ -+If the filesystem implements its ->d_revalidate() (step 3), then it is -+called. Actually aufs implements it and checks the dentry on a branch is -+still valid. -+But it is not enough. Because aufs has to release the lock for the -+parent dir on a branch at the end of ->lookup() (step 2) and -+->d_revalidate() (step 3) while the i_mutex of the aufs dir is still -+held by VFS. -+If the file on a branch is changed directly, eg. bypassing aufs, after -+aufs released the lock, then the subsequent operation may cause -+something unpleasant result. -+ -+This situation is a result of VFS architecture, ->lookup() and -+->d_revalidate() is separated. But I never say it is wrong. It is a good -+design from VFS's point of view. It is just not suitable for sub-VFS -+character in aufs. -+ -+Aufs supports such case by three level of revalidation which is -+selectable by user. -+1. Simple Revalidate -+ Addition to the native flow in VFS's, confirm the child-parent -+ relationship on the branch just after locking the parent dir on the -+ branch in the "actual operation" (step 4). When this validation -+ fails, aufs returns EBUSY. ->d_revalidate() (step 3) in aufs still -+ checks the validation of the dentry on branches. -+2. Monitor Changes Internally by Inotify/Fsnotify -+ Addition to above, in the "actual operation" (step 4) aufs re-lookup -+ the dentry on the branch, and returns EBUSY if it finds different -+ dentry. -+ Additionally, aufs sets the inotify/fsnotify watch for every dir on branches -+ during it is in cache. When the event is notified, aufs registers a -+ function to kernel 'events' thread by schedule_work(). And the -+ function sets some special status to the cached aufs dentry and inode -+ private data. If they are not cached, then aufs has nothing to -+ do. When the same file is accessed through aufs (step 0-3) later, -+ aufs will detect the status and refresh all necessary data. -+ In this mode, aufs has to ignore the event which is fired by aufs -+ itself. -+3. No Extra Validation -+ This is the simplest test and doesn't add any additional revalidation -+ test, and skip the revalidation in step 4. It is useful and improves -+ aufs performance when system surely hide the aufs branches from user, -+ by over-mounting something (or another method). -diff -Nurp linux-5.10-rc6/Documentation/filesystems/aufs/design/04branch.txt linux-5.10-rc6.aufs/Documentation/filesystems/aufs/design/04branch.txt ---- linux-5.10-rc6/Documentation/filesystems/aufs/design/04branch.txt 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/Documentation/filesystems/aufs/design/04branch.txt 2020-12-02 21:19:51.877036563 +0200 -@@ -0,0 +1,61 @@ -+ -+# Copyright (C) 2005-2020 Junjiro R. Okajima -+ -+Branch Manipulation -+ -+Since aufs supports dynamic branch manipulation, ie. add/remove a branch -+and changing its permission/attribute, there are a lot of works to do. -+ -+ -+Add a Branch -+---------------------------------------------------------------------- -+o Confirm the adding dir exists outside of aufs, including loopback -+ mount, and its various attributes. -+o Initialize the xino file and whiteout bases if necessary. -+ See struct.txt. -+ -+o Check the owner/group/mode of the directory -+ When the owner/group/mode of the adding directory differs from the -+ existing branch, aufs issues a warning because it may impose a -+ security risk. -+ For example, when a upper writable branch has a world writable empty -+ top directory, a malicious user can create any files on the writable -+ branch directly, like copy-up and modify manually. If something like -+ /etc/{passwd,shadow} exists on the lower readonly branch but the upper -+ writable branch, and the writable branch is world-writable, then a -+ malicious guy may create /etc/passwd on the writable branch directly -+ and the infected file will be valid in aufs. -+ I am afraid it can be a security issue, but aufs can do nothing except -+ producing a warning. -+ -+ -+Delete a Branch -+---------------------------------------------------------------------- -+o Confirm the deleting branch is not busy -+ To be general, there is one merit to adopt "remount" interface to -+ manipulate branches. It is to discard caches. At deleting a branch, -+ aufs checks the still cached (and connected) dentries and inodes. If -+ there are any, then they are all in-use. An inode without its -+ corresponding dentry can be alive alone (for example, inotify/fsnotify case). -+ -+ For the cached one, aufs checks whether the same named entry exists on -+ other branches. -+ If the cached one is a directory, because aufs provides a merged view -+ to users, as long as one dir is left on any branch aufs can show the -+ dir to users. In this case, the branch can be removed from aufs. -+ Otherwise aufs rejects deleting the branch. -+ -+ If any file on the deleting branch is opened by aufs, then aufs -+ rejects deleting. -+ -+ -+Modify the Permission of a Branch -+---------------------------------------------------------------------- -+o Re-initialize or remove the xino file and whiteout bases if necessary. -+ See struct.txt. -+ -+o rw --> ro: Confirm the modifying branch is not busy -+ Aufs rejects the request if any of these conditions are true. -+ - a file on the branch is mmap-ed. -+ - a regular file on the branch is opened for write and there is no -+ same named entry on the upper branch. -diff -Nurp linux-5.10-rc6/Documentation/filesystems/aufs/design/05wbr_policy.txt linux-5.10-rc6.aufs/Documentation/filesystems/aufs/design/05wbr_policy.txt ---- linux-5.10-rc6/Documentation/filesystems/aufs/design/05wbr_policy.txt 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/Documentation/filesystems/aufs/design/05wbr_policy.txt 2020-12-02 21:19:51.877036563 +0200 -@@ -0,0 +1,51 @@ -+ -+# Copyright (C) 2005-2020 Junjiro R. Okajima -+ -+Policies to Select One among Multiple Writable Branches -+---------------------------------------------------------------------- -+When the number of writable branch is more than one, aufs has to decide -+the target branch for file creation or copy-up. By default, the highest -+writable branch which has the parent (or ancestor) dir of the target -+file is chosen (top-down-parent policy). -+By user's request, aufs implements some other policies to select the -+writable branch, for file creation several policies, round-robin, -+most-free-space, and other policies. For copy-up, top-down-parent, -+bottom-up-parent, bottom-up and others. -+ -+As expected, the round-robin policy selects the branch in circular. When -+you have two writable branches and creates 10 new files, 5 files will be -+created for each branch. mkdir(2) systemcall is an exception. When you -+create 10 new directories, all will be created on the same branch. -+And the most-free-space policy selects the one which has most free -+space among the writable branches. The amount of free space will be -+checked by aufs internally, and users can specify its time interval. -+ -+The policies for copy-up is more simple, -+top-down-parent is equivalent to the same named on in create policy, -+bottom-up-parent selects the writable branch where the parent dir -+exists and the nearest upper one from the copyup-source, -+bottom-up selects the nearest upper writable branch from the -+copyup-source, regardless the existence of the parent dir. -+ -+There are some rules or exceptions to apply these policies. -+- If there is a readonly branch above the policy-selected branch and -+ the parent dir is marked as opaque (a variation of whiteout), or the -+ target (creating) file is whiteout-ed on the upper readonly branch, -+ then the result of the policy is ignored and the target file will be -+ created on the nearest upper writable branch than the readonly branch. -+- If there is a writable branch above the policy-selected branch and -+ the parent dir is marked as opaque or the target file is whiteouted -+ on the branch, then the result of the policy is ignored and the target -+ file will be created on the highest one among the upper writable -+ branches who has diropq or whiteout. In case of whiteout, aufs removes -+ it as usual. -+- link(2) and rename(2) systemcalls are exceptions in every policy. -+ They try selecting the branch where the source exists as possible -+ since copyup a large file will take long time. If it can't be, -+ ie. the branch where the source exists is readonly, then they will -+ follow the copyup policy. -+- There is an exception for rename(2) when the target exists. -+ If the rename target exists, aufs compares the index of the branches -+ where the source and the target exists and selects the higher -+ one. If the selected branch is readonly, then aufs follows the -+ copyup policy. -diff -Nurp linux-5.10-rc6/Documentation/filesystems/aufs/design/06dirren.dot linux-5.10-rc6.aufs/Documentation/filesystems/aufs/design/06dirren.dot ---- linux-5.10-rc6/Documentation/filesystems/aufs/design/06dirren.dot 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/Documentation/filesystems/aufs/design/06dirren.dot 2020-12-02 21:19:51.877036563 +0200 -@@ -0,0 +1,31 @@ -+ -+// to view this graph, run dot(1) command in GRAPHVIZ. -+ -+digraph G { -+node [shape=box]; -+whinfo [label="detailed info file\n(lower_brid_root-hinum, h_inum, namelen, old name)"]; -+ -+node [shape=oval]; -+ -+aufs_rename -> whinfo [label="store/remove"]; -+ -+node [shape=oval]; -+inode_list [label="h_inum list in branch\ncache"]; -+ -+node [shape=box]; -+whinode [label="h_inum list file"]; -+ -+node [shape=oval]; -+brmgmt [label="br_add/del/mod/umount"]; -+ -+brmgmt -> inode_list [label="create/remove"]; -+brmgmt -> whinode [label="load/store"]; -+ -+inode_list -> whinode [style=dashed,dir=both]; -+ -+aufs_rename -> inode_list [label="add/del"]; -+ -+aufs_lookup -> inode_list [label="search"]; -+ -+aufs_lookup -> whinfo [label="load/remove"]; -+} -diff -Nurp linux-5.10-rc6/Documentation/filesystems/aufs/design/06dirren.txt linux-5.10-rc6.aufs/Documentation/filesystems/aufs/design/06dirren.txt ---- linux-5.10-rc6/Documentation/filesystems/aufs/design/06dirren.txt 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/Documentation/filesystems/aufs/design/06dirren.txt 2020-12-02 21:19:51.877036563 +0200 -@@ -0,0 +1,89 @@ -+ -+# Copyright (C) 2017-2020 Junjiro R. Okajima -+ -+Special handling for renaming a directory (DIRREN) -+---------------------------------------------------------------------- -+First, let's assume we have a simple usecase. -+ -+- /u = /rw + /ro -+- /rw/dirA exists -+- /ro/dirA and /ro/dirA/file exist too -+- there is no dirB on both branches -+- a user issues rename("dirA", "dirB") -+ -+Now, what should aufs behave against this rename(2)? -+There are a few possible cases. -+ -+A. returns EROFS. -+ since dirA exists on a readonly branch which cannot be renamed. -+B. returns EXDEV. -+ it is possible to copy-up dirA (only the dir itself), but the child -+ entries ("file" in this case) should not be. it must be a bad -+ approach to copy-up recursively. -+C. returns a success. -+ even the branch /ro is readonly, aufs tries renaming it. Obviously it -+ is a violation of aufs' policy. -+D. construct an extra information which indicates that /ro/dirA should -+ be handled as the name of dirB. -+ overlayfs has a similar feature called REDIRECT. -+ -+Until now, aufs implements the case B only which returns EXDEV, and -+expects the userspace application behaves like mv(1) which tries -+issueing rename(2) recursively. -+ -+A new aufs feature called DIRREN is introduced which implements the case -+D. There are several "extra information" added. -+ -+1. detailed info per renamed directory -+ path: /rw/dirB/$AUFS_WH_DR_INFO_PFX. -+2. the inode-number list of directories on a branch -+ path: /rw/dirB/$AUFS_WH_DR_BRHINO -+ -+The filename of "detailed info per directory" represents the lower -+branch, and its format is -+- a type of the branch id -+ one of these. -+ + uuid (not implemented yet) -+ + fsid -+ + dev -+- the inode-number of the branch root dir -+ -+And it contains these info in a single regular file. -+- magic number -+- branch's inode-number of the logically renamed dir -+- the name of the before-renamed dir -+ -+The "detailed info per directory" file is created in aufs rename(2), and -+loaded in any lookup. -+The info is considered in lookup for the matching case only. Here -+"matching" means that the root of branch (in the info filename) is same -+to the current looking-up branch. After looking-up the before-renamed -+name, the inode-number is compared. And the matched dentry is used. -+ -+The "inode-number list of directories" is a regular file which contains -+simply the inode-numbers on the branch. The file is created or updated -+in removing the branch, and loaded in adding the branch. Its lifetime is -+equal to the branch. -+The list is refered in lookup, and when the current target inode is -+found in the list, the aufs tries loading the "detailed info per -+directory" and get the changed and valid name of the dir. -+ -+Theoretically these "extra informaiton" may be able to be put into XATTR -+in the dir inode. But aufs doesn't choose this way because -+1. XATTR may not be supported by the branch (or its configuration) -+2. XATTR may have its size limit. -+3. XATTR may be less easy to convert than a regular file, when the -+ format of the info is changed in the future. -+At the same time, I agree that the regular file approach is much slower -+than XATTR approach. So, in the future, aufs may take the XATTR or other -+better approach. -+ -+This DIRREN feature is enabled by aufs configuration, and is activated -+by a new mount option. -+ -+For the more complicated case, there is a work with UDBA option, which -+is to dected the direct access to the branches (by-passing aufs) and to -+maintain the cashes in aufs. Since a single cached aufs dentry may -+contains two names, before- and after-rename, the name comparision in -+UDBA handler may not work correctly. In this case, the behaviour will be -+equivalen to udba=reval case. -diff -Nurp linux-5.10-rc6/Documentation/filesystems/aufs/design/06fhsm.txt linux-5.10-rc6.aufs/Documentation/filesystems/aufs/design/06fhsm.txt ---- linux-5.10-rc6/Documentation/filesystems/aufs/design/06fhsm.txt 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/Documentation/filesystems/aufs/design/06fhsm.txt 2020-12-02 21:19:51.877036563 +0200 -@@ -0,0 +1,105 @@ -+ -+# Copyright (C) 2011-2020 Junjiro R. Okajima -+ -+File-based Hierarchical Storage Management (FHSM) -+---------------------------------------------------------------------- -+Hierarchical Storage Management (or HSM) is a well-known feature in the -+storage world. Aufs provides this feature as file-based with multiple -+writable branches, based upon the principle of "Colder, the Lower". -+Here the word "colder" means that the less used files, and "lower" means -+that the position in the order of the stacked branches vertically. -+These multiple writable branches are prioritized, ie. the topmost one -+should be the fastest drive and be used heavily. -+ -+o Characters in aufs FHSM story -+- aufs itself and a new branch attribute. -+- a new ioctl interface to move-down and to establish a connection with -+ the daemon ("move-down" is a converse of "copy-up"). -+- userspace tool and daemon. -+ -+The userspace daemon establishes a connection with aufs and waits for -+the notification. The notified information is very similar to struct -+statfs containing the number of consumed blocks and inodes. -+When the consumed blocks/inodes of a branch exceeds the user-specified -+upper watermark, the daemon activates its move-down process until the -+consumed blocks/inodes reaches the user-specified lower watermark. -+ -+The actual move-down is done by aufs based upon the request from -+user-space since we need to maintain the inode number and the internal -+pointer arrays in aufs. -+ -+Currently aufs FHSM handles the regular files only. Additionally they -+must not be hard-linked nor pseudo-linked. -+ -+ -+o Cowork of aufs and the user-space daemon -+ During the userspace daemon established the connection, aufs sends a -+ small notification to it whenever aufs writes something into the -+ writable branch. But it may cost high since aufs issues statfs(2) -+ internally. So user can specify a new option to cache the -+ info. Actually the notification is controlled by these factors. -+ + the specified cache time. -+ + classified as "force" by aufs internally. -+ Until the specified time expires, aufs doesn't send the info -+ except the forced cases. When aufs decide forcing, the info is always -+ notified to userspace. -+ For example, the number of free inodes is generally large enough and -+ the shortage of it happens rarely. So aufs doesn't force the -+ notification when creating a new file, directory and others. This is -+ the typical case which aufs doesn't force. -+ When aufs writes the actual filedata and the files consumes any of new -+ blocks, the aufs forces notifying. -+ -+ -+o Interfaces in aufs -+- New branch attribute. -+ + fhsm -+ Specifies that the branch is managed by FHSM feature. In other word, -+ participant in the FHSM. -+ When nofhsm is set to the branch, it will not be the source/target -+ branch of the move-down operation. This attribute is set -+ independently from coo and moo attributes, and if you want full -+ FHSM, you should specify them as well. -+- New mount option. -+ + fhsm_sec -+ Specifies a second to suppress many less important info to be -+ notified. -+- New ioctl. -+ + AUFS_CTL_FHSM_FD -+ create a new file descriptor which userspace can read the notification -+ (a subset of struct statfs) from aufs. -+- Module parameter 'brs' -+ It has to be set to 1. Otherwise the new mount option 'fhsm' will not -+ be set. -+- mount helpers /sbin/mount.aufs and /sbin/umount.aufs -+ When there are two or more branches with fhsm attributes, -+ /sbin/mount.aufs invokes the user-space daemon and /sbin/umount.aufs -+ terminates it. As a result of remounting and branch-manipulation, the -+ number of branches with fhsm attribute can be one. In this case, -+ /sbin/mount.aufs will terminate the user-space daemon. -+ -+ -+Finally the operation is done as these steps in kernel-space. -+- make sure that, -+ + no one else is using the file. -+ + the file is not hard-linked. -+ + the file is not pseudo-linked. -+ + the file is a regular file. -+ + the parent dir is not opaqued. -+- find the target writable branch. -+- make sure the file is not whiteout-ed by the upper (than the target) -+ branch. -+- make the parent dir on the target branch. -+- mutex lock the inode on the branch. -+- unlink the whiteout on the target branch (if exists). -+- lookup and create the whiteout-ed temporary name on the target branch. -+- copy the file as the whiteout-ed temporary name on the target branch. -+- rename the whiteout-ed temporary name to the original name. -+- unlink the file on the source branch. -+- maintain the internal pointer array and the external inode number -+ table (XINO). -+- maintain the timestamps and other attributes of the parent dir and the -+ file. -+ -+And of course, in every step, an error may happen. So the operation -+should restore the original file state after an error happens. -diff -Nurp linux-5.10-rc6/Documentation/filesystems/aufs/design/06mmap.txt linux-5.10-rc6.aufs/Documentation/filesystems/aufs/design/06mmap.txt ---- linux-5.10-rc6/Documentation/filesystems/aufs/design/06mmap.txt 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/Documentation/filesystems/aufs/design/06mmap.txt 2020-12-02 21:19:51.877036563 +0200 -@@ -0,0 +1,59 @@ -+ -+# Copyright (C) 2005-2020 Junjiro R. Okajima -+ -+mmap(2) -- File Memory Mapping -+---------------------------------------------------------------------- -+In aufs, the file-mapped pages are handled by a branch fs directly, no -+interaction with aufs. It means aufs_mmap() calls the branch fs's -+->mmap(). -+This approach is simple and good, but there is one problem. -+Under /proc, several entries show the mmapped files by its path (with -+device and inode number), and the printed path will be the path on the -+branch fs's instead of virtual aufs's. -+This is not a problem in most cases, but some utilities lsof(1) (and its -+user) may expect the path on aufs. -+ -+To address this issue, aufs adds a new member called vm_prfile in struct -+vm_area_struct (and struct vm_region). The original vm_file points to -+the file on the branch fs in order to handle everything correctly as -+usual. The new vm_prfile points to a virtual file in aufs, and the -+show-functions in procfs refers to vm_prfile if it is set. -+Also we need to maintain several other places where touching vm_file -+such like -+- fork()/clone() copies vma and the reference count of vm_file is -+ incremented. -+- merging vma maintains the ref count too. -+ -+This is not a good approach. It just fakes the printed path. But it -+leaves all behaviour around f_mapping unchanged. This is surely an -+advantage. -+Actually aufs had adopted another complicated approach which calls -+generic_file_mmap() and handles struct vm_operations_struct. In this -+approach, aufs met a hard problem and I could not solve it without -+switching the approach. -+ -+There may be one more another approach which is -+- bind-mount the branch-root onto the aufs-root internally -+- grab the new vfsmount (ie. struct mount) -+- lazy-umount the branch-root internally -+- in open(2) the aufs-file, open the branch-file with the hidden -+ vfsmount (instead of the original branch's vfsmount) -+- ideally this "bind-mount and lazy-umount" should be done atomically, -+ but it may be possible from userspace by the mount helper. -+ -+Adding the internal hidden vfsmount and using it in opening a file, the -+file path under /proc will be printed correctly. This approach looks -+smarter, but is not possible I am afraid. -+- aufs-root may be bind-mount later. when it happens, another hidden -+ vfsmount will be required. -+- it is hard to get the chance to bind-mount and lazy-umount -+ + in kernel-space, FS can have vfsmount in open(2) via -+ file->f_path, and aufs can know its vfsmount. But several locks are -+ already acquired, and if aufs tries to bind-mount and lazy-umount -+ here, then it may cause a deadlock. -+ + in user-space, bind-mount doesn't invoke the mount helper. -+- since /proc shows dev and ino, aufs has to give vma these info. it -+ means a new member vm_prinode will be necessary. this is essentially -+ equivalent to vm_prfile described above. -+ -+I have to give up this "looks-smater" approach. -diff -Nurp linux-5.10-rc6/Documentation/filesystems/aufs/design/06xattr.txt linux-5.10-rc6.aufs/Documentation/filesystems/aufs/design/06xattr.txt ---- linux-5.10-rc6/Documentation/filesystems/aufs/design/06xattr.txt 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/Documentation/filesystems/aufs/design/06xattr.txt 2020-12-02 21:19:51.877036563 +0200 -@@ -0,0 +1,81 @@ -+ -+# Copyright (C) 2014-2020 Junjiro R. Okajima -+ -+Listing XATTR/EA and getting the value -+---------------------------------------------------------------------- -+For the inode standard attributes (owner, group, timestamps, etc.), aufs -+shows the values from the topmost existing file. This behaviour is good -+for the non-dir entries since the bahaviour exactly matches the shown -+information. But for the directories, aufs considers all the same named -+entries on the lower branches. Which means, if one of the lower entry -+rejects readdir call, then aufs returns an error even if the topmost -+entry allows it. This behaviour is necessary to respect the branch fs's -+security, but can make users confused since the user-visible standard -+attributes don't match the behaviour. -+To address this issue, aufs has a mount option called dirperm1 which -+checks the permission for the topmost entry only, and ignores the lower -+entry's permission. -+ -+A similar issue can happen around XATTR. -+getxattr(2) and listxattr(2) families behave as if dirperm1 option is -+always set. Otherwise these very unpleasant situation would happen. -+- listxattr(2) may return the duplicated entries. -+- users may not be able to remove or reset the XATTR forever, -+ -+ -+XATTR/EA support in the internal (copy,move)-(up,down) -+---------------------------------------------------------------------- -+Generally the extended attributes of inode are categorized as these. -+- "security" for LSM and capability. -+- "system" for posix ACL, 'acl' mount option is required for the branch -+ fs generally. -+- "trusted" for userspace, CAP_SYS_ADMIN is required. -+- "user" for userspace, 'user_xattr' mount option is required for the -+ branch fs generally. -+ -+Moreover there are some other categories. Aufs handles these rather -+unpopular categories as the ordinary ones, ie. there is no special -+condition nor exception. -+ -+In copy-up, the support for XATTR on the dst branch may differ from the -+src branch. In this case, the copy-up operation will get an error and -+the original user operation which triggered the copy-up will fail. It -+can happen that even all copy-up will fail. -+When both of src and dst branches support XATTR and if an error occurs -+during copying XATTR, then the copy-up should fail obviously. That is a -+good reason and aufs should return an error to userspace. But when only -+the src branch support that XATTR, aufs should not return an error. -+For example, the src branch supports ACL but the dst branch doesn't -+because the dst branch may natively un-support it or temporary -+un-support it due to "noacl" mount option. Of course, the dst branch fs -+may NOT return an error even if the XATTR is not supported. It is -+totally up to the branch fs. -+ -+Anyway when the aufs internal copy-up gets an error from the dst branch -+fs, then aufs tries removing the just copied entry and returns the error -+to the userspace. The worst case of this situation will be all copy-up -+will fail. -+ -+For the copy-up operation, there two basic approaches. -+- copy the specified XATTR only (by category above), and return the -+ error unconditionally if it happens. -+- copy all XATTR, and ignore the error on the specified category only. -+ -+In order to support XATTR and to implement the correct behaviour, aufs -+chooses the latter approach and introduces some new branch attributes, -+"icexsec", "icexsys", "icextr", "icexusr", and "icexoth". -+They correspond to the XATTR namespaces (see above). Additionally, to be -+convenient, "icex" is also provided which means all "icex*" attributes -+are set (here the word "icex" stands for "ignore copy-error on XATTR"). -+ -+The meaning of these attributes is to ignore the error from setting -+XATTR on that branch. -+Note that aufs tries copying all XATTR unconditionally, and ignores the -+error from the dst branch according to the specified attributes. -+ -+Some XATTR may have its default value. The default value may come from -+the parent dir or the environment. If the default value is set at the -+file creating-time, it will be overwritten by copy-up. -+Some contradiction may happen I am afraid. -+Do we need another attribute to stop copying XATTR? I am unsure. For -+now, aufs implements the branch attributes to ignore the error. -diff -Nurp linux-5.10-rc6/Documentation/filesystems/aufs/design/07export.txt linux-5.10-rc6.aufs/Documentation/filesystems/aufs/design/07export.txt ---- linux-5.10-rc6/Documentation/filesystems/aufs/design/07export.txt 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/Documentation/filesystems/aufs/design/07export.txt 2020-12-02 21:19:51.877036563 +0200 -@@ -0,0 +1,45 @@ -+ -+# Copyright (C) 2005-2020 Junjiro R. Okajima -+ -+Export Aufs via NFS -+---------------------------------------------------------------------- -+Here is an approach. -+- like xino/xib, add a new file 'xigen' which stores aufs inode -+ generation. -+- iget_locked(): initialize aufs inode generation for a new inode, and -+ store it in xigen file. -+- destroy_inode(): increment aufs inode generation and store it in xigen -+ file. it is necessary even if it is not unlinked, because any data of -+ inode may be changed by UDBA. -+- encode_fh(): for a root dir, simply return FILEID_ROOT. otherwise -+ build file handle by -+ + branch id (4 bytes) -+ + superblock generation (4 bytes) -+ + inode number (4 or 8 bytes) -+ + parent dir inode number (4 or 8 bytes) -+ + inode generation (4 bytes)) -+ + return value of exportfs_encode_fh() for the parent on a branch (4 -+ bytes) -+ + file handle for a branch (by exportfs_encode_fh()) -+- fh_to_dentry(): -+ + find the index of a branch from its id in handle, and check it is -+ still exist in aufs. -+ + 1st level: get the inode number from handle and search it in cache. -+ + 2nd level: if not found in cache, get the parent inode number from -+ the handle and search it in cache. and then open the found parent -+ dir, find the matching inode number by vfs_readdir() and get its -+ name, and call lookup_one_len() for the target dentry. -+ + 3rd level: if the parent dir is not cached, call -+ exportfs_decode_fh() for a branch and get the parent on a branch, -+ build a pathname of it, convert it a pathname in aufs, call -+ path_lookup(). now aufs gets a parent dir dentry, then handle it as -+ the 2nd level. -+ + to open the dir, aufs needs struct vfsmount. aufs keeps vfsmount -+ for every branch, but not itself. to get this, (currently) aufs -+ searches in current->nsproxy->mnt_ns list. it may not be a good -+ idea, but I didn't get other approach. -+ + test the generation of the gotten inode. -+- every inode operation: they may get EBUSY due to UDBA. in this case, -+ convert it into ESTALE for NFSD. -+- readdir(): call lockdep_on/off() because filldir in NFSD calls -+ lookup_one_len(), vfs_getattr(), encode_fh() and others. -diff -Nurp linux-5.10-rc6/Documentation/filesystems/aufs/design/08shwh.txt linux-5.10-rc6.aufs/Documentation/filesystems/aufs/design/08shwh.txt ---- linux-5.10-rc6/Documentation/filesystems/aufs/design/08shwh.txt 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/Documentation/filesystems/aufs/design/08shwh.txt 2020-12-02 21:19:51.877036563 +0200 -@@ -0,0 +1,39 @@ -+ -+# Copyright (C) 2005-2020 Junjiro R. Okajima -+ -+Show Whiteout Mode (shwh) -+---------------------------------------------------------------------- -+Generally aufs hides the name of whiteouts. But in some cases, to show -+them is very useful for users. For instance, creating a new middle layer -+(branch) by merging existing layers. -+ -+(borrowing aufs1 HOW-TO from a user, Michael Towers) -+When you have three branches, -+- Bottom: 'system', squashfs (underlying base system), read-only -+- Middle: 'mods', squashfs, read-only -+- Top: 'overlay', ram (tmpfs), read-write -+ -+The top layer is loaded at boot time and saved at shutdown, to preserve -+the changes made to the system during the session. -+When larger changes have been made, or smaller changes have accumulated, -+the size of the saved top layer data grows. At this point, it would be -+nice to be able to merge the two overlay branches ('mods' and 'overlay') -+and rewrite the 'mods' squashfs, clearing the top layer and thus -+restoring save and load speed. -+ -+This merging is simplified by the use of another aufs mount, of just the -+two overlay branches using the 'shwh' option. -+# mount -t aufs -o ro,shwh,br:/livesys/overlay=ro+wh:/livesys/mods=rr+wh \ -+ aufs /livesys/merge_union -+ -+A merged view of these two branches is then available at -+/livesys/merge_union, and the new feature is that the whiteouts are -+visible! -+Note that in 'shwh' mode the aufs mount must be 'ro', which will disable -+writing to all branches. Also the default mode for all branches is 'ro'. -+It is now possible to save the combined contents of the two overlay -+branches to a new squashfs, e.g.: -+# mksquashfs /livesys/merge_union /path/to/newmods.squash -+ -+This new squashfs archive can be stored on the boot device and the -+initramfs will use it to replace the old one at the next boot. -diff -Nurp linux-5.10-rc6/Documentation/filesystems/aufs/design/10dynop.txt linux-5.10-rc6.aufs/Documentation/filesystems/aufs/design/10dynop.txt ---- linux-5.10-rc6/Documentation/filesystems/aufs/design/10dynop.txt 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/Documentation/filesystems/aufs/design/10dynop.txt 2020-12-02 21:19:51.877036563 +0200 -@@ -0,0 +1,34 @@ -+ -+# Copyright (C) 2010-2020 Junjiro R. Okajima -+ -+Dynamically customizable FS operations -+---------------------------------------------------------------------- -+Generally FS operations (struct inode_operations, struct -+address_space_operations, struct file_operations, etc.) are defined as -+"static const", but it never means that FS have only one set of -+operation. Some FS have multiple sets of them. For instance, ext2 has -+three sets, one for XIP, for NOBH, and for normal. -+Since aufs overrides and redirects these operations, sometimes aufs has -+to change its behaviour according to the branch FS type. More importantly -+VFS acts differently if a function (member in the struct) is set or -+not. It means aufs should have several sets of operations and select one -+among them according to the branch FS definition. -+ -+In order to solve this problem and not to affect the behaviour of VFS, -+aufs defines these operations dynamically. For instance, aufs defines -+dummy direct_IO function for struct address_space_operations, but it may -+not be set to the address_space_operations actually. When the branch FS -+doesn't have it, aufs doesn't set it to its address_space_operations -+while the function definition itself is still alive. So the behaviour -+itself will not change, and it will return an error when direct_IO is -+not set. -+ -+The lifetime of these dynamically generated operation object is -+maintained by aufs branch object. When the branch is removed from aufs, -+the reference counter of the object is decremented. When it reaches -+zero, the dynamically generated operation object will be freed. -+ -+This approach is designed to support AIO (io_submit), Direct I/O and -+XIP (DAX) mainly. -+Currently this approach is applied to address_space_operations for -+regular files only. -diff -Nurp linux-5.10-rc6/Documentation/filesystems/aufs/README linux-5.10-rc6.aufs/Documentation/filesystems/aufs/README ---- linux-5.10-rc6/Documentation/filesystems/aufs/README 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/Documentation/filesystems/aufs/README 2020-12-02 21:19:51.876036518 +0200 -@@ -0,0 +1,401 @@ -+ -+Aufs5 -- advanced multi layered unification filesystem version 5.x -+http://aufs.sf.net -+Junjiro R. Okajima -+ -+ -+0. Introduction -+---------------------------------------- -+In the early days, aufs was entirely re-designed and re-implemented -+Unionfs Version 1.x series. Adding many original ideas, approaches, -+improvements and implementations, it became totally different from -+Unionfs while keeping the basic features. -+Later, Unionfs Version 2.x series began taking some of the same -+approaches to aufs1's. -+Unionfs was being developed by Professor Erez Zadok at Stony Brook -+University and his team. -+ -+Aufs5 supports linux-v5.0 and later, If you want older kernel version -+support, -+- for linux-v4.x series, try aufs4-linux.git or aufs4-standalone.git -+- for linux-v3.x series, try aufs3-linux.git or aufs3-standalone.git -+- for linux-v2.6.16 and later, try aufs2-2.6.git, aufs2-standalone.git -+ or aufs1 from CVS on SourceForge. -+ -+Note: it becomes clear that "Aufs was rejected. Let's give it up." -+ According to Christoph Hellwig, linux rejects all union-type -+ filesystems but UnionMount. -+ -+ -+PS. Al Viro seems have a plan to merge aufs as well as overlayfs and -+ UnionMount, and he pointed out an issue around a directory mutex -+ lock and aufs addressed it. But it is still unsure whether aufs will -+ be merged (or any other union solution). -+ -+ -+ -+1. Features -+---------------------------------------- -+- unite several directories into a single virtual filesystem. The member -+ directory is called as a branch. -+- you can specify the permission flags to the branch, which are 'readonly', -+ 'readwrite' and 'whiteout-able.' -+- by upper writable branch, internal copyup and whiteout, files/dirs on -+ readonly branch are modifiable logically. -+- dynamic branch manipulation, add, del. -+- etc... -+ -+Also there are many enhancements in aufs, such as: -+- test only the highest one for the directory permission (dirperm1) -+- copyup on open (coo=) -+- 'move' policy for copy-up between two writable branches, after -+ checking free space. -+- xattr, acl -+- readdir(3) in userspace. -+- keep inode number by external inode number table -+- keep the timestamps of file/dir in internal copyup operation -+- seekable directory, supporting NFS readdir. -+- whiteout is hardlinked in order to reduce the consumption of inodes -+ on branch -+- do not copyup, nor create a whiteout when it is unnecessary -+- revert a single systemcall when an error occurs in aufs -+- remount interface instead of ioctl -+- maintain /etc/mtab by an external command, /sbin/mount.aufs. -+- loopback mounted filesystem as a branch -+- kernel thread for removing the dir who has a plenty of whiteouts -+- support copyup sparse file (a file which has a 'hole' in it) -+- default permission flags for branches -+- selectable permission flags for ro branch, whether whiteout can -+ exist or not -+- export via NFS. -+- support /fs/aufs and /aufs. -+- support multiple writable branches, some policies to select one -+ among multiple writable branches. -+- a new semantics for link(2) and rename(2) to support multiple -+ writable branches. -+- no glibc changes are required. -+- pseudo hardlink (hardlink over branches) -+- allow a direct access manually to a file on branch, e.g. bypassing aufs. -+ including NFS or remote filesystem branch. -+- userspace wrapper for pathconf(3)/fpathconf(3) with _PC_LINK_MAX. -+- and more... -+ -+Currently these features are dropped temporary from aufs5. -+See design/08plan.txt in detail. -+- nested mount, i.e. aufs as readonly no-whiteout branch of another aufs -+ (robr) -+- statistics of aufs thread (/sys/fs/aufs/stat) -+ -+Features or just an idea in the future (see also design/*.txt), -+- reorder the branch index without del/re-add. -+- permanent xino files for NFSD -+- an option for refreshing the opened files after add/del branches -+- light version, without branch manipulation. (unnecessary?) -+- copyup in userspace -+- inotify in userspace -+- readv/writev -+ -+ -+2. Download -+---------------------------------------- -+There are three GIT trees for aufs5, aufs5-linux.git, -+aufs5-standalone.git, and aufs-util.git. Note that there is no "5" in -+"aufs-util.git." -+While the aufs-util is always necessary, you need either of aufs5-linux -+or aufs5-standalone. -+ -+The aufs5-linux tree includes the whole linux mainline GIT tree, -+git://git.kernel.org/.../torvalds/linux.git. -+And you cannot select CONFIG_AUFS_FS=m for this version, eg. you cannot -+build aufs5 as an external kernel module. -+Several extra patches are not included in this tree. Only -+aufs5-standalone tree contains them. They are described in the later -+section "Configuration and Compilation." -+ -+On the other hand, the aufs5-standalone tree has only aufs source files -+and necessary patches, and you can select CONFIG_AUFS_FS=m. -+But you need to apply all aufs patches manually. -+ -+You will find GIT branches whose name is in form of "aufs5.x" where "x" -+represents the linux kernel version, "linux-5.x". For instance, -+"aufs5.0" is for linux-5.0. For latest "linux-5.x-rcN", use -+"aufs5.x-rcN" branch. -+ -+o aufs5-linux tree -+$ git clone --reference /your/linux/git/tree \ -+ git://github.com/sfjro/aufs5-linux.git aufs5-linux.git -+- if you don't have linux GIT tree, then remove "--reference ..." -+$ cd aufs5-linux.git -+$ git checkout origin/aufs5.0 -+ -+Or You may want to directly git-pull aufs into your linux GIT tree, and -+leave the patch-work to GIT. -+$ cd /your/linux/git/tree -+$ git remote add aufs5 git://github.com/sfjro/aufs5-linux.git -+$ git fetch aufs5 -+$ git checkout -b my5.0 v5.0 -+$ (add your local change...) -+$ git pull aufs5 aufs5.0 -+- now you have v5.0 + your_changes + aufs5.0 in you my5.0 branch. -+- you may need to solve some conflicts between your_changes and -+ aufs5.0. in this case, git-rerere is recommended so that you can -+ solve the similar conflicts automatically when you upgrade to 5.1 or -+ later in the future. -+ -+o aufs5-standalone tree -+$ git clone git://github.com/sfjro/aufs5-standalone.git aufs5-standalone.git -+$ cd aufs5-standalone.git -+$ git checkout origin/aufs5.0 -+ -+o aufs-util tree -+$ git clone git://git.code.sf.net/p/aufs/aufs-util aufs-util.git -+- note that the public aufs-util.git is on SourceForge instead of -+ GitHUB. -+$ cd aufs-util.git -+$ git checkout origin/aufs5.0 -+ -+Note: The 5.x-rcN branch is to be used with `rc' kernel versions ONLY. -+The minor version number, 'x' in '5.x', of aufs may not always -+follow the minor version number of the kernel. -+Because changes in the kernel that cause the use of a new -+minor version number do not always require changes to aufs-util. -+ -+Since aufs-util has its own minor version number, you may not be -+able to find a GIT branch in aufs-util for your kernel's -+exact minor version number. -+In this case, you should git-checkout the branch for the -+nearest lower number. -+ -+For (an unreleased) example: -+If you are using "linux-5.10" and the "aufs5.10" branch -+does not exist in aufs-util repository, then "aufs5.9", "aufs5.8" -+or something numerically smaller is the branch for your kernel. -+ -+Also you can view all branches by -+ $ git branch -a -+ -+ -+3. Configuration and Compilation -+---------------------------------------- -+Make sure you have git-checkout'ed the correct branch. -+ -+For aufs5-linux tree, -+- enable CONFIG_AUFS_FS. -+- set other aufs configurations if necessary. -+ -+For aufs5-standalone tree, -+There are several ways to build. -+ -+1. -+- apply ./aufs5-kbuild.patch to your kernel source files. -+- apply ./aufs5-base.patch too. -+- apply ./aufs5-mmap.patch too. -+- apply ./aufs5-standalone.patch too, if you have a plan to set -+ CONFIG_AUFS_FS=m. otherwise you don't need ./aufs5-standalone.patch. -+- copy ./{Documentation,fs,include/uapi/linux/aufs_type.h} files to your -+ kernel source tree. Never copy $PWD/include/uapi/linux/Kbuild. -+- enable CONFIG_AUFS_FS, you can select either -+ =m or =y. -+- and build your kernel as usual. -+- install the built kernel. -+- install the header files too by "make headers_install" to the -+ directory where you specify. By default, it is $PWD/usr. -+ "make help" shows a brief note for headers_install. -+- and reboot your system. -+ -+2. -+- module only (CONFIG_AUFS_FS=m). -+- apply ./aufs5-base.patch to your kernel source files. -+- apply ./aufs5-mmap.patch too. -+- apply ./aufs5-standalone.patch too. -+- build your kernel, don't forget "make headers_install", and reboot. -+- edit ./config.mk and set other aufs configurations if necessary. -+ Note: You should read $PWD/fs/aufs/Kconfig carefully which describes -+ every aufs configurations. -+- build the module by simple "make". -+- you can specify ${KDIR} make variable which points to your kernel -+ source tree. -+- install the files -+ + run "make install" to install the aufs module, or copy the built -+ $PWD/aufs.ko to /lib/modules/... and run depmod -a (or reboot simply). -+ + run "make install_headers" (instead of headers_install) to install -+ the modified aufs header file (you can specify DESTDIR which is -+ available in aufs standalone version's Makefile only), or copy -+ $PWD/usr/include/linux/aufs_type.h to /usr/include/linux or wherever -+ you like manually. By default, the target directory is $PWD/usr. -+- no need to apply aufs5-kbuild.patch, nor copying source files to your -+ kernel source tree. -+ -+Note: The header file aufs_type.h is necessary to build aufs-util -+ as well as "make headers_install" in the kernel source tree. -+ headers_install is subject to be forgotten, but it is essentially -+ necessary, not only for building aufs-util. -+ You may not meet problems without headers_install in some older -+ version though. -+ -+And then, -+- read README in aufs-util, build and install it -+- note that your distribution may contain an obsoleted version of -+ aufs_type.h in /usr/include/linux or something. When you build aufs -+ utilities, make sure that your compiler refers the correct aufs header -+ file which is built by "make headers_install." -+- if you want to use readdir(3) in userspace or pathconf(3) wrapper, -+ then run "make install_ulib" too. And refer to the aufs manual in -+ detail. -+ -+There several other patches in aufs5-standalone.git. They are all -+optional. When you meet some problems, they will help you. -+- aufs5-loopback.patch -+ Supports a nested loopback mount in a branch-fs. This patch is -+ unnecessary until aufs produces a message like "you may want to try -+ another patch for loopback file". -+- proc_mounts.patch -+ When there are many mountpoints and many mount(2)/umount(2) are -+ running, then /proc/mounts may not show the all mountpoints. This -+ patch makes /proc/mounts always show the full mountpoints list. -+ If you don't want to apply this patch and meet such problem, then you -+ need to increase the value of 'ProcMounts_Times' make-variable in -+ aufs-util.git as a second best solution. -+- vfs-ino.patch -+ Modifies a system global kernel internal function get_next_ino() in -+ order to stop assigning 0 for an inode-number. Not directly related to -+ aufs, but recommended generally. -+- tmpfs-idr.patch -+ Keeps the tmpfs inode number as the lowest value. Effective to reduce -+ the size of aufs XINO files for tmpfs branch. Also it prevents the -+ duplication of inode number, which is important for backup tools and -+ other utilities. When you find aufs XINO files for tmpfs branch -+ growing too much, try this patch. -+- lockdep-debug.patch -+ Because aufs is not only an ordinary filesystem (callee of VFS), but -+ also a caller of VFS functions for branch filesystems, subclassing of -+ the internal locks for LOCKDEP is necessary. LOCKDEP is a debugging -+ feature of linux kernel. If you enable CONFIG_LOCKDEP, then you will -+ need to apply this debug patch to expand several constant values. -+ If you don't know what LOCKDEP is, then you don't have apply this -+ patch. -+ -+ -+4. Usage -+---------------------------------------- -+At first, make sure aufs-util are installed, and please read the aufs -+manual, aufs.5 in aufs-util.git tree. -+$ man -l aufs.5 -+ -+And then, -+$ mkdir /tmp/rw /tmp/aufs -+# mount -t aufs -o br=/tmp/rw:${HOME} none /tmp/aufs -+ -+Here is another example. The result is equivalent. -+# mount -t aufs -o br=/tmp/rw=rw:${HOME}=ro none /tmp/aufs -+ Or -+# mount -t aufs -o br:/tmp/rw none /tmp/aufs -+# mount -o remount,append:${HOME} /tmp/aufs -+ -+Then, you can see whole tree of your home dir through /tmp/aufs. If -+you modify a file under /tmp/aufs, the one on your home directory is -+not affected, instead the same named file will be newly created under -+/tmp/rw. And all of your modification to a file will be applied to -+the one under /tmp/rw. This is called the file based Copy on Write -+(COW) method. -+Aufs mount options are described in aufs.5. -+If you run chroot or something and make your aufs as a root directory, -+then you need to customize the shutdown script. See the aufs manual in -+detail. -+ -+Additionally, there are some sample usages of aufs which are a -+diskless system with network booting, and LiveCD over NFS. -+See sample dir in CVS tree on SourceForge. -+ -+ -+5. Contact -+---------------------------------------- -+When you have any problems or strange behaviour in aufs, please let me -+know with: -+- /proc/mounts (instead of the output of mount(8)) -+- /sys/module/aufs/* -+- /sys/fs/aufs/* (if you have them) -+- /debug/aufs/* (if you have them) -+- linux kernel version -+ if your kernel is not plain, for example modified by distributor, -+ the url where i can download its source is necessary too. -+- aufs version which was printed at loading the module or booting the -+ system, instead of the date you downloaded. -+- configuration (define/undefine CONFIG_AUFS_xxx) -+- kernel configuration or /proc/config.gz (if you have it) -+- LSM (linux security module, if you are using) -+- behaviour which you think to be incorrect -+- actual operation, reproducible one is better -+- mailto: aufs-users at lists.sourceforge.net -+ -+Usually, I don't watch the Public Areas(Bugs, Support Requests, Patches, -+and Feature Requests) on SourceForge. Please join and write to -+aufs-users ML. -+ -+ -+6. Acknowledgements -+---------------------------------------- -+Thanks to everyone who have tried and are using aufs, whoever -+have reported a bug or any feedback. -+ -+Especially donators: -+Tomas Matejicek(slax.org) made a donation (much more than once). -+ Since Apr 2010, Tomas M (the author of Slax and Linux Live -+ scripts) is making "doubling" donations. -+ Unfortunately I cannot list all of the donators, but I really -+ appreciate. -+ It ends Aug 2010, but the ordinary donation URL is still available. -+ -+Dai Itasaka made a donation (2007/8). -+Chuck Smith made a donation (2008/4, 10 and 12). -+Henk Schoneveld made a donation (2008/9). -+Chih-Wei Huang, ASUS, CTC donated Eee PC 4G (2008/10). -+Francois Dupoux made a donation (2008/11). -+Bruno Cesar Ribas and Luis Carlos Erpen de Bona, C3SL serves public -+ aufs2 GIT tree (2009/2). -+William Grant made a donation (2009/3). -+Patrick Lane made a donation (2009/4). -+The Mail Archive (mail-archive.com) made donations (2009/5). -+Nippy Networks (Ed Wildgoose) made a donation (2009/7). -+New Dream Network, LLC (www.dreamhost.com) made a donation (2009/11). -+Pavel Pronskiy made a donation (2011/2). -+Iridium and Inmarsat satellite phone retailer (www.mailasail.com), Nippy -+ Networks (Ed Wildgoose) made a donation for hardware (2011/3). -+Max Lekomcev (DOM-TV project) made a donation (2011/7, 12, 2012/3, 6 and -+11). -+Sam Liddicott made a donation (2011/9). -+Era Scarecrow made a donation (2013/4). -+Bor Ratajc made a donation (2013/4). -+Alessandro Gorreta made a donation (2013/4). -+POIRETTE Marc made a donation (2013/4). -+Alessandro Gorreta made a donation (2013/4). -+lauri kasvandik made a donation (2013/5). -+"pemasu from Finland" made a donation (2013/7). -+The Parted Magic Project made a donation (2013/9 and 11). -+Pavel Barta made a donation (2013/10). -+Nikolay Pertsev made a donation (2014/5). -+James B made a donation (2014/7 and 2015/7). -+Stefano Di Biase made a donation (2014/8). -+Daniel Epellei made a donation (2015/1). -+OmegaPhil made a donation (2016/1, 2018/4). -+Tomasz Szewczyk made a donation (2016/4). -+James Burry made a donation (2016/12). -+Carsten Rose made a donation (2018/9). -+Porteus Kiosk made a donation (2018/10). -+ -+Thank you very much. -+Donations are always, including future donations, very important and -+helpful for me to keep on developing aufs. -+ -+ -+7. -+---------------------------------------- -+If you are an experienced user, no explanation is needed. Aufs is -+just a linux filesystem. -+ -+ -+Enjoy! -+ -+# Local variables: ; -+# mode: text; -+# End: ; -diff -Nurp linux-5.10-rc6/drivers/block/loop.c linux-5.10-rc6.aufs/drivers/block/loop.c ---- linux-5.10-rc6/drivers/block/loop.c 2020-12-02 21:18:30.377394775 +0200 -+++ linux-5.10-rc6.aufs/drivers/block/loop.c 2020-12-02 21:19:51.879036653 +0200 -@@ -765,6 +765,24 @@ out_err: - return error; - } - -+/* -+ * for AUFS -+ * no get/put for file. -+ */ -+struct file *loop_backing_file(struct super_block *sb) -+{ -+ struct file *ret; -+ struct loop_device *l; -+ -+ ret = NULL; -+ if (MAJOR(sb->s_dev) == LOOP_MAJOR) { -+ l = sb->s_bdev->bd_disk->private_data; -+ ret = l->lo_backing_file; -+ } -+ return ret; -+} -+EXPORT_SYMBOL_GPL(loop_backing_file); -+ - /* loop sysfs attributes */ - - static ssize_t loop_attr_show(struct device *dev, char *page, -diff -Nurp linux-5.10-rc6/fs/aufs/aufs.h linux-5.10-rc6.aufs/fs/aufs/aufs.h ---- linux-5.10-rc6/fs/aufs/aufs.h 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/aufs.h 2020-12-02 21:19:51.879036653 +0200 -@@ -0,0 +1,49 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * all header files -+ */ -+ -+#ifndef __AUFS_H__ -+#define __AUFS_H__ -+ -+#ifdef __KERNEL__ -+ -+#define AuStub(type, name, body, ...) \ -+ static inline type name(__VA_ARGS__) { body; } -+ -+#define AuStubVoid(name, ...) \ -+ AuStub(void, name, , __VA_ARGS__) -+#define AuStubInt0(name, ...) \ -+ AuStub(int, name, return 0, __VA_ARGS__) -+ -+#include "debug.h" -+ -+#include "branch.h" -+#include "cpup.h" -+#include "dcsub.h" -+#include "dbgaufs.h" -+#include "dentry.h" -+#include "dir.h" -+#include "dirren.h" -+#include "dynop.h" -+#include "file.h" -+#include "fstype.h" -+#include "hbl.h" -+#include "inode.h" -+#include "lcnt.h" -+#include "loop.h" -+#include "module.h" -+#include "opts.h" -+#include "rwsem.h" -+#include "super.h" -+#include "sysaufs.h" -+#include "vfsub.h" -+#include "whout.h" -+#include "wkq.h" -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_H__ */ -diff -Nurp linux-5.10-rc6/fs/aufs/branch.c linux-5.10-rc6.aufs/fs/aufs/branch.c ---- linux-5.10-rc6/fs/aufs/branch.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/branch.c 2020-12-02 21:19:51.880036698 +0200 -@@ -0,0 +1,1414 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * branch management -+ */ -+ -+#include -+#include -+#include "aufs.h" -+ -+/* -+ * free a single branch -+ */ -+static void au_br_do_free(struct au_branch *br) -+{ -+ int i; -+ struct au_wbr *wbr; -+ struct au_dykey **key; -+ -+ au_hnotify_fin_br(br); -+ /* always, regardless the mount option */ -+ au_dr_hino_free(&br->br_dirren); -+ au_xino_put(br); -+ -+ AuLCntZero(au_lcnt_read(&br->br_nfiles, /*do_rev*/0)); -+ au_lcnt_fin(&br->br_nfiles, /*do_sync*/0); -+ AuLCntZero(au_lcnt_read(&br->br_count, /*do_rev*/0)); -+ au_lcnt_fin(&br->br_count, /*do_sync*/0); -+ -+ wbr = br->br_wbr; -+ if (wbr) { -+ for (i = 0; i < AuBrWh_Last; i++) -+ dput(wbr->wbr_wh[i]); -+ AuDebugOn(atomic_read(&wbr->wbr_wh_running)); -+ AuRwDestroy(&wbr->wbr_wh_rwsem); -+ } -+ -+ if (br->br_fhsm) { -+ au_br_fhsm_fin(br->br_fhsm); -+ au_kfree_try_rcu(br->br_fhsm); -+ } -+ -+ key = br->br_dykey; -+ for (i = 0; i < AuBrDynOp; i++, key++) -+ if (*key) -+ au_dy_put(*key); -+ else -+ break; -+ -+ /* recursive lock, s_umount of branch's */ -+ /* synchronize_rcu(); */ /* why? */ -+ lockdep_off(); -+ path_put(&br->br_path); -+ lockdep_on(); -+ au_kfree_rcu(wbr); -+ au_lcnt_wait_for_fin(&br->br_nfiles); -+ au_lcnt_wait_for_fin(&br->br_count); -+ /* I don't know why, but percpu_refcount requires this */ -+ /* synchronize_rcu(); */ -+ au_kfree_rcu(br); -+} -+ -+/* -+ * frees all branches -+ */ -+void au_br_free(struct au_sbinfo *sbinfo) -+{ -+ aufs_bindex_t bmax; -+ struct au_branch **br; -+ -+ AuRwMustWriteLock(&sbinfo->si_rwsem); -+ -+ bmax = sbinfo->si_bbot + 1; -+ br = sbinfo->si_branch; -+ while (bmax--) -+ au_br_do_free(*br++); -+} -+ -+/* -+ * find the index of a branch which is specified by @br_id. -+ */ -+int au_br_index(struct super_block *sb, aufs_bindex_t br_id) -+{ -+ aufs_bindex_t bindex, bbot; -+ -+ bbot = au_sbbot(sb); -+ for (bindex = 0; bindex <= bbot; bindex++) -+ if (au_sbr_id(sb, bindex) == br_id) -+ return bindex; -+ return -1; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * add a branch -+ */ -+ -+static int test_overlap(struct super_block *sb, struct dentry *h_adding, -+ struct dentry *h_root) -+{ -+ if (unlikely(h_adding == h_root -+ || au_test_loopback_overlap(sb, h_adding))) -+ return 1; -+ if (h_adding->d_sb != h_root->d_sb) -+ return 0; -+ return au_test_subdir(h_adding, h_root) -+ || au_test_subdir(h_root, h_adding); -+} -+ -+/* -+ * returns a newly allocated branch. @new_nbranch is a number of branches -+ * after adding a branch. -+ */ -+static struct au_branch *au_br_alloc(struct super_block *sb, int new_nbranch, -+ int perm) -+{ -+ struct au_branch *add_branch; -+ struct dentry *root; -+ struct inode *inode; -+ int err; -+ -+ err = -ENOMEM; -+ add_branch = kzalloc(sizeof(*add_branch), GFP_NOFS); -+ if (unlikely(!add_branch)) -+ goto out; -+ add_branch->br_xino = au_xino_alloc(/*nfile*/1); -+ if (unlikely(!add_branch->br_xino)) -+ goto out_br; -+ err = au_hnotify_init_br(add_branch, perm); -+ if (unlikely(err)) -+ goto out_xino; -+ -+ if (au_br_writable(perm)) { -+ /* may be freed separately at changing the branch permission */ -+ add_branch->br_wbr = kzalloc(sizeof(*add_branch->br_wbr), -+ GFP_NOFS); -+ if (unlikely(!add_branch->br_wbr)) -+ goto out_hnotify; -+ } -+ -+ if (au_br_fhsm(perm)) { -+ err = au_fhsm_br_alloc(add_branch); -+ if (unlikely(err)) -+ goto out_wbr; -+ } -+ -+ root = sb->s_root; -+ err = au_sbr_realloc(au_sbi(sb), new_nbranch, /*may_shrink*/0); -+ if (!err) -+ err = au_di_realloc(au_di(root), new_nbranch, /*may_shrink*/0); -+ if (!err) { -+ inode = d_inode(root); -+ err = au_hinode_realloc(au_ii(inode), new_nbranch, -+ /*may_shrink*/0); -+ } -+ if (!err) -+ return add_branch; /* success */ -+ -+out_wbr: -+ au_kfree_rcu(add_branch->br_wbr); -+out_hnotify: -+ au_hnotify_fin_br(add_branch); -+out_xino: -+ au_xino_put(add_branch); -+out_br: -+ au_kfree_rcu(add_branch); -+out: -+ return ERR_PTR(err); -+} -+ -+/* -+ * test if the branch permission is legal or not. -+ */ -+static int test_br(struct inode *inode, int brperm, char *path) -+{ -+ int err; -+ -+ err = (au_br_writable(brperm) && IS_RDONLY(inode)); -+ if (!err) -+ goto out; -+ -+ err = -EINVAL; -+ pr_err("write permission for readonly mount or inode, %s\n", path); -+ -+out: -+ return err; -+} -+ -+/* -+ * returns: -+ * 0: success, the caller will add it -+ * plus: success, it is already unified, the caller should ignore it -+ * minus: error -+ */ -+static int test_add(struct super_block *sb, struct au_opt_add *add, int remount) -+{ -+ int err; -+ aufs_bindex_t bbot, bindex; -+ struct dentry *root, *h_dentry; -+ struct inode *inode, *h_inode; -+ -+ root = sb->s_root; -+ bbot = au_sbbot(sb); -+ if (unlikely(bbot >= 0 -+ && au_find_dbindex(root, add->path.dentry) >= 0)) { -+ err = 1; -+ if (!remount) { -+ err = -EINVAL; -+ pr_err("%s duplicated\n", add->pathname); -+ } -+ goto out; -+ } -+ -+ err = -ENOSPC; /* -E2BIG; */ -+ if (unlikely(AUFS_BRANCH_MAX <= add->bindex -+ || AUFS_BRANCH_MAX - 1 <= bbot)) { -+ pr_err("number of branches exceeded %s\n", add->pathname); -+ goto out; -+ } -+ -+ err = -EDOM; -+ if (unlikely(add->bindex < 0 || bbot + 1 < add->bindex)) { -+ pr_err("bad index %d\n", add->bindex); -+ goto out; -+ } -+ -+ inode = d_inode(add->path.dentry); -+ err = -ENOENT; -+ if (unlikely(!inode->i_nlink)) { -+ pr_err("no existence %s\n", add->pathname); -+ goto out; -+ } -+ -+ err = -EINVAL; -+ if (unlikely(inode->i_sb == sb)) { -+ pr_err("%s must be outside\n", add->pathname); -+ goto out; -+ } -+ -+ if (unlikely(au_test_fs_unsuppoted(inode->i_sb))) { -+ pr_err("unsupported filesystem, %s (%s)\n", -+ add->pathname, au_sbtype(inode->i_sb)); -+ goto out; -+ } -+ -+ if (unlikely(inode->i_sb->s_stack_depth)) { -+ pr_err("already stacked, %s (%s)\n", -+ add->pathname, au_sbtype(inode->i_sb)); -+ goto out; -+ } -+ -+ err = test_br(d_inode(add->path.dentry), add->perm, add->pathname); -+ if (unlikely(err)) -+ goto out; -+ -+ if (bbot < 0) -+ return 0; /* success */ -+ -+ err = -EINVAL; -+ for (bindex = 0; bindex <= bbot; bindex++) -+ if (unlikely(test_overlap(sb, add->path.dentry, -+ au_h_dptr(root, bindex)))) { -+ pr_err("%s is overlapped\n", add->pathname); -+ goto out; -+ } -+ -+ err = 0; -+ if (au_opt_test(au_mntflags(sb), WARN_PERM)) { -+ h_dentry = au_h_dptr(root, 0); -+ h_inode = d_inode(h_dentry); -+ if ((h_inode->i_mode & S_IALLUGO) != (inode->i_mode & S_IALLUGO) -+ || !uid_eq(h_inode->i_uid, inode->i_uid) -+ || !gid_eq(h_inode->i_gid, inode->i_gid)) -+ pr_warn("uid/gid/perm %s %u/%u/0%o, %u/%u/0%o\n", -+ add->pathname, -+ i_uid_read(inode), i_gid_read(inode), -+ (inode->i_mode & S_IALLUGO), -+ i_uid_read(h_inode), i_gid_read(h_inode), -+ (h_inode->i_mode & S_IALLUGO)); -+ } -+ -+out: -+ return err; -+} -+ -+/* -+ * initialize or clean the whiteouts for an adding branch -+ */ -+static int au_br_init_wh(struct super_block *sb, struct au_branch *br, -+ int new_perm) -+{ -+ int err, old_perm; -+ aufs_bindex_t bindex; -+ struct inode *h_inode; -+ struct au_wbr *wbr; -+ struct au_hinode *hdir; -+ struct dentry *h_dentry; -+ -+ err = vfsub_mnt_want_write(au_br_mnt(br)); -+ if (unlikely(err)) -+ goto out; -+ -+ wbr = br->br_wbr; -+ old_perm = br->br_perm; -+ br->br_perm = new_perm; -+ hdir = NULL; -+ h_inode = NULL; -+ bindex = au_br_index(sb, br->br_id); -+ if (0 <= bindex) { -+ hdir = au_hi(d_inode(sb->s_root), bindex); -+ au_hn_inode_lock_nested(hdir, AuLsc_I_PARENT); -+ } else { -+ h_dentry = au_br_dentry(br); -+ h_inode = d_inode(h_dentry); -+ inode_lock_nested(h_inode, AuLsc_I_PARENT); -+ } -+ if (!wbr) -+ err = au_wh_init(br, sb); -+ else { -+ wbr_wh_write_lock(wbr); -+ err = au_wh_init(br, sb); -+ wbr_wh_write_unlock(wbr); -+ } -+ if (hdir) -+ au_hn_inode_unlock(hdir); -+ else -+ inode_unlock(h_inode); -+ vfsub_mnt_drop_write(au_br_mnt(br)); -+ br->br_perm = old_perm; -+ -+ if (!err && wbr && !au_br_writable(new_perm)) { -+ au_kfree_rcu(wbr); -+ br->br_wbr = NULL; -+ } -+ -+out: -+ return err; -+} -+ -+static int au_wbr_init(struct au_branch *br, struct super_block *sb, -+ int perm) -+{ -+ int err; -+ struct kstatfs kst; -+ struct au_wbr *wbr; -+ -+ wbr = br->br_wbr; -+ au_rw_init(&wbr->wbr_wh_rwsem); -+ atomic_set(&wbr->wbr_wh_running, 0); -+ -+ /* -+ * a limit for rmdir/rename a dir -+ * cf. AUFS_MAX_NAMELEN in include/uapi/linux/aufs_type.h -+ */ -+ err = vfs_statfs(&br->br_path, &kst); -+ if (unlikely(err)) -+ goto out; -+ err = -EINVAL; -+ if (kst.f_namelen >= NAME_MAX) -+ err = au_br_init_wh(sb, br, perm); -+ else -+ pr_err("%pd(%s), unsupported namelen %ld\n", -+ au_br_dentry(br), -+ au_sbtype(au_br_dentry(br)->d_sb), kst.f_namelen); -+ -+out: -+ return err; -+} -+ -+/* initialize a new branch */ -+static int au_br_init(struct au_branch *br, struct super_block *sb, -+ struct au_opt_add *add) -+{ -+ int err; -+ struct au_branch *brbase; -+ struct file *xf; -+ struct inode *h_inode; -+ -+ err = 0; -+ br->br_perm = add->perm; -+ br->br_path = add->path; /* set first, path_get() later */ -+ spin_lock_init(&br->br_dykey_lock); -+ au_lcnt_init(&br->br_nfiles, /*release*/NULL); -+ au_lcnt_init(&br->br_count, /*release*/NULL); -+ br->br_id = au_new_br_id(sb); -+ AuDebugOn(br->br_id < 0); -+ -+ /* always, regardless the given option */ -+ err = au_dr_br_init(sb, br, &add->path); -+ if (unlikely(err)) -+ goto out_err; -+ -+ if (au_br_writable(add->perm)) { -+ err = au_wbr_init(br, sb, add->perm); -+ if (unlikely(err)) -+ goto out_err; -+ } -+ -+ if (au_opt_test(au_mntflags(sb), XINO)) { -+ brbase = au_sbr(sb, 0); -+ xf = au_xino_file(brbase->br_xino, /*idx*/-1); -+ AuDebugOn(!xf); -+ h_inode = d_inode(add->path.dentry); -+ err = au_xino_init_br(sb, br, h_inode->i_ino, &xf->f_path); -+ if (unlikely(err)) { -+ AuDebugOn(au_xino_file(br->br_xino, /*idx*/-1)); -+ goto out_err; -+ } -+ } -+ -+ sysaufs_br_init(br); -+ path_get(&br->br_path); -+ goto out; /* success */ -+ -+out_err: -+ memset(&br->br_path, 0, sizeof(br->br_path)); -+out: -+ return err; -+} -+ -+static void au_br_do_add_brp(struct au_sbinfo *sbinfo, aufs_bindex_t bindex, -+ struct au_branch *br, aufs_bindex_t bbot, -+ aufs_bindex_t amount) -+{ -+ struct au_branch **brp; -+ -+ AuRwMustWriteLock(&sbinfo->si_rwsem); -+ -+ brp = sbinfo->si_branch + bindex; -+ memmove(brp + 1, brp, sizeof(*brp) * amount); -+ *brp = br; -+ sbinfo->si_bbot++; -+ if (unlikely(bbot < 0)) -+ sbinfo->si_bbot = 0; -+} -+ -+static void au_br_do_add_hdp(struct au_dinfo *dinfo, aufs_bindex_t bindex, -+ aufs_bindex_t bbot, aufs_bindex_t amount) -+{ -+ struct au_hdentry *hdp; -+ -+ AuRwMustWriteLock(&dinfo->di_rwsem); -+ -+ hdp = au_hdentry(dinfo, bindex); -+ memmove(hdp + 1, hdp, sizeof(*hdp) * amount); -+ au_h_dentry_init(hdp); -+ dinfo->di_bbot++; -+ if (unlikely(bbot < 0)) -+ dinfo->di_btop = 0; -+} -+ -+static void au_br_do_add_hip(struct au_iinfo *iinfo, aufs_bindex_t bindex, -+ aufs_bindex_t bbot, aufs_bindex_t amount) -+{ -+ struct au_hinode *hip; -+ -+ AuRwMustWriteLock(&iinfo->ii_rwsem); -+ -+ hip = au_hinode(iinfo, bindex); -+ memmove(hip + 1, hip, sizeof(*hip) * amount); -+ au_hinode_init(hip); -+ iinfo->ii_bbot++; -+ if (unlikely(bbot < 0)) -+ iinfo->ii_btop = 0; -+} -+ -+static void au_br_do_add(struct super_block *sb, struct au_branch *br, -+ aufs_bindex_t bindex) -+{ -+ struct dentry *root, *h_dentry; -+ struct inode *root_inode, *h_inode; -+ aufs_bindex_t bbot, amount; -+ -+ root = sb->s_root; -+ root_inode = d_inode(root); -+ bbot = au_sbbot(sb); -+ amount = bbot + 1 - bindex; -+ h_dentry = au_br_dentry(br); -+ au_sbilist_lock(); -+ au_br_do_add_brp(au_sbi(sb), bindex, br, bbot, amount); -+ au_br_do_add_hdp(au_di(root), bindex, bbot, amount); -+ au_br_do_add_hip(au_ii(root_inode), bindex, bbot, amount); -+ au_set_h_dptr(root, bindex, dget(h_dentry)); -+ h_inode = d_inode(h_dentry); -+ au_set_h_iptr(root_inode, bindex, au_igrab(h_inode), /*flags*/0); -+ au_sbilist_unlock(); -+} -+ -+int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount) -+{ -+ int err; -+ aufs_bindex_t bbot, add_bindex; -+ struct dentry *root, *h_dentry; -+ struct inode *root_inode; -+ struct au_branch *add_branch; -+ -+ root = sb->s_root; -+ root_inode = d_inode(root); -+ IMustLock(root_inode); -+ IiMustWriteLock(root_inode); -+ err = test_add(sb, add, remount); -+ if (unlikely(err < 0)) -+ goto out; -+ if (err) { -+ err = 0; -+ goto out; /* success */ -+ } -+ -+ bbot = au_sbbot(sb); -+ add_branch = au_br_alloc(sb, bbot + 2, add->perm); -+ err = PTR_ERR(add_branch); -+ if (IS_ERR(add_branch)) -+ goto out; -+ -+ err = au_br_init(add_branch, sb, add); -+ if (unlikely(err)) { -+ au_br_do_free(add_branch); -+ goto out; -+ } -+ -+ add_bindex = add->bindex; -+ sysaufs_brs_del(sb, add_bindex); /* remove successors */ -+ au_br_do_add(sb, add_branch, add_bindex); -+ sysaufs_brs_add(sb, add_bindex); /* append successors */ -+ dbgaufs_brs_add(sb, add_bindex, /*topdown*/0); /* rename successors */ -+ -+ h_dentry = add->path.dentry; -+ if (!add_bindex) { -+ au_cpup_attr_all(root_inode, /*force*/1); -+ sb->s_maxbytes = h_dentry->d_sb->s_maxbytes; -+ } else -+ au_add_nlink(root_inode, d_inode(h_dentry)); -+ -+out: -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static unsigned long long au_farray_cb(struct super_block *sb, void *a, -+ unsigned long long max __maybe_unused, -+ void *arg) -+{ -+ unsigned long long n; -+ struct file **p, *f; -+ struct hlist_bl_head *files; -+ struct hlist_bl_node *pos; -+ struct au_finfo *finfo; -+ -+ n = 0; -+ p = a; -+ files = &au_sbi(sb)->si_files; -+ hlist_bl_lock(files); -+ hlist_bl_for_each_entry(finfo, pos, files, fi_hlist) { -+ f = finfo->fi_file; -+ if (file_count(f) -+ && !special_file(file_inode(f)->i_mode)) { -+ get_file(f); -+ *p++ = f; -+ n++; -+ AuDebugOn(n > max); -+ } -+ } -+ hlist_bl_unlock(files); -+ -+ return n; -+} -+ -+static struct file **au_farray_alloc(struct super_block *sb, -+ unsigned long long *max) -+{ -+ struct au_sbinfo *sbi; -+ -+ sbi = au_sbi(sb); -+ *max = au_lcnt_read(&sbi->si_nfiles, /*do_rev*/1); -+ return au_array_alloc(max, au_farray_cb, sb, /*arg*/NULL); -+} -+ -+static void au_farray_free(struct file **a, unsigned long long max) -+{ -+ unsigned long long ull; -+ -+ for (ull = 0; ull < max; ull++) -+ if (a[ull]) -+ fput(a[ull]); -+ kvfree(a); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * delete a branch -+ */ -+ -+/* to show the line number, do not make it inlined function */ -+#define AuVerbose(do_info, fmt, ...) do { \ -+ if (do_info) \ -+ pr_info(fmt, ##__VA_ARGS__); \ -+} while (0) -+ -+static int au_test_ibusy(struct inode *inode, aufs_bindex_t btop, -+ aufs_bindex_t bbot) -+{ -+ return (inode && !S_ISDIR(inode->i_mode)) || btop == bbot; -+} -+ -+static int au_test_dbusy(struct dentry *dentry, aufs_bindex_t btop, -+ aufs_bindex_t bbot) -+{ -+ return au_test_ibusy(d_inode(dentry), btop, bbot); -+} -+ -+/* -+ * test if the branch is deletable or not. -+ */ -+static int test_dentry_busy(struct dentry *root, aufs_bindex_t bindex, -+ unsigned int sigen, const unsigned int verbose) -+{ -+ int err, i, j, ndentry; -+ aufs_bindex_t btop, bbot; -+ struct au_dcsub_pages dpages; -+ struct au_dpage *dpage; -+ struct dentry *d; -+ -+ err = au_dpages_init(&dpages, GFP_NOFS); -+ if (unlikely(err)) -+ goto out; -+ err = au_dcsub_pages(&dpages, root, NULL, NULL); -+ if (unlikely(err)) -+ goto out_dpages; -+ -+ for (i = 0; !err && i < dpages.ndpage; i++) { -+ dpage = dpages.dpages + i; -+ ndentry = dpage->ndentry; -+ for (j = 0; !err && j < ndentry; j++) { -+ d = dpage->dentries[j]; -+ AuDebugOn(au_dcount(d) <= 0); -+ if (!au_digen_test(d, sigen)) { -+ di_read_lock_child(d, AuLock_IR); -+ if (unlikely(au_dbrange_test(d))) { -+ di_read_unlock(d, AuLock_IR); -+ continue; -+ } -+ } else { -+ di_write_lock_child(d); -+ if (unlikely(au_dbrange_test(d))) { -+ di_write_unlock(d); -+ continue; -+ } -+ err = au_reval_dpath(d, sigen); -+ if (!err) -+ di_downgrade_lock(d, AuLock_IR); -+ else { -+ di_write_unlock(d); -+ break; -+ } -+ } -+ -+ /* AuDbgDentry(d); */ -+ btop = au_dbtop(d); -+ bbot = au_dbbot(d); -+ if (btop <= bindex -+ && bindex <= bbot -+ && au_h_dptr(d, bindex) -+ && au_test_dbusy(d, btop, bbot)) { -+ err = -EBUSY; -+ AuVerbose(verbose, "busy %pd\n", d); -+ AuDbgDentry(d); -+ } -+ di_read_unlock(d, AuLock_IR); -+ } -+ } -+ -+out_dpages: -+ au_dpages_free(&dpages); -+out: -+ return err; -+} -+ -+static int test_inode_busy(struct super_block *sb, aufs_bindex_t bindex, -+ unsigned int sigen, const unsigned int verbose) -+{ -+ int err; -+ unsigned long long max, ull; -+ struct inode *i, **array; -+ aufs_bindex_t btop, bbot; -+ -+ array = au_iarray_alloc(sb, &max); -+ err = PTR_ERR(array); -+ if (IS_ERR(array)) -+ goto out; -+ -+ err = 0; -+ AuDbg("b%d\n", bindex); -+ for (ull = 0; !err && ull < max; ull++) { -+ i = array[ull]; -+ if (unlikely(!i)) -+ break; -+ if (i->i_ino == AUFS_ROOT_INO) -+ continue; -+ -+ /* AuDbgInode(i); */ -+ if (au_iigen(i, NULL) == sigen) -+ ii_read_lock_child(i); -+ else { -+ ii_write_lock_child(i); -+ err = au_refresh_hinode_self(i); -+ au_iigen_dec(i); -+ if (!err) -+ ii_downgrade_lock(i); -+ else { -+ ii_write_unlock(i); -+ break; -+ } -+ } -+ -+ btop = au_ibtop(i); -+ bbot = au_ibbot(i); -+ if (btop <= bindex -+ && bindex <= bbot -+ && au_h_iptr(i, bindex) -+ && au_test_ibusy(i, btop, bbot)) { -+ err = -EBUSY; -+ AuVerbose(verbose, "busy i%lu\n", i->i_ino); -+ AuDbgInode(i); -+ } -+ ii_read_unlock(i); -+ } -+ au_iarray_free(array, max); -+ -+out: -+ return err; -+} -+ -+static int test_children_busy(struct dentry *root, aufs_bindex_t bindex, -+ const unsigned int verbose) -+{ -+ int err; -+ unsigned int sigen; -+ -+ sigen = au_sigen(root->d_sb); -+ DiMustNoWaiters(root); -+ IiMustNoWaiters(d_inode(root)); -+ di_write_unlock(root); -+ err = test_dentry_busy(root, bindex, sigen, verbose); -+ if (!err) -+ err = test_inode_busy(root->d_sb, bindex, sigen, verbose); -+ di_write_lock_child(root); /* aufs_write_lock() calls ..._child() */ -+ -+ return err; -+} -+ -+static int test_dir_busy(struct file *file, aufs_bindex_t br_id, -+ struct file **to_free, int *idx) -+{ -+ int err; -+ unsigned char matched, root; -+ aufs_bindex_t bindex, bbot; -+ struct au_fidir *fidir; -+ struct au_hfile *hfile; -+ -+ err = 0; -+ root = IS_ROOT(file->f_path.dentry); -+ if (root) { -+ get_file(file); -+ to_free[*idx] = file; -+ (*idx)++; -+ goto out; -+ } -+ -+ matched = 0; -+ fidir = au_fi(file)->fi_hdir; -+ AuDebugOn(!fidir); -+ bbot = au_fbbot_dir(file); -+ for (bindex = au_fbtop(file); bindex <= bbot; bindex++) { -+ hfile = fidir->fd_hfile + bindex; -+ if (!hfile->hf_file) -+ continue; -+ -+ if (hfile->hf_br->br_id == br_id) { -+ matched = 1; -+ break; -+ } -+ } -+ if (matched) -+ err = -EBUSY; -+ -+out: -+ return err; -+} -+ -+static int test_file_busy(struct super_block *sb, aufs_bindex_t br_id, -+ struct file **to_free, int opened) -+{ -+ int err, idx; -+ unsigned long long ull, max; -+ aufs_bindex_t btop; -+ struct file *file, **array; -+ struct dentry *root; -+ struct au_hfile *hfile; -+ -+ array = au_farray_alloc(sb, &max); -+ err = PTR_ERR(array); -+ if (IS_ERR(array)) -+ goto out; -+ -+ err = 0; -+ idx = 0; -+ root = sb->s_root; -+ di_write_unlock(root); -+ for (ull = 0; ull < max; ull++) { -+ file = array[ull]; -+ if (unlikely(!file)) -+ break; -+ -+ /* AuDbg("%pD\n", file); */ -+ fi_read_lock(file); -+ btop = au_fbtop(file); -+ if (!d_is_dir(file->f_path.dentry)) { -+ hfile = &au_fi(file)->fi_htop; -+ if (hfile->hf_br->br_id == br_id) -+ err = -EBUSY; -+ } else -+ err = test_dir_busy(file, br_id, to_free, &idx); -+ fi_read_unlock(file); -+ if (unlikely(err)) -+ break; -+ } -+ di_write_lock_child(root); -+ au_farray_free(array, max); -+ AuDebugOn(idx > opened); -+ -+out: -+ return err; -+} -+ -+static void br_del_file(struct file **to_free, unsigned long long opened, -+ aufs_bindex_t br_id) -+{ -+ unsigned long long ull; -+ aufs_bindex_t bindex, btop, bbot, bfound; -+ struct file *file; -+ struct au_fidir *fidir; -+ struct au_hfile *hfile; -+ -+ for (ull = 0; ull < opened; ull++) { -+ file = to_free[ull]; -+ if (unlikely(!file)) -+ break; -+ -+ /* AuDbg("%pD\n", file); */ -+ AuDebugOn(!d_is_dir(file->f_path.dentry)); -+ bfound = -1; -+ fidir = au_fi(file)->fi_hdir; -+ AuDebugOn(!fidir); -+ fi_write_lock(file); -+ btop = au_fbtop(file); -+ bbot = au_fbbot_dir(file); -+ for (bindex = btop; bindex <= bbot; bindex++) { -+ hfile = fidir->fd_hfile + bindex; -+ if (!hfile->hf_file) -+ continue; -+ -+ if (hfile->hf_br->br_id == br_id) { -+ bfound = bindex; -+ break; -+ } -+ } -+ AuDebugOn(bfound < 0); -+ au_set_h_fptr(file, bfound, NULL); -+ if (bfound == btop) { -+ for (btop++; btop <= bbot; btop++) -+ if (au_hf_dir(file, btop)) { -+ au_set_fbtop(file, btop); -+ break; -+ } -+ } -+ fi_write_unlock(file); -+ } -+} -+ -+static void au_br_do_del_brp(struct au_sbinfo *sbinfo, -+ const aufs_bindex_t bindex, -+ const aufs_bindex_t bbot) -+{ -+ struct au_branch **brp, **p; -+ -+ AuRwMustWriteLock(&sbinfo->si_rwsem); -+ -+ brp = sbinfo->si_branch + bindex; -+ if (bindex < bbot) -+ memmove(brp, brp + 1, sizeof(*brp) * (bbot - bindex)); -+ sbinfo->si_branch[0 + bbot] = NULL; -+ sbinfo->si_bbot--; -+ -+ p = au_krealloc(sbinfo->si_branch, sizeof(*p) * bbot, AuGFP_SBILIST, -+ /*may_shrink*/1); -+ if (p) -+ sbinfo->si_branch = p; -+ /* harmless error */ -+} -+ -+static void au_br_do_del_hdp(struct au_dinfo *dinfo, const aufs_bindex_t bindex, -+ const aufs_bindex_t bbot) -+{ -+ struct au_hdentry *hdp, *p; -+ -+ AuRwMustWriteLock(&dinfo->di_rwsem); -+ -+ hdp = au_hdentry(dinfo, bindex); -+ if (bindex < bbot) -+ memmove(hdp, hdp + 1, sizeof(*hdp) * (bbot - bindex)); -+ /* au_h_dentry_init(au_hdentry(dinfo, bbot); */ -+ dinfo->di_bbot--; -+ -+ p = au_krealloc(dinfo->di_hdentry, sizeof(*p) * bbot, AuGFP_SBILIST, -+ /*may_shrink*/1); -+ if (p) -+ dinfo->di_hdentry = p; -+ /* harmless error */ -+} -+ -+static void au_br_do_del_hip(struct au_iinfo *iinfo, const aufs_bindex_t bindex, -+ const aufs_bindex_t bbot) -+{ -+ struct au_hinode *hip, *p; -+ -+ AuRwMustWriteLock(&iinfo->ii_rwsem); -+ -+ hip = au_hinode(iinfo, bindex); -+ if (bindex < bbot) -+ memmove(hip, hip + 1, sizeof(*hip) * (bbot - bindex)); -+ /* au_hinode_init(au_hinode(iinfo, bbot)); */ -+ iinfo->ii_bbot--; -+ -+ p = au_krealloc(iinfo->ii_hinode, sizeof(*p) * bbot, AuGFP_SBILIST, -+ /*may_shrink*/1); -+ if (p) -+ iinfo->ii_hinode = p; -+ /* harmless error */ -+} -+ -+static void au_br_do_del(struct super_block *sb, aufs_bindex_t bindex, -+ struct au_branch *br) -+{ -+ aufs_bindex_t bbot; -+ struct au_sbinfo *sbinfo; -+ struct dentry *root, *h_root; -+ struct inode *inode, *h_inode; -+ struct au_hinode *hinode; -+ -+ SiMustWriteLock(sb); -+ -+ root = sb->s_root; -+ inode = d_inode(root); -+ sbinfo = au_sbi(sb); -+ bbot = sbinfo->si_bbot; -+ -+ h_root = au_h_dptr(root, bindex); -+ hinode = au_hi(inode, bindex); -+ h_inode = au_igrab(hinode->hi_inode); -+ au_hiput(hinode); -+ -+ au_sbilist_lock(); -+ au_br_do_del_brp(sbinfo, bindex, bbot); -+ au_br_do_del_hdp(au_di(root), bindex, bbot); -+ au_br_do_del_hip(au_ii(inode), bindex, bbot); -+ au_sbilist_unlock(); -+ -+ /* ignore an error */ -+ au_dr_br_fin(sb, br); /* always, regardless the mount option */ -+ -+ dput(h_root); -+ iput(h_inode); -+ au_br_do_free(br); -+} -+ -+static unsigned long long empty_cb(struct super_block *sb, void *array, -+ unsigned long long max, void *arg) -+{ -+ return max; -+} -+ -+int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount) -+{ -+ int err, rerr, i; -+ unsigned long long opened; -+ unsigned int mnt_flags; -+ aufs_bindex_t bindex, bbot, br_id; -+ unsigned char do_wh, verbose; -+ struct au_branch *br; -+ struct au_wbr *wbr; -+ struct dentry *root; -+ struct file **to_free; -+ -+ err = 0; -+ opened = 0; -+ to_free = NULL; -+ root = sb->s_root; -+ bindex = au_find_dbindex(root, del->h_path.dentry); -+ if (bindex < 0) { -+ if (remount) -+ goto out; /* success */ -+ err = -ENOENT; -+ pr_err("%s no such branch\n", del->pathname); -+ goto out; -+ } -+ AuDbg("bindex b%d\n", bindex); -+ -+ err = -EBUSY; -+ mnt_flags = au_mntflags(sb); -+ verbose = !!au_opt_test(mnt_flags, VERBOSE); -+ bbot = au_sbbot(sb); -+ if (unlikely(!bbot)) { -+ AuVerbose(verbose, "no more branches left\n"); -+ goto out; -+ } -+ -+ br = au_sbr(sb, bindex); -+ AuDebugOn(!path_equal(&br->br_path, &del->h_path)); -+ if (unlikely(au_lcnt_read(&br->br_count, /*do_rev*/1))) { -+ AuVerbose(verbose, "br %pd2 is busy now\n", del->h_path.dentry); -+ goto out; -+ } -+ -+ br_id = br->br_id; -+ opened = au_lcnt_read(&br->br_nfiles, /*do_rev*/1); -+ if (unlikely(opened)) { -+ to_free = au_array_alloc(&opened, empty_cb, sb, NULL); -+ err = PTR_ERR(to_free); -+ if (IS_ERR(to_free)) -+ goto out; -+ -+ err = test_file_busy(sb, br_id, to_free, opened); -+ if (unlikely(err)) { -+ AuVerbose(verbose, "%llu file(s) opened\n", opened); -+ goto out; -+ } -+ } -+ -+ wbr = br->br_wbr; -+ do_wh = wbr && (wbr->wbr_whbase || wbr->wbr_plink || wbr->wbr_orph); -+ if (do_wh) { -+ /* instead of WbrWhMustWriteLock(wbr) */ -+ SiMustWriteLock(sb); -+ for (i = 0; i < AuBrWh_Last; i++) { -+ dput(wbr->wbr_wh[i]); -+ wbr->wbr_wh[i] = NULL; -+ } -+ } -+ -+ err = test_children_busy(root, bindex, verbose); -+ if (unlikely(err)) { -+ if (do_wh) -+ goto out_wh; -+ goto out; -+ } -+ -+ err = 0; -+ if (to_free) { -+ /* -+ * now we confirmed the branch is deletable. -+ * let's free the remaining opened dirs on the branch. -+ */ -+ di_write_unlock(root); -+ br_del_file(to_free, opened, br_id); -+ di_write_lock_child(root); -+ } -+ -+ sysaufs_brs_del(sb, bindex); /* remove successors */ -+ dbgaufs_xino_del(br); /* remove one */ -+ au_br_do_del(sb, bindex, br); -+ sysaufs_brs_add(sb, bindex); /* append successors */ -+ dbgaufs_brs_add(sb, bindex, /*topdown*/1); /* rename successors */ -+ -+ if (!bindex) { -+ au_cpup_attr_all(d_inode(root), /*force*/1); -+ sb->s_maxbytes = au_sbr_sb(sb, 0)->s_maxbytes; -+ } else -+ au_sub_nlink(d_inode(root), d_inode(del->h_path.dentry)); -+ if (au_opt_test(mnt_flags, PLINK)) -+ au_plink_half_refresh(sb, br_id); -+ -+ goto out; /* success */ -+ -+out_wh: -+ /* revert */ -+ rerr = au_br_init_wh(sb, br, br->br_perm); -+ if (rerr) -+ pr_warn("failed re-creating base whiteout, %s. (%d)\n", -+ del->pathname, rerr); -+out: -+ if (to_free) -+ au_farray_free(to_free, opened); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int au_ibusy(struct super_block *sb, struct aufs_ibusy __user *arg) -+{ -+ int err; -+ aufs_bindex_t btop, bbot; -+ struct aufs_ibusy ibusy; -+ struct inode *inode, *h_inode; -+ -+ err = -EPERM; -+ if (unlikely(!capable(CAP_SYS_ADMIN))) -+ goto out; -+ -+ err = copy_from_user(&ibusy, arg, sizeof(ibusy)); -+ if (!err) -+ /* VERIFY_WRITE */ -+ err = !access_ok(&arg->h_ino, sizeof(arg->h_ino)); -+ if (unlikely(err)) { -+ err = -EFAULT; -+ AuTraceErr(err); -+ goto out; -+ } -+ -+ err = -EINVAL; -+ si_read_lock(sb, AuLock_FLUSH); -+ if (unlikely(ibusy.bindex < 0 || ibusy.bindex > au_sbbot(sb))) -+ goto out_unlock; -+ -+ err = 0; -+ ibusy.h_ino = 0; /* invalid */ -+ inode = ilookup(sb, ibusy.ino); -+ if (!inode -+ || inode->i_ino == AUFS_ROOT_INO -+ || au_is_bad_inode(inode)) -+ goto out_unlock; -+ -+ ii_read_lock_child(inode); -+ btop = au_ibtop(inode); -+ bbot = au_ibbot(inode); -+ if (btop <= ibusy.bindex && ibusy.bindex <= bbot) { -+ h_inode = au_h_iptr(inode, ibusy.bindex); -+ if (h_inode && au_test_ibusy(inode, btop, bbot)) -+ ibusy.h_ino = h_inode->i_ino; -+ } -+ ii_read_unlock(inode); -+ iput(inode); -+ -+out_unlock: -+ si_read_unlock(sb); -+ if (!err) { -+ err = __put_user(ibusy.h_ino, &arg->h_ino); -+ if (unlikely(err)) { -+ err = -EFAULT; -+ AuTraceErr(err); -+ } -+ } -+out: -+ return err; -+} -+ -+long au_ibusy_ioctl(struct file *file, unsigned long arg) -+{ -+ return au_ibusy(file->f_path.dentry->d_sb, (void __user *)arg); -+} -+ -+#ifdef CONFIG_COMPAT -+long au_ibusy_compat_ioctl(struct file *file, unsigned long arg) -+{ -+ return au_ibusy(file->f_path.dentry->d_sb, compat_ptr(arg)); -+} -+#endif -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * change a branch permission -+ */ -+ -+static void au_warn_ima(void) -+{ -+#ifdef CONFIG_IMA -+ /* since it doesn't support mark_files_ro() */ -+ AuWarn1("RW -> RO makes IMA to produce wrong message\n"); -+#endif -+} -+ -+static int do_need_sigen_inc(int a, int b) -+{ -+ return au_br_whable(a) && !au_br_whable(b); -+} -+ -+static int need_sigen_inc(int old, int new) -+{ -+ return do_need_sigen_inc(old, new) -+ || do_need_sigen_inc(new, old); -+} -+ -+static int au_br_mod_files_ro(struct super_block *sb, aufs_bindex_t bindex) -+{ -+ int err, do_warn; -+ unsigned int mnt_flags; -+ unsigned long long ull, max; -+ aufs_bindex_t br_id; -+ unsigned char verbose, writer; -+ struct file *file, *hf, **array; -+ struct au_hfile *hfile; -+ struct inode *h_inode; -+ -+ mnt_flags = au_mntflags(sb); -+ verbose = !!au_opt_test(mnt_flags, VERBOSE); -+ -+ array = au_farray_alloc(sb, &max); -+ err = PTR_ERR(array); -+ if (IS_ERR(array)) -+ goto out; -+ -+ do_warn = 0; -+ br_id = au_sbr_id(sb, bindex); -+ for (ull = 0; ull < max; ull++) { -+ file = array[ull]; -+ if (unlikely(!file)) -+ break; -+ -+ /* AuDbg("%pD\n", file); */ -+ fi_read_lock(file); -+ if (unlikely(au_test_mmapped(file))) { -+ err = -EBUSY; -+ AuVerbose(verbose, "mmapped %pD\n", file); -+ AuDbgFile(file); -+ FiMustNoWaiters(file); -+ fi_read_unlock(file); -+ goto out_array; -+ } -+ -+ hfile = &au_fi(file)->fi_htop; -+ hf = hfile->hf_file; -+ if (!d_is_reg(file->f_path.dentry) -+ || !(file->f_mode & FMODE_WRITE) -+ || hfile->hf_br->br_id != br_id -+ || !(hf->f_mode & FMODE_WRITE)) -+ array[ull] = NULL; -+ else { -+ do_warn = 1; -+ get_file(file); -+ } -+ -+ FiMustNoWaiters(file); -+ fi_read_unlock(file); -+ fput(file); -+ } -+ -+ err = 0; -+ if (do_warn) -+ au_warn_ima(); -+ -+ for (ull = 0; ull < max; ull++) { -+ file = array[ull]; -+ if (!file) -+ continue; -+ -+ /* todo: already flushed? */ -+ /* -+ * fs/super.c:mark_files_ro() is gone, but aufs keeps its -+ * approach which resets f_mode and calls mnt_drop_write() and -+ * file_release_write() for each file, because the branch -+ * attribute in aufs world is totally different from the native -+ * fs rw/ro mode. -+ */ -+ /* fi_read_lock(file); */ -+ hfile = &au_fi(file)->fi_htop; -+ hf = hfile->hf_file; -+ /* fi_read_unlock(file); */ -+ spin_lock(&hf->f_lock); -+ writer = !!(hf->f_mode & FMODE_WRITER); -+ hf->f_mode &= ~(FMODE_WRITE | FMODE_WRITER); -+ spin_unlock(&hf->f_lock); -+ if (writer) { -+ h_inode = file_inode(hf); -+ if (hf->f_mode & FMODE_READ) -+ i_readcount_inc(h_inode); -+ put_write_access(h_inode); -+ __mnt_drop_write(hf->f_path.mnt); -+ } -+ } -+ -+out_array: -+ au_farray_free(array, max); -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount, -+ int *do_refresh) -+{ -+ int err, rerr; -+ aufs_bindex_t bindex; -+ struct dentry *root; -+ struct au_branch *br; -+ struct au_br_fhsm *bf; -+ -+ root = sb->s_root; -+ bindex = au_find_dbindex(root, mod->h_root); -+ if (bindex < 0) { -+ if (remount) -+ return 0; /* success */ -+ err = -ENOENT; -+ pr_err("%s no such branch\n", mod->path); -+ goto out; -+ } -+ AuDbg("bindex b%d\n", bindex); -+ -+ err = test_br(d_inode(mod->h_root), mod->perm, mod->path); -+ if (unlikely(err)) -+ goto out; -+ -+ br = au_sbr(sb, bindex); -+ AuDebugOn(mod->h_root != au_br_dentry(br)); -+ if (br->br_perm == mod->perm) -+ return 0; /* success */ -+ -+ /* pre-allocate for non-fhsm --> fhsm */ -+ bf = NULL; -+ if (!au_br_fhsm(br->br_perm) && au_br_fhsm(mod->perm)) { -+ err = au_fhsm_br_alloc(br); -+ if (unlikely(err)) -+ goto out; -+ bf = br->br_fhsm; -+ br->br_fhsm = NULL; -+ } -+ -+ if (au_br_writable(br->br_perm)) { -+ /* remove whiteout base */ -+ err = au_br_init_wh(sb, br, mod->perm); -+ if (unlikely(err)) -+ goto out_bf; -+ -+ if (!au_br_writable(mod->perm)) { -+ /* rw --> ro, file might be mmapped */ -+ DiMustNoWaiters(root); -+ IiMustNoWaiters(d_inode(root)); -+ di_write_unlock(root); -+ err = au_br_mod_files_ro(sb, bindex); -+ /* aufs_write_lock() calls ..._child() */ -+ di_write_lock_child(root); -+ -+ if (unlikely(err)) { -+ rerr = -ENOMEM; -+ br->br_wbr = kzalloc(sizeof(*br->br_wbr), -+ GFP_NOFS); -+ if (br->br_wbr) -+ rerr = au_wbr_init(br, sb, br->br_perm); -+ if (unlikely(rerr)) { -+ AuIOErr("nested error %d (%d)\n", -+ rerr, err); -+ br->br_perm = mod->perm; -+ } -+ } -+ } -+ } else if (au_br_writable(mod->perm)) { -+ /* ro --> rw */ -+ err = -ENOMEM; -+ br->br_wbr = kzalloc(sizeof(*br->br_wbr), GFP_NOFS); -+ if (br->br_wbr) { -+ err = au_wbr_init(br, sb, mod->perm); -+ if (unlikely(err)) { -+ au_kfree_rcu(br->br_wbr); -+ br->br_wbr = NULL; -+ } -+ } -+ } -+ if (unlikely(err)) -+ goto out_bf; -+ -+ if (au_br_fhsm(br->br_perm)) { -+ if (!au_br_fhsm(mod->perm)) { -+ /* fhsm --> non-fhsm */ -+ au_br_fhsm_fin(br->br_fhsm); -+ au_kfree_rcu(br->br_fhsm); -+ br->br_fhsm = NULL; -+ } -+ } else if (au_br_fhsm(mod->perm)) -+ /* non-fhsm --> fhsm */ -+ br->br_fhsm = bf; -+ -+ *do_refresh |= need_sigen_inc(br->br_perm, mod->perm); -+ br->br_perm = mod->perm; -+ goto out; /* success */ -+ -+out_bf: -+ au_kfree_try_rcu(bf); -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+int au_br_stfs(struct au_branch *br, struct aufs_stfs *stfs) -+{ -+ int err; -+ struct kstatfs kstfs; -+ -+ err = vfs_statfs(&br->br_path, &kstfs); -+ if (!err) { -+ stfs->f_blocks = kstfs.f_blocks; -+ stfs->f_bavail = kstfs.f_bavail; -+ stfs->f_files = kstfs.f_files; -+ stfs->f_ffree = kstfs.f_ffree; -+ } -+ -+ return err; -+} -diff -Nurp linux-5.10-rc6/fs/aufs/branch.h linux-5.10-rc6.aufs/fs/aufs/branch.h ---- linux-5.10-rc6/fs/aufs/branch.h 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/branch.h 2020-12-02 21:19:51.880036698 +0200 -@@ -0,0 +1,353 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * branch filesystems and xino for them -+ */ -+ -+#ifndef __AUFS_BRANCH_H__ -+#define __AUFS_BRANCH_H__ -+ -+#ifdef __KERNEL__ -+ -+#include -+#include "dirren.h" -+#include "dynop.h" -+#include "lcnt.h" -+#include "rwsem.h" -+#include "super.h" -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* a xino file */ -+struct au_xino { -+ struct file **xi_file; -+ unsigned int xi_nfile; -+ -+ struct { -+ spinlock_t spin; -+ ino_t *array; -+ int total; -+ /* reserved for future use */ -+ /* unsigned long *bitmap; */ -+ wait_queue_head_t wqh; -+ } xi_nondir; -+ -+ struct mutex xi_mtx; /* protects xi_file array */ -+ struct hlist_bl_head xi_writing; -+ -+ atomic_t xi_truncating; -+ -+ struct kref xi_kref; -+}; -+ -+/* File-based Hierarchical Storage Management */ -+struct au_br_fhsm { -+#ifdef CONFIG_AUFS_FHSM -+ struct mutex bf_lock; -+ unsigned long bf_jiffy; -+ struct aufs_stfs bf_stfs; -+ int bf_readable; -+#endif -+}; -+ -+/* members for writable branch only */ -+enum {AuBrWh_BASE, AuBrWh_PLINK, AuBrWh_ORPH, AuBrWh_Last}; -+struct au_wbr { -+ struct au_rwsem wbr_wh_rwsem; -+ struct dentry *wbr_wh[AuBrWh_Last]; -+ atomic_t wbr_wh_running; -+#define wbr_whbase wbr_wh[AuBrWh_BASE] /* whiteout base */ -+#define wbr_plink wbr_wh[AuBrWh_PLINK] /* pseudo-link dir */ -+#define wbr_orph wbr_wh[AuBrWh_ORPH] /* dir for orphans */ -+ -+ /* mfs mode */ -+ unsigned long long wbr_bytes; -+}; -+ -+/* ext2 has 3 types of operations at least, ext3 has 4 */ -+#define AuBrDynOp (AuDyLast * 4) -+ -+#ifdef CONFIG_AUFS_HFSNOTIFY -+/* support for asynchronous destruction */ -+struct au_br_hfsnotify { -+ struct fsnotify_group *hfsn_group; -+}; -+#endif -+ -+/* sysfs entries */ -+struct au_brsysfs { -+ char name[16]; -+ struct attribute attr; -+}; -+ -+enum { -+ AuBrSysfs_BR, -+ AuBrSysfs_BRID, -+ AuBrSysfs_Last -+}; -+ -+/* protected by superblock rwsem */ -+struct au_branch { -+ struct au_xino *br_xino; -+ -+ aufs_bindex_t br_id; -+ -+ int br_perm; -+ struct path br_path; -+ spinlock_t br_dykey_lock; -+ struct au_dykey *br_dykey[AuBrDynOp]; -+ au_lcnt_t br_nfiles; /* opened files */ -+ au_lcnt_t br_count; /* in-use for other */ -+ -+ struct au_wbr *br_wbr; -+ struct au_br_fhsm *br_fhsm; -+ -+#ifdef CONFIG_AUFS_HFSNOTIFY -+ struct au_br_hfsnotify *br_hfsn; -+#endif -+ -+#ifdef CONFIG_SYSFS -+ /* entries under sysfs per mount-point */ -+ struct au_brsysfs br_sysfs[AuBrSysfs_Last]; -+#endif -+ -+#ifdef CONFIG_DEBUG_FS -+ struct dentry *br_dbgaufs; /* xino */ -+#endif -+ -+ struct au_dr_br br_dirren; -+}; -+ -+/* ---------------------------------------------------------------------- */ -+ -+static inline struct vfsmount *au_br_mnt(struct au_branch *br) -+{ -+ return br->br_path.mnt; -+} -+ -+static inline struct dentry *au_br_dentry(struct au_branch *br) -+{ -+ return br->br_path.dentry; -+} -+ -+static inline struct super_block *au_br_sb(struct au_branch *br) -+{ -+ return au_br_mnt(br)->mnt_sb; -+} -+ -+static inline int au_br_rdonly(struct au_branch *br) -+{ -+ return (sb_rdonly(au_br_sb(br)) -+ || !au_br_writable(br->br_perm)) -+ ? -EROFS : 0; -+} -+ -+static inline int au_br_hnotifyable(int brperm __maybe_unused) -+{ -+#ifdef CONFIG_AUFS_HNOTIFY -+ return !(brperm & AuBrPerm_RR); -+#else -+ return 0; -+#endif -+} -+ -+static inline int au_br_test_oflag(int oflag, struct au_branch *br) -+{ -+ int err, exec_flag; -+ -+ err = 0; -+ exec_flag = oflag & __FMODE_EXEC; -+ if (unlikely(exec_flag && path_noexec(&br->br_path))) -+ err = -EACCES; -+ -+ return err; -+} -+ -+static inline void au_xino_get(struct au_branch *br) -+{ -+ struct au_xino *xi; -+ -+ xi = br->br_xino; -+ if (xi) -+ kref_get(&xi->xi_kref); -+} -+ -+static inline int au_xino_count(struct au_branch *br) -+{ -+ int v; -+ struct au_xino *xi; -+ -+ v = 0; -+ xi = br->br_xino; -+ if (xi) -+ v = kref_read(&xi->xi_kref); -+ -+ return v; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* branch.c */ -+struct au_sbinfo; -+void au_br_free(struct au_sbinfo *sinfo); -+int au_br_index(struct super_block *sb, aufs_bindex_t br_id); -+struct au_opt_add; -+int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount); -+struct au_opt_del; -+int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount); -+long au_ibusy_ioctl(struct file *file, unsigned long arg); -+#ifdef CONFIG_COMPAT -+long au_ibusy_compat_ioctl(struct file *file, unsigned long arg); -+#endif -+struct au_opt_mod; -+int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount, -+ int *do_refresh); -+struct aufs_stfs; -+int au_br_stfs(struct au_branch *br, struct aufs_stfs *stfs); -+ -+/* xino.c */ -+static const loff_t au_loff_max = LLONG_MAX; -+ -+aufs_bindex_t au_xi_root(struct super_block *sb, struct dentry *dentry); -+struct file *au_xino_create(struct super_block *sb, char *fpath, int silent, -+ int wbrtop); -+struct file *au_xino_create2(struct super_block *sb, struct path *base, -+ struct file *copy_src); -+struct au_xi_new { -+ struct au_xino *xi; /* switch between xino and xigen */ -+ int idx; -+ struct path *base; -+ struct file *copy_src; -+}; -+struct file *au_xi_new(struct super_block *sb, struct au_xi_new *xinew); -+ -+int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, -+ ino_t *ino); -+int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, -+ ino_t ino); -+ssize_t xino_fread(vfs_readf_t func, struct file *file, void *buf, size_t size, -+ loff_t *pos); -+ssize_t xino_fwrite(vfs_writef_t func, struct file *file, void *buf, -+ size_t size, loff_t *pos); -+ -+int au_xib_trunc(struct super_block *sb); -+int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex, int idx_begin); -+ -+struct au_xino *au_xino_alloc(unsigned int nfile); -+int au_xino_put(struct au_branch *br); -+struct file *au_xino_file1(struct au_xino *xi); -+ -+struct au_opt_xino; -+void au_xino_clr(struct super_block *sb); -+int au_xino_set(struct super_block *sb, struct au_opt_xino *xiopt, int remount); -+struct file *au_xino_def(struct super_block *sb); -+int au_xino_init_br(struct super_block *sb, struct au_branch *br, ino_t hino, -+ struct path *base); -+ -+ino_t au_xino_new_ino(struct super_block *sb); -+void au_xino_delete_inode(struct inode *inode, const int unlinked); -+ -+void au_xinondir_leave(struct super_block *sb, aufs_bindex_t bindex, -+ ino_t h_ino, int idx); -+int au_xinondir_enter(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, -+ int *idx); -+ -+int au_xino_path(struct seq_file *seq, struct file *file); -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* @idx is signed to accept -1 meaning the first file */ -+static inline struct file *au_xino_file(struct au_xino *xi, int idx) -+{ -+ struct file *file; -+ -+ file = NULL; -+ if (!xi) -+ goto out; -+ -+ if (idx >= 0) { -+ if (idx < xi->xi_nfile) -+ file = xi->xi_file[idx]; -+ } else -+ file = au_xino_file1(xi); -+ -+out: -+ return file; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* Superblock to branch */ -+static inline -+aufs_bindex_t au_sbr_id(struct super_block *sb, aufs_bindex_t bindex) -+{ -+ return au_sbr(sb, bindex)->br_id; -+} -+ -+static inline -+struct vfsmount *au_sbr_mnt(struct super_block *sb, aufs_bindex_t bindex) -+{ -+ return au_br_mnt(au_sbr(sb, bindex)); -+} -+ -+static inline -+struct super_block *au_sbr_sb(struct super_block *sb, aufs_bindex_t bindex) -+{ -+ return au_br_sb(au_sbr(sb, bindex)); -+} -+ -+static inline int au_sbr_perm(struct super_block *sb, aufs_bindex_t bindex) -+{ -+ return au_sbr(sb, bindex)->br_perm; -+} -+ -+static inline int au_sbr_whable(struct super_block *sb, aufs_bindex_t bindex) -+{ -+ return au_br_whable(au_sbr_perm(sb, bindex)); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+#define wbr_wh_read_lock(wbr) au_rw_read_lock(&(wbr)->wbr_wh_rwsem) -+#define wbr_wh_write_lock(wbr) au_rw_write_lock(&(wbr)->wbr_wh_rwsem) -+#define wbr_wh_read_trylock(wbr) au_rw_read_trylock(&(wbr)->wbr_wh_rwsem) -+#define wbr_wh_write_trylock(wbr) au_rw_write_trylock(&(wbr)->wbr_wh_rwsem) -+/* -+#define wbr_wh_read_trylock_nested(wbr) \ -+ au_rw_read_trylock_nested(&(wbr)->wbr_wh_rwsem) -+#define wbr_wh_write_trylock_nested(wbr) \ -+ au_rw_write_trylock_nested(&(wbr)->wbr_wh_rwsem) -+*/ -+ -+#define wbr_wh_read_unlock(wbr) au_rw_read_unlock(&(wbr)->wbr_wh_rwsem) -+#define wbr_wh_write_unlock(wbr) au_rw_write_unlock(&(wbr)->wbr_wh_rwsem) -+#define wbr_wh_downgrade_lock(wbr) au_rw_dgrade_lock(&(wbr)->wbr_wh_rwsem) -+ -+#define WbrWhMustNoWaiters(wbr) AuRwMustNoWaiters(&(wbr)->wbr_wh_rwsem) -+#define WbrWhMustAnyLock(wbr) AuRwMustAnyLock(&(wbr)->wbr_wh_rwsem) -+#define WbrWhMustWriteLock(wbr) AuRwMustWriteLock(&(wbr)->wbr_wh_rwsem) -+ -+/* ---------------------------------------------------------------------- */ -+ -+#ifdef CONFIG_AUFS_FHSM -+static inline void au_br_fhsm_init(struct au_br_fhsm *brfhsm) -+{ -+ mutex_init(&brfhsm->bf_lock); -+ brfhsm->bf_jiffy = 0; -+ brfhsm->bf_readable = 0; -+} -+ -+static inline void au_br_fhsm_fin(struct au_br_fhsm *brfhsm) -+{ -+ mutex_destroy(&brfhsm->bf_lock); -+} -+#else -+AuStubVoid(au_br_fhsm_init, struct au_br_fhsm *brfhsm) -+AuStubVoid(au_br_fhsm_fin, struct au_br_fhsm *brfhsm) -+#endif -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_BRANCH_H__ */ -diff -Nurp linux-5.10-rc6/fs/aufs/cpup.c linux-5.10-rc6.aufs/fs/aufs/cpup.c ---- linux-5.10-rc6/fs/aufs/cpup.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/cpup.c 2020-12-02 21:19:51.880036698 +0200 -@@ -0,0 +1,1445 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * copy-up functions, see wbr_policy.c for copy-down -+ */ -+ -+#include -+#include -+#include -+#include "aufs.h" -+ -+void au_cpup_attr_flags(struct inode *dst, unsigned int iflags) -+{ -+ const unsigned int mask = S_DEAD | S_SWAPFILE | S_PRIVATE -+ | S_NOATIME | S_NOCMTIME | S_AUTOMOUNT; -+ -+ BUILD_BUG_ON(sizeof(iflags) != sizeof(dst->i_flags)); -+ -+ dst->i_flags |= iflags & ~mask; -+ if (au_test_fs_notime(dst->i_sb)) -+ dst->i_flags |= S_NOATIME | S_NOCMTIME; -+} -+ -+void au_cpup_attr_timesizes(struct inode *inode) -+{ -+ struct inode *h_inode; -+ -+ h_inode = au_h_iptr(inode, au_ibtop(inode)); -+ fsstack_copy_attr_times(inode, h_inode); -+ fsstack_copy_inode_size(inode, h_inode); -+} -+ -+void au_cpup_attr_nlink(struct inode *inode, int force) -+{ -+ struct inode *h_inode; -+ struct super_block *sb; -+ aufs_bindex_t bindex, bbot; -+ -+ sb = inode->i_sb; -+ bindex = au_ibtop(inode); -+ h_inode = au_h_iptr(inode, bindex); -+ if (!force -+ && !S_ISDIR(h_inode->i_mode) -+ && au_opt_test(au_mntflags(sb), PLINK) -+ && au_plink_test(inode)) -+ return; -+ -+ /* -+ * 0 can happen in revalidating. -+ * h_inode->i_mutex may not be held here, but it is harmless since once -+ * i_nlink reaches 0, it will never become positive except O_TMPFILE -+ * case. -+ * todo: O_TMPFILE+linkat(AT_SYMLINK_FOLLOW) bypassing aufs may cause -+ * the incorrect link count. -+ */ -+ set_nlink(inode, h_inode->i_nlink); -+ -+ /* -+ * fewer nlink makes find(1) noisy, but larger nlink doesn't. -+ * it may includes whplink directory. -+ */ -+ if (S_ISDIR(h_inode->i_mode)) { -+ bbot = au_ibbot(inode); -+ for (bindex++; bindex <= bbot; bindex++) { -+ h_inode = au_h_iptr(inode, bindex); -+ if (h_inode) -+ au_add_nlink(inode, h_inode); -+ } -+ } -+} -+ -+void au_cpup_attr_changeable(struct inode *inode) -+{ -+ struct inode *h_inode; -+ -+ h_inode = au_h_iptr(inode, au_ibtop(inode)); -+ inode->i_mode = h_inode->i_mode; -+ inode->i_uid = h_inode->i_uid; -+ inode->i_gid = h_inode->i_gid; -+ au_cpup_attr_timesizes(inode); -+ au_cpup_attr_flags(inode, h_inode->i_flags); -+} -+ -+void au_cpup_igen(struct inode *inode, struct inode *h_inode) -+{ -+ struct au_iinfo *iinfo = au_ii(inode); -+ -+ IiMustWriteLock(inode); -+ -+ iinfo->ii_higen = h_inode->i_generation; -+ iinfo->ii_hsb1 = h_inode->i_sb; -+} -+ -+void au_cpup_attr_all(struct inode *inode, int force) -+{ -+ struct inode *h_inode; -+ -+ h_inode = au_h_iptr(inode, au_ibtop(inode)); -+ au_cpup_attr_changeable(inode); -+ if (inode->i_nlink > 0) -+ au_cpup_attr_nlink(inode, force); -+ inode->i_rdev = h_inode->i_rdev; -+ inode->i_blkbits = h_inode->i_blkbits; -+ au_cpup_igen(inode, h_inode); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* Note: dt_dentry and dt_h_dentry are not dget/dput-ed */ -+ -+/* keep the timestamps of the parent dir when cpup */ -+void au_dtime_store(struct au_dtime *dt, struct dentry *dentry, -+ struct path *h_path) -+{ -+ struct inode *h_inode; -+ -+ dt->dt_dentry = dentry; -+ dt->dt_h_path = *h_path; -+ h_inode = d_inode(h_path->dentry); -+ dt->dt_atime = h_inode->i_atime; -+ dt->dt_mtime = h_inode->i_mtime; -+ /* smp_mb(); */ -+} -+ -+void au_dtime_revert(struct au_dtime *dt) -+{ -+ struct iattr attr; -+ int err; -+ -+ attr.ia_atime = dt->dt_atime; -+ attr.ia_mtime = dt->dt_mtime; -+ attr.ia_valid = ATTR_FORCE | ATTR_MTIME | ATTR_MTIME_SET -+ | ATTR_ATIME | ATTR_ATIME_SET; -+ -+ /* no delegation since this is a directory */ -+ err = vfsub_notify_change(&dt->dt_h_path, &attr, /*delegated*/NULL); -+ if (unlikely(err)) -+ pr_warn("restoring timestamps failed(%d). ignored\n", err); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* internal use only */ -+struct au_cpup_reg_attr { -+ int valid; -+ struct kstat st; -+ unsigned int iflags; /* inode->i_flags */ -+}; -+ -+static noinline_for_stack -+int cpup_iattr(struct dentry *dst, aufs_bindex_t bindex, struct dentry *h_src, -+ struct au_cpup_reg_attr *h_src_attr) -+{ -+ int err, sbits, icex; -+ unsigned int mnt_flags; -+ unsigned char verbose; -+ struct iattr ia; -+ struct path h_path; -+ struct inode *h_isrc, *h_idst; -+ struct kstat *h_st; -+ struct au_branch *br; -+ -+ h_path.dentry = au_h_dptr(dst, bindex); -+ h_idst = d_inode(h_path.dentry); -+ br = au_sbr(dst->d_sb, bindex); -+ h_path.mnt = au_br_mnt(br); -+ h_isrc = d_inode(h_src); -+ ia.ia_valid = ATTR_FORCE | ATTR_UID | ATTR_GID -+ | ATTR_ATIME | ATTR_MTIME -+ | ATTR_ATIME_SET | ATTR_MTIME_SET; -+ if (h_src_attr && h_src_attr->valid) { -+ h_st = &h_src_attr->st; -+ ia.ia_uid = h_st->uid; -+ ia.ia_gid = h_st->gid; -+ ia.ia_atime = h_st->atime; -+ ia.ia_mtime = h_st->mtime; -+ if (h_idst->i_mode != h_st->mode -+ && !S_ISLNK(h_idst->i_mode)) { -+ ia.ia_valid |= ATTR_MODE; -+ ia.ia_mode = h_st->mode; -+ } -+ sbits = !!(h_st->mode & (S_ISUID | S_ISGID)); -+ au_cpup_attr_flags(h_idst, h_src_attr->iflags); -+ } else { -+ ia.ia_uid = h_isrc->i_uid; -+ ia.ia_gid = h_isrc->i_gid; -+ ia.ia_atime = h_isrc->i_atime; -+ ia.ia_mtime = h_isrc->i_mtime; -+ if (h_idst->i_mode != h_isrc->i_mode -+ && !S_ISLNK(h_idst->i_mode)) { -+ ia.ia_valid |= ATTR_MODE; -+ ia.ia_mode = h_isrc->i_mode; -+ } -+ sbits = !!(h_isrc->i_mode & (S_ISUID | S_ISGID)); -+ au_cpup_attr_flags(h_idst, h_isrc->i_flags); -+ } -+ /* no delegation since it is just created */ -+ err = vfsub_notify_change(&h_path, &ia, /*delegated*/NULL); -+ -+ /* is this nfs only? */ -+ if (!err && sbits && au_test_nfs(h_path.dentry->d_sb)) { -+ ia.ia_valid = ATTR_FORCE | ATTR_MODE; -+ ia.ia_mode = h_isrc->i_mode; -+ err = vfsub_notify_change(&h_path, &ia, /*delegated*/NULL); -+ } -+ -+ icex = br->br_perm & AuBrAttr_ICEX; -+ if (!err) { -+ mnt_flags = au_mntflags(dst->d_sb); -+ verbose = !!au_opt_test(mnt_flags, VERBOSE); -+ err = au_cpup_xattr(h_path.dentry, h_src, icex, verbose); -+ } -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int au_do_copy_file(struct file *dst, struct file *src, loff_t len, -+ char *buf, unsigned long blksize) -+{ -+ int err; -+ size_t sz, rbytes, wbytes; -+ unsigned char all_zero; -+ char *p, *zp; -+ struct inode *h_inode; -+ /* reduce stack usage */ -+ struct iattr *ia; -+ -+ zp = page_address(ZERO_PAGE(0)); -+ if (unlikely(!zp)) -+ return -ENOMEM; /* possible? */ -+ -+ err = 0; -+ all_zero = 0; -+ while (len) { -+ AuDbg("len %lld\n", len); -+ sz = blksize; -+ if (len < blksize) -+ sz = len; -+ -+ rbytes = 0; -+ /* todo: signal_pending? */ -+ while (!rbytes || err == -EAGAIN || err == -EINTR) { -+ rbytes = vfsub_read_k(src, buf, sz, &src->f_pos); -+ err = rbytes; -+ } -+ if (unlikely(err < 0)) -+ break; -+ -+ all_zero = 0; -+ if (len >= rbytes && rbytes == blksize) -+ all_zero = !memcmp(buf, zp, rbytes); -+ if (!all_zero) { -+ wbytes = rbytes; -+ p = buf; -+ while (wbytes) { -+ size_t b; -+ -+ b = vfsub_write_k(dst, p, wbytes, &dst->f_pos); -+ err = b; -+ /* todo: signal_pending? */ -+ if (unlikely(err == -EAGAIN || err == -EINTR)) -+ continue; -+ if (unlikely(err < 0)) -+ break; -+ wbytes -= b; -+ p += b; -+ } -+ if (unlikely(err < 0)) -+ break; -+ } else { -+ loff_t res; -+ -+ AuLabel(hole); -+ res = vfsub_llseek(dst, rbytes, SEEK_CUR); -+ err = res; -+ if (unlikely(res < 0)) -+ break; -+ } -+ len -= rbytes; -+ err = 0; -+ } -+ -+ /* the last block may be a hole */ -+ if (!err && all_zero) { -+ AuLabel(last hole); -+ -+ err = 1; -+ if (au_test_nfs(dst->f_path.dentry->d_sb)) { -+ /* nfs requires this step to make last hole */ -+ /* is this only nfs? */ -+ do { -+ /* todo: signal_pending? */ -+ err = vfsub_write_k(dst, "\0", 1, &dst->f_pos); -+ } while (err == -EAGAIN || err == -EINTR); -+ if (err == 1) -+ dst->f_pos--; -+ } -+ -+ if (err == 1) { -+ ia = (void *)buf; -+ ia->ia_size = dst->f_pos; -+ ia->ia_valid = ATTR_SIZE | ATTR_FILE; -+ ia->ia_file = dst; -+ h_inode = file_inode(dst); -+ inode_lock_nested(h_inode, AuLsc_I_CHILD2); -+ /* no delegation since it is just created */ -+ err = vfsub_notify_change(&dst->f_path, ia, -+ /*delegated*/NULL); -+ inode_unlock(h_inode); -+ } -+ } -+ -+ return err; -+} -+ -+int au_copy_file(struct file *dst, struct file *src, loff_t len) -+{ -+ int err; -+ unsigned long blksize; -+ unsigned char do_kfree; -+ char *buf; -+ struct super_block *h_sb; -+ -+ err = -ENOMEM; -+ h_sb = file_inode(dst)->i_sb; -+ blksize = h_sb->s_blocksize; -+ if (!blksize || PAGE_SIZE < blksize) -+ blksize = PAGE_SIZE; -+ AuDbg("blksize %lu\n", blksize); -+ do_kfree = (blksize != PAGE_SIZE && blksize >= sizeof(struct iattr *)); -+ if (do_kfree) -+ buf = kmalloc(blksize, GFP_NOFS); -+ else -+ buf = (void *)__get_free_page(GFP_NOFS); -+ if (unlikely(!buf)) -+ goto out; -+ -+ if (len > (1 << 22)) -+ AuDbg("copying a large file %lld\n", (long long)len); -+ -+ src->f_pos = 0; -+ dst->f_pos = 0; -+ err = au_do_copy_file(dst, src, len, buf, blksize); -+ if (do_kfree) { -+ AuDebugOn(!au_kfree_do_sz_test(blksize)); -+ au_kfree_do_rcu(buf); -+ } else -+ free_page((unsigned long)buf); -+ -+out: -+ return err; -+} -+ -+static int au_do_copy(struct file *dst, struct file *src, loff_t len) -+{ -+ int err; -+ struct super_block *h_src_sb; -+ struct inode *h_src_inode; -+ -+ h_src_inode = file_inode(src); -+ h_src_sb = h_src_inode->i_sb; -+ -+ /* XFS acquires inode_lock */ -+ if (!au_test_xfs(h_src_sb)) -+ err = au_copy_file(dst, src, len); -+ else { -+ inode_unlock_shared(h_src_inode); -+ err = au_copy_file(dst, src, len); -+ inode_lock_shared_nested(h_src_inode, AuLsc_I_CHILD); -+ } -+ -+ return err; -+} -+ -+static int au_clone_or_copy(struct file *dst, struct file *src, loff_t len) -+{ -+ int err; -+ loff_t lo; -+ struct super_block *h_src_sb; -+ struct inode *h_src_inode; -+ -+ h_src_inode = file_inode(src); -+ h_src_sb = h_src_inode->i_sb; -+ if (h_src_sb != file_inode(dst)->i_sb -+ || !dst->f_op->remap_file_range) { -+ err = au_do_copy(dst, src, len); -+ goto out; -+ } -+ -+ if (!au_test_nfs(h_src_sb)) { -+ inode_unlock_shared(h_src_inode); -+ lo = vfsub_clone_file_range(src, dst, len); -+ inode_lock_shared_nested(h_src_inode, AuLsc_I_CHILD); -+ } else -+ lo = vfsub_clone_file_range(src, dst, len); -+ if (lo == len) { -+ err = 0; -+ goto out; /* success */ -+ } else if (lo >= 0) -+ /* todo: possible? */ -+ /* paritially succeeded */ -+ AuDbg("lo %lld, len %lld. Retrying.\n", lo, len); -+ else if (lo != -EOPNOTSUPP) { -+ /* older XFS has a condition in cloning */ -+ err = lo; -+ goto out; -+ } -+ -+ /* the backend fs on NFS may not support cloning */ -+ err = au_do_copy(dst, src, len); -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+/* -+ * to support a sparse file which is opened with O_APPEND, -+ * we need to close the file. -+ */ -+static int au_cp_regular(struct au_cp_generic *cpg) -+{ -+ int err, i; -+ enum { SRC, DST }; -+ struct { -+ aufs_bindex_t bindex; -+ unsigned int flags; -+ struct dentry *dentry; -+ int force_wr; -+ struct file *file; -+ } *f, file[] = { -+ { -+ .bindex = cpg->bsrc, -+ .flags = O_RDONLY | O_NOATIME | O_LARGEFILE, -+ }, -+ { -+ .bindex = cpg->bdst, -+ .flags = O_WRONLY | O_NOATIME | O_LARGEFILE, -+ .force_wr = !!au_ftest_cpup(cpg->flags, RWDST), -+ } -+ }; -+ struct au_branch *br; -+ struct super_block *sb, *h_src_sb; -+ struct inode *h_src_inode; -+ struct task_struct *tsk = current; -+ -+ /* bsrc branch can be ro/rw. */ -+ sb = cpg->dentry->d_sb; -+ f = file; -+ for (i = 0; i < 2; i++, f++) { -+ f->dentry = au_h_dptr(cpg->dentry, f->bindex); -+ f->file = au_h_open(cpg->dentry, f->bindex, f->flags, -+ /*file*/NULL, f->force_wr); -+ if (IS_ERR(f->file)) { -+ err = PTR_ERR(f->file); -+ if (i == SRC) -+ goto out; -+ else -+ goto out_src; -+ } -+ } -+ -+ /* try stopping to update while we copyup */ -+ h_src_inode = d_inode(file[SRC].dentry); -+ h_src_sb = h_src_inode->i_sb; -+ if (!au_test_nfs(h_src_sb)) -+ IMustLock(h_src_inode); -+ err = au_clone_or_copy(file[DST].file, file[SRC].file, cpg->len); -+ -+ /* i wonder if we had O_NO_DELAY_FPUT flag */ -+ if (tsk->flags & PF_KTHREAD) -+ __fput_sync(file[DST].file); -+ else { -+ /* it happened actually */ -+ fput(file[DST].file); -+ /* -+ * too bad. -+ * we have to call both since we don't know which place the file -+ * was added to. -+ */ -+ task_work_run(); -+ flush_delayed_fput(); -+ } -+ br = au_sbr(sb, file[DST].bindex); -+ au_lcnt_dec(&br->br_nfiles); -+ -+out_src: -+ fput(file[SRC].file); -+ br = au_sbr(sb, file[SRC].bindex); -+ au_lcnt_dec(&br->br_nfiles); -+out: -+ return err; -+} -+ -+static int au_do_cpup_regular(struct au_cp_generic *cpg, -+ struct au_cpup_reg_attr *h_src_attr) -+{ -+ int err, rerr; -+ loff_t l; -+ struct path h_path; -+ struct inode *h_src_inode, *h_dst_inode; -+ -+ err = 0; -+ h_src_inode = au_h_iptr(d_inode(cpg->dentry), cpg->bsrc); -+ l = i_size_read(h_src_inode); -+ if (cpg->len == -1 || l < cpg->len) -+ cpg->len = l; -+ if (cpg->len) { -+ /* try stopping to update while we are referencing */ -+ inode_lock_shared_nested(h_src_inode, AuLsc_I_CHILD); -+ au_pin_hdir_unlock(cpg->pin); -+ -+ h_path.dentry = au_h_dptr(cpg->dentry, cpg->bsrc); -+ h_path.mnt = au_sbr_mnt(cpg->dentry->d_sb, cpg->bsrc); -+ h_src_attr->iflags = h_src_inode->i_flags; -+ if (!au_test_nfs(h_src_inode->i_sb)) -+ err = vfsub_getattr(&h_path, &h_src_attr->st); -+ else { -+ inode_unlock_shared(h_src_inode); -+ err = vfsub_getattr(&h_path, &h_src_attr->st); -+ inode_lock_shared_nested(h_src_inode, AuLsc_I_CHILD); -+ } -+ if (unlikely(err)) { -+ inode_unlock_shared(h_src_inode); -+ goto out; -+ } -+ h_src_attr->valid = 1; -+ if (!au_test_nfs(h_src_inode->i_sb)) { -+ err = au_cp_regular(cpg); -+ inode_unlock_shared(h_src_inode); -+ } else { -+ inode_unlock_shared(h_src_inode); -+ err = au_cp_regular(cpg); -+ } -+ rerr = au_pin_hdir_relock(cpg->pin); -+ if (!err && rerr) -+ err = rerr; -+ } -+ if (!err && (h_src_inode->i_state & I_LINKABLE)) { -+ h_path.dentry = au_h_dptr(cpg->dentry, cpg->bdst); -+ h_dst_inode = d_inode(h_path.dentry); -+ spin_lock(&h_dst_inode->i_lock); -+ h_dst_inode->i_state |= I_LINKABLE; -+ spin_unlock(&h_dst_inode->i_lock); -+ } -+ -+out: -+ return err; -+} -+ -+static int au_do_cpup_symlink(struct path *h_path, struct dentry *h_src, -+ struct inode *h_dir) -+{ -+ int err, symlen; -+ mm_segment_t old_fs; -+ union { -+ char *k; -+ char __user *u; -+ } sym; -+ -+ err = -ENOMEM; -+ sym.k = (void *)__get_free_page(GFP_NOFS); -+ if (unlikely(!sym.k)) -+ goto out; -+ -+ /* unnecessary to support mmap_sem since symlink is not mmap-able */ -+ old_fs = get_fs(); -+ set_fs(KERNEL_DS); -+ symlen = vfs_readlink(h_src, sym.u, PATH_MAX); -+ err = symlen; -+ set_fs(old_fs); -+ -+ if (symlen > 0) { -+ sym.k[symlen] = 0; -+ err = vfsub_symlink(h_dir, h_path, sym.k); -+ } -+ free_page((unsigned long)sym.k); -+ -+out: -+ return err; -+} -+ -+/* -+ * regardless 'acl' option, reset all ACL. -+ * All ACL will be copied up later from the original entry on the lower branch. -+ */ -+static int au_reset_acl(struct inode *h_dir, struct path *h_path, umode_t mode) -+{ -+ int err; -+ struct dentry *h_dentry; -+ struct inode *h_inode; -+ -+ h_dentry = h_path->dentry; -+ h_inode = d_inode(h_dentry); -+ /* forget_all_cached_acls(h_inode)); */ -+ err = vfsub_removexattr(h_dentry, XATTR_NAME_POSIX_ACL_ACCESS); -+ AuTraceErr(err); -+ if (err == -EOPNOTSUPP) -+ err = 0; -+ if (!err) -+ err = vfsub_acl_chmod(h_inode, mode); -+ -+ AuTraceErr(err); -+ return err; -+} -+ -+static int au_do_cpup_dir(struct au_cp_generic *cpg, struct dentry *dst_parent, -+ struct inode *h_dir, struct path *h_path) -+{ -+ int err; -+ struct inode *dir, *inode; -+ -+ err = vfsub_removexattr(h_path->dentry, XATTR_NAME_POSIX_ACL_DEFAULT); -+ AuTraceErr(err); -+ if (err == -EOPNOTSUPP) -+ err = 0; -+ if (unlikely(err)) -+ goto out; -+ -+ /* -+ * strange behaviour from the users view, -+ * particularly setattr case -+ */ -+ dir = d_inode(dst_parent); -+ if (au_ibtop(dir) == cpg->bdst) -+ au_cpup_attr_nlink(dir, /*force*/1); -+ inode = d_inode(cpg->dentry); -+ au_cpup_attr_nlink(inode, /*force*/1); -+ -+out: -+ return err; -+} -+ -+static noinline_for_stack -+int cpup_entry(struct au_cp_generic *cpg, struct dentry *dst_parent, -+ struct au_cpup_reg_attr *h_src_attr) -+{ -+ int err; -+ umode_t mode; -+ unsigned int mnt_flags; -+ unsigned char isdir, isreg, force; -+ const unsigned char do_dt = !!au_ftest_cpup(cpg->flags, DTIME); -+ struct au_dtime dt; -+ struct path h_path; -+ struct dentry *h_src, *h_dst, *h_parent; -+ struct inode *h_inode, *h_dir; -+ struct super_block *sb; -+ -+ /* bsrc branch can be ro/rw. */ -+ h_src = au_h_dptr(cpg->dentry, cpg->bsrc); -+ h_inode = d_inode(h_src); -+ AuDebugOn(h_inode != au_h_iptr(d_inode(cpg->dentry), cpg->bsrc)); -+ -+ /* try stopping to be referenced while we are creating */ -+ h_dst = au_h_dptr(cpg->dentry, cpg->bdst); -+ if (au_ftest_cpup(cpg->flags, RENAME)) -+ AuDebugOn(strncmp(h_dst->d_name.name, AUFS_WH_PFX, -+ AUFS_WH_PFX_LEN)); -+ h_parent = h_dst->d_parent; /* dir inode is locked */ -+ h_dir = d_inode(h_parent); -+ IMustLock(h_dir); -+ AuDebugOn(h_parent != h_dst->d_parent); -+ -+ sb = cpg->dentry->d_sb; -+ h_path.mnt = au_sbr_mnt(sb, cpg->bdst); -+ if (do_dt) { -+ h_path.dentry = h_parent; -+ au_dtime_store(&dt, dst_parent, &h_path); -+ } -+ h_path.dentry = h_dst; -+ -+ isreg = 0; -+ isdir = 0; -+ mode = h_inode->i_mode; -+ switch (mode & S_IFMT) { -+ case S_IFREG: -+ isreg = 1; -+ err = vfsub_create(h_dir, &h_path, 0600, /*want_excl*/true); -+ if (!err) -+ err = au_do_cpup_regular(cpg, h_src_attr); -+ break; -+ case S_IFDIR: -+ isdir = 1; -+ err = vfsub_mkdir(h_dir, &h_path, mode); -+ if (!err) -+ err = au_do_cpup_dir(cpg, dst_parent, h_dir, &h_path); -+ break; -+ case S_IFLNK: -+ err = au_do_cpup_symlink(&h_path, h_src, h_dir); -+ break; -+ case S_IFCHR: -+ case S_IFBLK: -+ AuDebugOn(!capable(CAP_MKNOD)); -+ /*FALLTHROUGH*/ -+ case S_IFIFO: -+ case S_IFSOCK: -+ err = vfsub_mknod(h_dir, &h_path, mode, h_inode->i_rdev); -+ break; -+ default: -+ AuIOErr("Unknown inode type 0%o\n", mode); -+ err = -EIO; -+ } -+ if (!err) -+ err = au_reset_acl(h_dir, &h_path, mode); -+ -+ mnt_flags = au_mntflags(sb); -+ if (!au_opt_test(mnt_flags, UDBA_NONE) -+ && !isdir -+ && au_opt_test(mnt_flags, XINO) -+ && (h_inode->i_nlink == 1 -+ || (h_inode->i_state & I_LINKABLE)) -+ /* todo: unnecessary? */ -+ /* && d_inode(cpg->dentry)->i_nlink == 1 */ -+ && cpg->bdst < cpg->bsrc -+ && !au_ftest_cpup(cpg->flags, KEEPLINO)) -+ au_xino_write(sb, cpg->bsrc, h_inode->i_ino, /*ino*/0); -+ /* ignore this error */ -+ -+ if (!err) { -+ force = 0; -+ if (isreg) { -+ force = !!cpg->len; -+ if (cpg->len == -1) -+ force = !!i_size_read(h_inode); -+ } -+ au_fhsm_wrote(sb, cpg->bdst, force); -+ } -+ -+ if (do_dt) -+ au_dtime_revert(&dt); -+ return err; -+} -+ -+static int au_do_ren_after_cpup(struct au_cp_generic *cpg, struct path *h_path) -+{ -+ int err; -+ struct dentry *dentry, *h_dentry, *h_parent, *parent; -+ struct inode *h_dir; -+ aufs_bindex_t bdst; -+ -+ dentry = cpg->dentry; -+ bdst = cpg->bdst; -+ h_dentry = au_h_dptr(dentry, bdst); -+ if (!au_ftest_cpup(cpg->flags, OVERWRITE)) { -+ dget(h_dentry); -+ au_set_h_dptr(dentry, bdst, NULL); -+ err = au_lkup_neg(dentry, bdst, /*wh*/0); -+ if (!err) -+ h_path->dentry = dget(au_h_dptr(dentry, bdst)); -+ au_set_h_dptr(dentry, bdst, h_dentry); -+ } else { -+ err = 0; -+ parent = dget_parent(dentry); -+ h_parent = au_h_dptr(parent, bdst); -+ dput(parent); -+ h_path->dentry = vfsub_lkup_one(&dentry->d_name, h_parent); -+ if (IS_ERR(h_path->dentry)) -+ err = PTR_ERR(h_path->dentry); -+ } -+ if (unlikely(err)) -+ goto out; -+ -+ h_parent = h_dentry->d_parent; /* dir inode is locked */ -+ h_dir = d_inode(h_parent); -+ IMustLock(h_dir); -+ AuDbg("%pd %pd\n", h_dentry, h_path->dentry); -+ /* no delegation since it is just created */ -+ err = vfsub_rename(h_dir, h_dentry, h_dir, h_path, /*delegated*/NULL, -+ /*flags*/0); -+ dput(h_path->dentry); -+ -+out: -+ return err; -+} -+ -+/* -+ * copyup the @dentry from @bsrc to @bdst. -+ * the caller must set the both of lower dentries. -+ * @len is for truncating when it is -1 copyup the entire file. -+ * in link/rename cases, @dst_parent may be different from the real one. -+ * basic->bsrc can be larger than basic->bdst. -+ * aufs doesn't touch the credential so -+ * security_inode_copy_up{,_xattr}() are unnecessary. -+ */ -+static int au_cpup_single(struct au_cp_generic *cpg, struct dentry *dst_parent) -+{ -+ int err, rerr; -+ aufs_bindex_t old_ibtop; -+ unsigned char isdir, plink; -+ struct dentry *h_src, *h_dst, *h_parent; -+ struct inode *dst_inode, *h_dir, *inode, *delegated, *src_inode; -+ struct super_block *sb; -+ struct au_branch *br; -+ /* to reduce stack size */ -+ struct { -+ struct au_dtime dt; -+ struct path h_path; -+ struct au_cpup_reg_attr h_src_attr; -+ } *a; -+ -+ err = -ENOMEM; -+ a = kmalloc(sizeof(*a), GFP_NOFS); -+ if (unlikely(!a)) -+ goto out; -+ a->h_src_attr.valid = 0; -+ -+ sb = cpg->dentry->d_sb; -+ br = au_sbr(sb, cpg->bdst); -+ a->h_path.mnt = au_br_mnt(br); -+ h_dst = au_h_dptr(cpg->dentry, cpg->bdst); -+ h_parent = h_dst->d_parent; /* dir inode is locked */ -+ h_dir = d_inode(h_parent); -+ IMustLock(h_dir); -+ -+ h_src = au_h_dptr(cpg->dentry, cpg->bsrc); -+ inode = d_inode(cpg->dentry); -+ -+ if (!dst_parent) -+ dst_parent = dget_parent(cpg->dentry); -+ else -+ dget(dst_parent); -+ -+ plink = !!au_opt_test(au_mntflags(sb), PLINK); -+ dst_inode = au_h_iptr(inode, cpg->bdst); -+ if (dst_inode) { -+ if (unlikely(!plink)) { -+ err = -EIO; -+ AuIOErr("hi%lu(i%lu) exists on b%d " -+ "but plink is disabled\n", -+ dst_inode->i_ino, inode->i_ino, cpg->bdst); -+ goto out_parent; -+ } -+ -+ if (dst_inode->i_nlink) { -+ const int do_dt = au_ftest_cpup(cpg->flags, DTIME); -+ -+ h_src = au_plink_lkup(inode, cpg->bdst); -+ err = PTR_ERR(h_src); -+ if (IS_ERR(h_src)) -+ goto out_parent; -+ if (unlikely(d_is_negative(h_src))) { -+ err = -EIO; -+ AuIOErr("i%lu exists on b%d " -+ "but not pseudo-linked\n", -+ inode->i_ino, cpg->bdst); -+ dput(h_src); -+ goto out_parent; -+ } -+ -+ if (do_dt) { -+ a->h_path.dentry = h_parent; -+ au_dtime_store(&a->dt, dst_parent, &a->h_path); -+ } -+ -+ a->h_path.dentry = h_dst; -+ delegated = NULL; -+ err = vfsub_link(h_src, h_dir, &a->h_path, &delegated); -+ if (!err && au_ftest_cpup(cpg->flags, RENAME)) -+ err = au_do_ren_after_cpup(cpg, &a->h_path); -+ if (do_dt) -+ au_dtime_revert(&a->dt); -+ if (unlikely(err == -EWOULDBLOCK)) { -+ pr_warn("cannot retry for NFSv4 delegation" -+ " for an internal link\n"); -+ iput(delegated); -+ } -+ dput(h_src); -+ goto out_parent; -+ } else -+ /* todo: cpup_wh_file? */ -+ /* udba work */ -+ au_update_ibrange(inode, /*do_put_zero*/1); -+ } -+ -+ isdir = S_ISDIR(inode->i_mode); -+ old_ibtop = au_ibtop(inode); -+ err = cpup_entry(cpg, dst_parent, &a->h_src_attr); -+ if (unlikely(err)) -+ goto out_rev; -+ dst_inode = d_inode(h_dst); -+ inode_lock_nested(dst_inode, AuLsc_I_CHILD2); -+ /* todo: necessary? */ -+ /* au_pin_hdir_unlock(cpg->pin); */ -+ -+ err = cpup_iattr(cpg->dentry, cpg->bdst, h_src, &a->h_src_attr); -+ if (unlikely(err)) { -+ /* todo: necessary? */ -+ /* au_pin_hdir_relock(cpg->pin); */ /* ignore an error */ -+ inode_unlock(dst_inode); -+ goto out_rev; -+ } -+ -+ if (cpg->bdst < old_ibtop) { -+ if (S_ISREG(inode->i_mode)) { -+ err = au_dy_iaop(inode, cpg->bdst, dst_inode); -+ if (unlikely(err)) { -+ /* ignore an error */ -+ /* au_pin_hdir_relock(cpg->pin); */ -+ inode_unlock(dst_inode); -+ goto out_rev; -+ } -+ } -+ au_set_ibtop(inode, cpg->bdst); -+ } else -+ au_set_ibbot(inode, cpg->bdst); -+ au_set_h_iptr(inode, cpg->bdst, au_igrab(dst_inode), -+ au_hi_flags(inode, isdir)); -+ -+ /* todo: necessary? */ -+ /* err = au_pin_hdir_relock(cpg->pin); */ -+ inode_unlock(dst_inode); -+ if (unlikely(err)) -+ goto out_rev; -+ -+ src_inode = d_inode(h_src); -+ if (!isdir -+ && (src_inode->i_nlink > 1 -+ || src_inode->i_state & I_LINKABLE) -+ && plink) -+ au_plink_append(inode, cpg->bdst, h_dst); -+ -+ if (au_ftest_cpup(cpg->flags, RENAME)) { -+ a->h_path.dentry = h_dst; -+ err = au_do_ren_after_cpup(cpg, &a->h_path); -+ } -+ if (!err) -+ goto out_parent; /* success */ -+ -+ /* revert */ -+out_rev: -+ a->h_path.dentry = h_parent; -+ au_dtime_store(&a->dt, dst_parent, &a->h_path); -+ a->h_path.dentry = h_dst; -+ rerr = 0; -+ if (d_is_positive(h_dst)) { -+ if (!isdir) { -+ /* no delegation since it is just created */ -+ rerr = vfsub_unlink(h_dir, &a->h_path, -+ /*delegated*/NULL, /*force*/0); -+ } else -+ rerr = vfsub_rmdir(h_dir, &a->h_path); -+ } -+ au_dtime_revert(&a->dt); -+ if (rerr) { -+ AuIOErr("failed removing broken entry(%d, %d)\n", err, rerr); -+ err = -EIO; -+ } -+out_parent: -+ dput(dst_parent); -+ au_kfree_rcu(a); -+out: -+ return err; -+} -+ -+#if 0 /* reserved */ -+struct au_cpup_single_args { -+ int *errp; -+ struct au_cp_generic *cpg; -+ struct dentry *dst_parent; -+}; -+ -+static void au_call_cpup_single(void *args) -+{ -+ struct au_cpup_single_args *a = args; -+ -+ au_pin_hdir_acquire_nest(a->cpg->pin); -+ *a->errp = au_cpup_single(a->cpg, a->dst_parent); -+ au_pin_hdir_release(a->cpg->pin); -+} -+#endif -+ -+/* -+ * prevent SIGXFSZ in copy-up. -+ * testing CAP_MKNOD is for generic fs, -+ * but CAP_FSETID is for xfs only, currently. -+ */ -+static int au_cpup_sio_test(struct au_pin *pin, umode_t mode) -+{ -+ int do_sio; -+ struct super_block *sb; -+ struct inode *h_dir; -+ -+ do_sio = 0; -+ sb = au_pinned_parent(pin)->d_sb; -+ if (!au_wkq_test() -+ && (!au_sbi(sb)->si_plink_maint_pid -+ || au_plink_maint(sb, AuLock_NOPLM))) { -+ switch (mode & S_IFMT) { -+ case S_IFREG: -+ /* no condition about RLIMIT_FSIZE and the file size */ -+ do_sio = 1; -+ break; -+ case S_IFCHR: -+ case S_IFBLK: -+ do_sio = !capable(CAP_MKNOD); -+ break; -+ } -+ if (!do_sio) -+ do_sio = ((mode & (S_ISUID | S_ISGID)) -+ && !capable(CAP_FSETID)); -+ /* this workaround may be removed in the future */ -+ if (!do_sio) { -+ h_dir = au_pinned_h_dir(pin); -+ do_sio = h_dir->i_mode & S_ISVTX; -+ } -+ } -+ -+ return do_sio; -+} -+ -+#if 0 /* reserved */ -+int au_sio_cpup_single(struct au_cp_generic *cpg, struct dentry *dst_parent) -+{ -+ int err, wkq_err; -+ struct dentry *h_dentry; -+ -+ h_dentry = au_h_dptr(cpg->dentry, cpg->bsrc); -+ if (!au_cpup_sio_test(pin, d_inode(h_dentry)->i_mode)) -+ err = au_cpup_single(cpg, dst_parent); -+ else { -+ struct au_cpup_single_args args = { -+ .errp = &err, -+ .cpg = cpg, -+ .dst_parent = dst_parent -+ }; -+ wkq_err = au_wkq_wait(au_call_cpup_single, &args); -+ if (unlikely(wkq_err)) -+ err = wkq_err; -+ } -+ -+ return err; -+} -+#endif -+ -+/* -+ * copyup the @dentry from the first active lower branch to @bdst, -+ * using au_cpup_single(). -+ */ -+static int au_cpup_simple(struct au_cp_generic *cpg) -+{ -+ int err; -+ unsigned int flags_orig; -+ struct dentry *dentry; -+ -+ AuDebugOn(cpg->bsrc < 0); -+ -+ dentry = cpg->dentry; -+ DiMustWriteLock(dentry); -+ -+ err = au_lkup_neg(dentry, cpg->bdst, /*wh*/1); -+ if (!err) { -+ flags_orig = cpg->flags; -+ au_fset_cpup(cpg->flags, RENAME); -+ err = au_cpup_single(cpg, NULL); -+ cpg->flags = flags_orig; -+ if (!err) -+ return 0; /* success */ -+ -+ /* revert */ -+ au_set_h_dptr(dentry, cpg->bdst, NULL); -+ au_set_dbtop(dentry, cpg->bsrc); -+ } -+ -+ return err; -+} -+ -+struct au_cpup_simple_args { -+ int *errp; -+ struct au_cp_generic *cpg; -+}; -+ -+static void au_call_cpup_simple(void *args) -+{ -+ struct au_cpup_simple_args *a = args; -+ -+ au_pin_hdir_acquire_nest(a->cpg->pin); -+ *a->errp = au_cpup_simple(a->cpg); -+ au_pin_hdir_release(a->cpg->pin); -+} -+ -+static int au_do_sio_cpup_simple(struct au_cp_generic *cpg) -+{ -+ int err, wkq_err; -+ struct dentry *dentry, *parent; -+ struct file *h_file; -+ struct inode *h_dir; -+ -+ dentry = cpg->dentry; -+ h_file = NULL; -+ if (au_ftest_cpup(cpg->flags, HOPEN)) { -+ AuDebugOn(cpg->bsrc < 0); -+ h_file = au_h_open_pre(dentry, cpg->bsrc, /*force_wr*/0); -+ err = PTR_ERR(h_file); -+ if (IS_ERR(h_file)) -+ goto out; -+ } -+ -+ parent = dget_parent(dentry); -+ h_dir = au_h_iptr(d_inode(parent), cpg->bdst); -+ if (!au_test_h_perm_sio(h_dir, MAY_EXEC | MAY_WRITE) -+ && !au_cpup_sio_test(cpg->pin, d_inode(dentry)->i_mode)) -+ err = au_cpup_simple(cpg); -+ else { -+ struct au_cpup_simple_args args = { -+ .errp = &err, -+ .cpg = cpg -+ }; -+ wkq_err = au_wkq_wait(au_call_cpup_simple, &args); -+ if (unlikely(wkq_err)) -+ err = wkq_err; -+ } -+ -+ dput(parent); -+ if (h_file) -+ au_h_open_post(dentry, cpg->bsrc, h_file); -+ -+out: -+ return err; -+} -+ -+int au_sio_cpup_simple(struct au_cp_generic *cpg) -+{ -+ aufs_bindex_t bsrc, bbot; -+ struct dentry *dentry, *h_dentry; -+ -+ if (cpg->bsrc < 0) { -+ dentry = cpg->dentry; -+ bbot = au_dbbot(dentry); -+ for (bsrc = cpg->bdst + 1; bsrc <= bbot; bsrc++) { -+ h_dentry = au_h_dptr(dentry, bsrc); -+ if (h_dentry) { -+ AuDebugOn(d_is_negative(h_dentry)); -+ break; -+ } -+ } -+ AuDebugOn(bsrc > bbot); -+ cpg->bsrc = bsrc; -+ } -+ AuDebugOn(cpg->bsrc <= cpg->bdst); -+ return au_do_sio_cpup_simple(cpg); -+} -+ -+int au_sio_cpdown_simple(struct au_cp_generic *cpg) -+{ -+ AuDebugOn(cpg->bdst <= cpg->bsrc); -+ return au_do_sio_cpup_simple(cpg); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * copyup the deleted file for writing. -+ */ -+static int au_do_cpup_wh(struct au_cp_generic *cpg, struct dentry *wh_dentry, -+ struct file *file) -+{ -+ int err; -+ unsigned int flags_orig; -+ aufs_bindex_t bsrc_orig; -+ struct au_dinfo *dinfo; -+ struct { -+ struct au_hdentry *hd; -+ struct dentry *h_dentry; -+ } hdst, hsrc; -+ -+ dinfo = au_di(cpg->dentry); -+ AuRwMustWriteLock(&dinfo->di_rwsem); -+ -+ bsrc_orig = cpg->bsrc; -+ cpg->bsrc = dinfo->di_btop; -+ hdst.hd = au_hdentry(dinfo, cpg->bdst); -+ hdst.h_dentry = hdst.hd->hd_dentry; -+ hdst.hd->hd_dentry = wh_dentry; -+ dinfo->di_btop = cpg->bdst; -+ -+ hsrc.h_dentry = NULL; -+ if (file) { -+ hsrc.hd = au_hdentry(dinfo, cpg->bsrc); -+ hsrc.h_dentry = hsrc.hd->hd_dentry; -+ hsrc.hd->hd_dentry = au_hf_top(file)->f_path.dentry; -+ } -+ flags_orig = cpg->flags; -+ cpg->flags = !AuCpup_DTIME; -+ err = au_cpup_single(cpg, /*h_parent*/NULL); -+ cpg->flags = flags_orig; -+ if (file) { -+ if (!err) -+ err = au_reopen_nondir(file); -+ hsrc.hd->hd_dentry = hsrc.h_dentry; -+ } -+ hdst.hd->hd_dentry = hdst.h_dentry; -+ dinfo->di_btop = cpg->bsrc; -+ cpg->bsrc = bsrc_orig; -+ -+ return err; -+} -+ -+static int au_cpup_wh(struct au_cp_generic *cpg, struct file *file) -+{ -+ int err; -+ aufs_bindex_t bdst; -+ struct au_dtime dt; -+ struct dentry *dentry, *parent, *h_parent, *wh_dentry; -+ struct au_branch *br; -+ struct path h_path; -+ -+ dentry = cpg->dentry; -+ bdst = cpg->bdst; -+ br = au_sbr(dentry->d_sb, bdst); -+ parent = dget_parent(dentry); -+ h_parent = au_h_dptr(parent, bdst); -+ wh_dentry = au_whtmp_lkup(h_parent, br, &dentry->d_name); -+ err = PTR_ERR(wh_dentry); -+ if (IS_ERR(wh_dentry)) -+ goto out; -+ -+ h_path.dentry = h_parent; -+ h_path.mnt = au_br_mnt(br); -+ au_dtime_store(&dt, parent, &h_path); -+ err = au_do_cpup_wh(cpg, wh_dentry, file); -+ if (unlikely(err)) -+ goto out_wh; -+ -+ dget(wh_dentry); -+ h_path.dentry = wh_dentry; -+ if (!d_is_dir(wh_dentry)) { -+ /* no delegation since it is just created */ -+ err = vfsub_unlink(d_inode(h_parent), &h_path, -+ /*delegated*/NULL, /*force*/0); -+ } else -+ err = vfsub_rmdir(d_inode(h_parent), &h_path); -+ if (unlikely(err)) { -+ AuIOErr("failed remove copied-up tmp file %pd(%d)\n", -+ wh_dentry, err); -+ err = -EIO; -+ } -+ au_dtime_revert(&dt); -+ au_set_hi_wh(d_inode(dentry), bdst, wh_dentry); -+ -+out_wh: -+ dput(wh_dentry); -+out: -+ dput(parent); -+ return err; -+} -+ -+struct au_cpup_wh_args { -+ int *errp; -+ struct au_cp_generic *cpg; -+ struct file *file; -+}; -+ -+static void au_call_cpup_wh(void *args) -+{ -+ struct au_cpup_wh_args *a = args; -+ -+ au_pin_hdir_acquire_nest(a->cpg->pin); -+ *a->errp = au_cpup_wh(a->cpg, a->file); -+ au_pin_hdir_release(a->cpg->pin); -+} -+ -+int au_sio_cpup_wh(struct au_cp_generic *cpg, struct file *file) -+{ -+ int err, wkq_err; -+ aufs_bindex_t bdst; -+ struct dentry *dentry, *parent, *h_orph, *h_parent; -+ struct inode *dir, *h_dir, *h_tmpdir; -+ struct au_wbr *wbr; -+ struct au_pin wh_pin, *pin_orig; -+ -+ dentry = cpg->dentry; -+ bdst = cpg->bdst; -+ parent = dget_parent(dentry); -+ dir = d_inode(parent); -+ h_orph = NULL; -+ h_parent = NULL; -+ h_dir = au_igrab(au_h_iptr(dir, bdst)); -+ h_tmpdir = h_dir; -+ pin_orig = NULL; -+ if (!h_dir->i_nlink) { -+ wbr = au_sbr(dentry->d_sb, bdst)->br_wbr; -+ h_orph = wbr->wbr_orph; -+ -+ h_parent = dget(au_h_dptr(parent, bdst)); -+ au_set_h_dptr(parent, bdst, dget(h_orph)); -+ h_tmpdir = d_inode(h_orph); -+ au_set_h_iptr(dir, bdst, au_igrab(h_tmpdir), /*flags*/0); -+ -+ inode_lock_nested(h_tmpdir, AuLsc_I_PARENT3); -+ /* todo: au_h_open_pre()? */ -+ -+ pin_orig = cpg->pin; -+ au_pin_init(&wh_pin, dentry, bdst, AuLsc_DI_PARENT, -+ AuLsc_I_PARENT3, cpg->pin->udba, AuPin_DI_LOCKED); -+ cpg->pin = &wh_pin; -+ } -+ -+ if (!au_test_h_perm_sio(h_tmpdir, MAY_EXEC | MAY_WRITE) -+ && !au_cpup_sio_test(cpg->pin, d_inode(dentry)->i_mode)) -+ err = au_cpup_wh(cpg, file); -+ else { -+ struct au_cpup_wh_args args = { -+ .errp = &err, -+ .cpg = cpg, -+ .file = file -+ }; -+ wkq_err = au_wkq_wait(au_call_cpup_wh, &args); -+ if (unlikely(wkq_err)) -+ err = wkq_err; -+ } -+ -+ if (h_orph) { -+ inode_unlock(h_tmpdir); -+ /* todo: au_h_open_post()? */ -+ au_set_h_iptr(dir, bdst, au_igrab(h_dir), /*flags*/0); -+ au_set_h_dptr(parent, bdst, h_parent); -+ AuDebugOn(!pin_orig); -+ cpg->pin = pin_orig; -+ } -+ iput(h_dir); -+ dput(parent); -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * generic routine for both of copy-up and copy-down. -+ */ -+/* cf. revalidate function in file.c */ -+int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst, -+ int (*cp)(struct dentry *dentry, aufs_bindex_t bdst, -+ struct au_pin *pin, -+ struct dentry *h_parent, void *arg), -+ void *arg) -+{ -+ int err; -+ struct au_pin pin; -+ struct dentry *d, *parent, *h_parent, *real_parent, *h_dentry; -+ -+ err = 0; -+ parent = dget_parent(dentry); -+ if (IS_ROOT(parent)) -+ goto out; -+ -+ au_pin_init(&pin, dentry, bdst, AuLsc_DI_PARENT2, AuLsc_I_PARENT2, -+ au_opt_udba(dentry->d_sb), AuPin_MNT_WRITE); -+ -+ /* do not use au_dpage */ -+ real_parent = parent; -+ while (1) { -+ dput(parent); -+ parent = dget_parent(dentry); -+ h_parent = au_h_dptr(parent, bdst); -+ if (h_parent) -+ goto out; /* success */ -+ -+ /* find top dir which is necessary to cpup */ -+ do { -+ d = parent; -+ dput(parent); -+ parent = dget_parent(d); -+ di_read_lock_parent3(parent, !AuLock_IR); -+ h_parent = au_h_dptr(parent, bdst); -+ di_read_unlock(parent, !AuLock_IR); -+ } while (!h_parent); -+ -+ if (d != real_parent) -+ di_write_lock_child3(d); -+ -+ /* somebody else might create while we were sleeping */ -+ h_dentry = au_h_dptr(d, bdst); -+ if (!h_dentry || d_is_negative(h_dentry)) { -+ if (h_dentry) -+ au_update_dbtop(d); -+ -+ au_pin_set_dentry(&pin, d); -+ err = au_do_pin(&pin); -+ if (!err) { -+ err = cp(d, bdst, &pin, h_parent, arg); -+ au_unpin(&pin); -+ } -+ } -+ -+ if (d != real_parent) -+ di_write_unlock(d); -+ if (unlikely(err)) -+ break; -+ } -+ -+out: -+ dput(parent); -+ return err; -+} -+ -+static int au_cpup_dir(struct dentry *dentry, aufs_bindex_t bdst, -+ struct au_pin *pin, -+ struct dentry *h_parent __maybe_unused, -+ void *arg __maybe_unused) -+{ -+ struct au_cp_generic cpg = { -+ .dentry = dentry, -+ .bdst = bdst, -+ .bsrc = -1, -+ .len = 0, -+ .pin = pin, -+ .flags = AuCpup_DTIME -+ }; -+ return au_sio_cpup_simple(&cpg); -+} -+ -+int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst) -+{ -+ return au_cp_dirs(dentry, bdst, au_cpup_dir, NULL); -+} -+ -+int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst) -+{ -+ int err; -+ struct dentry *parent; -+ struct inode *dir; -+ -+ parent = dget_parent(dentry); -+ dir = d_inode(parent); -+ err = 0; -+ if (au_h_iptr(dir, bdst)) -+ goto out; -+ -+ di_read_unlock(parent, AuLock_IR); -+ di_write_lock_parent(parent); -+ /* someone else might change our inode while we were sleeping */ -+ if (!au_h_iptr(dir, bdst)) -+ err = au_cpup_dirs(dentry, bdst); -+ di_downgrade_lock(parent, AuLock_IR); -+ -+out: -+ dput(parent); -+ return err; -+} -diff -Nurp linux-5.10-rc6/fs/aufs/cpup.h linux-5.10-rc6.aufs/fs/aufs/cpup.h ---- linux-5.10-rc6/fs/aufs/cpup.h 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/cpup.h 2020-12-02 21:19:51.880036698 +0200 -@@ -0,0 +1,87 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * copy-up/down functions -+ */ -+ -+#ifndef __AUFS_CPUP_H__ -+#define __AUFS_CPUP_H__ -+ -+#ifdef __KERNEL__ -+ -+#include -+ -+struct inode; -+struct file; -+struct au_pin; -+ -+void au_cpup_attr_flags(struct inode *dst, unsigned int iflags); -+void au_cpup_attr_timesizes(struct inode *inode); -+void au_cpup_attr_nlink(struct inode *inode, int force); -+void au_cpup_attr_changeable(struct inode *inode); -+void au_cpup_igen(struct inode *inode, struct inode *h_inode); -+void au_cpup_attr_all(struct inode *inode, int force); -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct au_cp_generic { -+ struct dentry *dentry; -+ aufs_bindex_t bdst, bsrc; -+ loff_t len; -+ struct au_pin *pin; -+ unsigned int flags; -+}; -+ -+/* cpup flags */ -+#define AuCpup_DTIME 1 /* do dtime_store/revert */ -+#define AuCpup_KEEPLINO (1 << 1) /* do not clear the lower xino, -+ for link(2) */ -+#define AuCpup_RENAME (1 << 2) /* rename after cpup */ -+#define AuCpup_HOPEN (1 << 3) /* call h_open_pre/post() in -+ cpup */ -+#define AuCpup_OVERWRITE (1 << 4) /* allow overwriting the -+ existing entry */ -+#define AuCpup_RWDST (1 << 5) /* force write target even if -+ the branch is marked as RO */ -+ -+#ifndef CONFIG_AUFS_BR_HFSPLUS -+#undef AuCpup_HOPEN -+#define AuCpup_HOPEN 0 -+#endif -+ -+#define au_ftest_cpup(flags, name) ((flags) & AuCpup_##name) -+#define au_fset_cpup(flags, name) \ -+ do { (flags) |= AuCpup_##name; } while (0) -+#define au_fclr_cpup(flags, name) \ -+ do { (flags) &= ~AuCpup_##name; } while (0) -+ -+int au_copy_file(struct file *dst, struct file *src, loff_t len); -+int au_sio_cpup_simple(struct au_cp_generic *cpg); -+int au_sio_cpdown_simple(struct au_cp_generic *cpg); -+int au_sio_cpup_wh(struct au_cp_generic *cpg, struct file *file); -+ -+int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst, -+ int (*cp)(struct dentry *dentry, aufs_bindex_t bdst, -+ struct au_pin *pin, -+ struct dentry *h_parent, void *arg), -+ void *arg); -+int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst); -+int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst); -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* keep timestamps when copyup */ -+struct au_dtime { -+ struct dentry *dt_dentry; -+ struct path dt_h_path; -+ struct timespec64 dt_atime, dt_mtime; -+}; -+void au_dtime_store(struct au_dtime *dt, struct dentry *dentry, -+ struct path *h_path); -+void au_dtime_revert(struct au_dtime *dt); -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_CPUP_H__ */ -diff -Nurp linux-5.10-rc6/fs/aufs/dbgaufs.c linux-5.10-rc6.aufs/fs/aufs/dbgaufs.c ---- linux-5.10-rc6/fs/aufs/dbgaufs.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/dbgaufs.c 2020-12-02 21:19:51.880036698 +0200 -@@ -0,0 +1,513 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * debugfs interface -+ */ -+ -+#include -+#include "aufs.h" -+ -+#ifndef CONFIG_SYSFS -+#error DEBUG_FS depends upon SYSFS -+#endif -+ -+static struct dentry *dbgaufs; -+static const mode_t dbgaufs_mode = 0444; -+ -+/* 20 is max digits length of ulong 64 */ -+struct dbgaufs_arg { -+ int n; -+ char a[20 * 4]; -+}; -+ -+/* -+ * common function for all XINO files -+ */ -+static int dbgaufs_xi_release(struct inode *inode __maybe_unused, -+ struct file *file) -+{ -+ void *p; -+ -+ p = file->private_data; -+ if (p) { -+ /* this is struct dbgaufs_arg */ -+ AuDebugOn(!au_kfree_sz_test(p)); -+ au_kfree_do_rcu(p); -+ } -+ return 0; -+} -+ -+static int dbgaufs_xi_open(struct file *xf, struct file *file, int do_fcnt, -+ int cnt) -+{ -+ int err; -+ struct kstat st; -+ struct dbgaufs_arg *p; -+ -+ err = -ENOMEM; -+ p = kmalloc(sizeof(*p), GFP_NOFS); -+ if (unlikely(!p)) -+ goto out; -+ -+ err = 0; -+ p->n = 0; -+ file->private_data = p; -+ if (!xf) -+ goto out; -+ -+ err = vfsub_getattr(&xf->f_path, &st); -+ if (!err) { -+ if (do_fcnt) -+ p->n = snprintf -+ (p->a, sizeof(p->a), "%d, %llux%u %lld\n", -+ cnt, st.blocks, st.blksize, -+ (long long)st.size); -+ else -+ p->n = snprintf(p->a, sizeof(p->a), "%llux%u %lld\n", -+ st.blocks, st.blksize, -+ (long long)st.size); -+ AuDebugOn(p->n >= sizeof(p->a)); -+ } else { -+ p->n = snprintf(p->a, sizeof(p->a), "err %d\n", err); -+ err = 0; -+ } -+ -+out: -+ return err; -+} -+ -+static ssize_t dbgaufs_xi_read(struct file *file, char __user *buf, -+ size_t count, loff_t *ppos) -+{ -+ struct dbgaufs_arg *p; -+ -+ p = file->private_data; -+ return simple_read_from_buffer(buf, count, ppos, p->a, p->n); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct dbgaufs_plink_arg { -+ int n; -+ char a[]; -+}; -+ -+static int dbgaufs_plink_release(struct inode *inode __maybe_unused, -+ struct file *file) -+{ -+ free_page((unsigned long)file->private_data); -+ return 0; -+} -+ -+static int dbgaufs_plink_open(struct inode *inode, struct file *file) -+{ -+ int err, i, limit; -+ unsigned long n, sum; -+ struct dbgaufs_plink_arg *p; -+ struct au_sbinfo *sbinfo; -+ struct super_block *sb; -+ struct hlist_bl_head *hbl; -+ -+ err = -ENOMEM; -+ p = (void *)get_zeroed_page(GFP_NOFS); -+ if (unlikely(!p)) -+ goto out; -+ -+ err = -EFBIG; -+ sbinfo = inode->i_private; -+ sb = sbinfo->si_sb; -+ si_noflush_read_lock(sb); -+ if (au_opt_test(au_mntflags(sb), PLINK)) { -+ limit = PAGE_SIZE - sizeof(p->n); -+ -+ /* the number of buckets */ -+ n = snprintf(p->a + p->n, limit, "%d\n", AuPlink_NHASH); -+ p->n += n; -+ limit -= n; -+ -+ sum = 0; -+ for (i = 0, hbl = sbinfo->si_plink; i < AuPlink_NHASH; -+ i++, hbl++) { -+ n = au_hbl_count(hbl); -+ sum += n; -+ -+ n = snprintf(p->a + p->n, limit, "%lu ", n); -+ p->n += n; -+ limit -= n; -+ if (unlikely(limit <= 0)) -+ goto out_free; -+ } -+ p->a[p->n - 1] = '\n'; -+ -+ /* the sum of plinks */ -+ n = snprintf(p->a + p->n, limit, "%lu\n", sum); -+ p->n += n; -+ limit -= n; -+ if (unlikely(limit <= 0)) -+ goto out_free; -+ } else { -+#define str "1\n0\n0\n" -+ p->n = sizeof(str) - 1; -+ strcpy(p->a, str); -+#undef str -+ } -+ si_read_unlock(sb); -+ -+ err = 0; -+ file->private_data = p; -+ goto out; /* success */ -+ -+out_free: -+ free_page((unsigned long)p); -+out: -+ return err; -+} -+ -+static ssize_t dbgaufs_plink_read(struct file *file, char __user *buf, -+ size_t count, loff_t *ppos) -+{ -+ struct dbgaufs_plink_arg *p; -+ -+ p = file->private_data; -+ return simple_read_from_buffer(buf, count, ppos, p->a, p->n); -+} -+ -+static const struct file_operations dbgaufs_plink_fop = { -+ .owner = THIS_MODULE, -+ .open = dbgaufs_plink_open, -+ .release = dbgaufs_plink_release, -+ .read = dbgaufs_plink_read -+}; -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int dbgaufs_xib_open(struct inode *inode, struct file *file) -+{ -+ int err; -+ struct au_sbinfo *sbinfo; -+ struct super_block *sb; -+ -+ sbinfo = inode->i_private; -+ sb = sbinfo->si_sb; -+ si_noflush_read_lock(sb); -+ err = dbgaufs_xi_open(sbinfo->si_xib, file, /*do_fcnt*/0, /*cnt*/0); -+ si_read_unlock(sb); -+ return err; -+} -+ -+static const struct file_operations dbgaufs_xib_fop = { -+ .owner = THIS_MODULE, -+ .open = dbgaufs_xib_open, -+ .release = dbgaufs_xi_release, -+ .read = dbgaufs_xi_read -+}; -+ -+/* ---------------------------------------------------------------------- */ -+ -+#define DbgaufsXi_PREFIX "xi" -+ -+static int dbgaufs_xino_open(struct inode *inode, struct file *file) -+{ -+ int err, idx; -+ long l; -+ aufs_bindex_t bindex; -+ char *p, a[sizeof(DbgaufsXi_PREFIX) + 8]; -+ struct au_sbinfo *sbinfo; -+ struct super_block *sb; -+ struct au_xino *xi; -+ struct file *xf; -+ struct qstr *name; -+ struct au_branch *br; -+ -+ err = -ENOENT; -+ name = &file->f_path.dentry->d_name; -+ if (unlikely(name->len < sizeof(DbgaufsXi_PREFIX) -+ || memcmp(name->name, DbgaufsXi_PREFIX, -+ sizeof(DbgaufsXi_PREFIX) - 1))) -+ goto out; -+ -+ AuDebugOn(name->len >= sizeof(a)); -+ memcpy(a, name->name, name->len); -+ a[name->len] = '\0'; -+ p = strchr(a, '-'); -+ if (p) -+ *p = '\0'; -+ err = kstrtol(a + sizeof(DbgaufsXi_PREFIX) - 1, 10, &l); -+ if (unlikely(err)) -+ goto out; -+ bindex = l; -+ idx = 0; -+ if (p) { -+ err = kstrtol(p + 1, 10, &l); -+ if (unlikely(err)) -+ goto out; -+ idx = l; -+ } -+ -+ err = -ENOENT; -+ sbinfo = inode->i_private; -+ sb = sbinfo->si_sb; -+ si_noflush_read_lock(sb); -+ if (unlikely(bindex < 0 || bindex > au_sbbot(sb))) -+ goto out_si; -+ br = au_sbr(sb, bindex); -+ xi = br->br_xino; -+ if (unlikely(idx >= xi->xi_nfile)) -+ goto out_si; -+ xf = au_xino_file(xi, idx); -+ if (xf) -+ err = dbgaufs_xi_open(xf, file, /*do_fcnt*/1, -+ au_xino_count(br)); -+ -+out_si: -+ si_read_unlock(sb); -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+static const struct file_operations dbgaufs_xino_fop = { -+ .owner = THIS_MODULE, -+ .open = dbgaufs_xino_open, -+ .release = dbgaufs_xi_release, -+ .read = dbgaufs_xi_read -+}; -+ -+void dbgaufs_xino_del(struct au_branch *br) -+{ -+ struct dentry *dbgaufs; -+ -+ dbgaufs = br->br_dbgaufs; -+ if (!dbgaufs) -+ return; -+ -+ br->br_dbgaufs = NULL; -+ /* debugfs acquires the parent i_mutex */ -+ lockdep_off(); -+ debugfs_remove(dbgaufs); -+ lockdep_on(); -+} -+ -+void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex) -+{ -+ aufs_bindex_t bbot; -+ struct au_branch *br; -+ -+ if (!au_sbi(sb)->si_dbgaufs) -+ return; -+ -+ bbot = au_sbbot(sb); -+ for (; bindex <= bbot; bindex++) { -+ br = au_sbr(sb, bindex); -+ dbgaufs_xino_del(br); -+ } -+} -+ -+static void dbgaufs_br_do_add(struct super_block *sb, aufs_bindex_t bindex, -+ unsigned int idx, struct dentry *parent, -+ struct au_sbinfo *sbinfo) -+{ -+ struct au_branch *br; -+ struct dentry *d; -+ /* "xi" bindex(5) "-" idx(2) NULL */ -+ char name[sizeof(DbgaufsXi_PREFIX) + 8]; -+ -+ if (!idx) -+ snprintf(name, sizeof(name), DbgaufsXi_PREFIX "%d", bindex); -+ else -+ snprintf(name, sizeof(name), DbgaufsXi_PREFIX "%d-%u", -+ bindex, idx); -+ br = au_sbr(sb, bindex); -+ if (br->br_dbgaufs) { -+ struct qstr qstr = QSTR_INIT(name, strlen(name)); -+ -+ if (!au_qstreq(&br->br_dbgaufs->d_name, &qstr)) { -+ /* debugfs acquires the parent i_mutex */ -+ lockdep_off(); -+ d = debugfs_rename(parent, br->br_dbgaufs, parent, -+ name); -+ lockdep_on(); -+ if (unlikely(!d)) -+ pr_warn("failed renaming %pd/%s, ignored.\n", -+ parent, name); -+ } -+ } else { -+ lockdep_off(); -+ br->br_dbgaufs = debugfs_create_file(name, dbgaufs_mode, parent, -+ sbinfo, &dbgaufs_xino_fop); -+ lockdep_on(); -+ if (unlikely(!br->br_dbgaufs)) -+ pr_warn("failed creating %pd/%s, ignored.\n", -+ parent, name); -+ } -+} -+ -+static void dbgaufs_br_add(struct super_block *sb, aufs_bindex_t bindex, -+ struct dentry *parent, struct au_sbinfo *sbinfo) -+{ -+ struct au_branch *br; -+ struct au_xino *xi; -+ unsigned int u; -+ -+ br = au_sbr(sb, bindex); -+ xi = br->br_xino; -+ for (u = 0; u < xi->xi_nfile; u++) -+ dbgaufs_br_do_add(sb, bindex, u, parent, sbinfo); -+} -+ -+void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex, int topdown) -+{ -+ struct au_sbinfo *sbinfo; -+ struct dentry *parent; -+ aufs_bindex_t bbot; -+ -+ if (!au_opt_test(au_mntflags(sb), XINO)) -+ return; -+ -+ sbinfo = au_sbi(sb); -+ parent = sbinfo->si_dbgaufs; -+ if (!parent) -+ return; -+ -+ bbot = au_sbbot(sb); -+ if (topdown) -+ for (; bindex <= bbot; bindex++) -+ dbgaufs_br_add(sb, bindex, parent, sbinfo); -+ else -+ for (; bbot >= bindex; bbot--) -+ dbgaufs_br_add(sb, bbot, parent, sbinfo); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+#ifdef CONFIG_AUFS_EXPORT -+static int dbgaufs_xigen_open(struct inode *inode, struct file *file) -+{ -+ int err; -+ struct au_sbinfo *sbinfo; -+ struct super_block *sb; -+ -+ sbinfo = inode->i_private; -+ sb = sbinfo->si_sb; -+ si_noflush_read_lock(sb); -+ err = dbgaufs_xi_open(sbinfo->si_xigen, file, /*do_fcnt*/0, /*cnt*/0); -+ si_read_unlock(sb); -+ return err; -+} -+ -+static const struct file_operations dbgaufs_xigen_fop = { -+ .owner = THIS_MODULE, -+ .open = dbgaufs_xigen_open, -+ .release = dbgaufs_xi_release, -+ .read = dbgaufs_xi_read -+}; -+ -+static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo) -+{ -+ int err; -+ -+ /* -+ * This function is a dynamic '__init' function actually, -+ * so the tiny check for si_rwsem is unnecessary. -+ */ -+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */ -+ -+ err = -EIO; -+ sbinfo->si_dbgaufs_xigen = debugfs_create_file -+ ("xigen", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo, -+ &dbgaufs_xigen_fop); -+ if (sbinfo->si_dbgaufs_xigen) -+ err = 0; -+ -+ return err; -+} -+#else -+static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo) -+{ -+ return 0; -+} -+#endif /* CONFIG_AUFS_EXPORT */ -+ -+/* ---------------------------------------------------------------------- */ -+ -+void dbgaufs_si_fin(struct au_sbinfo *sbinfo) -+{ -+ /* -+ * This function is a dynamic '__fin' function actually, -+ * so the tiny check for si_rwsem is unnecessary. -+ */ -+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */ -+ -+ debugfs_remove_recursive(sbinfo->si_dbgaufs); -+ sbinfo->si_dbgaufs = NULL; -+} -+ -+int dbgaufs_si_init(struct au_sbinfo *sbinfo) -+{ -+ int err; -+ char name[SysaufsSiNameLen]; -+ -+ /* -+ * This function is a dynamic '__init' function actually, -+ * so the tiny check for si_rwsem is unnecessary. -+ */ -+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */ -+ -+ err = -ENOENT; -+ if (!dbgaufs) { -+ AuErr1("/debug/aufs is uninitialized\n"); -+ goto out; -+ } -+ -+ err = -EIO; -+ sysaufs_name(sbinfo, name); -+ sbinfo->si_dbgaufs = debugfs_create_dir(name, dbgaufs); -+ if (unlikely(!sbinfo->si_dbgaufs)) -+ goto out; -+ -+ /* regardless plink/noplink option */ -+ sbinfo->si_dbgaufs_plink = debugfs_create_file -+ ("plink", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo, -+ &dbgaufs_plink_fop); -+ if (unlikely(!sbinfo->si_dbgaufs_plink)) -+ goto out_dir; -+ -+ /* regardless xino/noxino option */ -+ sbinfo->si_dbgaufs_xib = debugfs_create_file -+ ("xib", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo, -+ &dbgaufs_xib_fop); -+ if (unlikely(!sbinfo->si_dbgaufs_xib)) -+ goto out_dir; -+ -+ err = dbgaufs_xigen_init(sbinfo); -+ if (!err) -+ goto out; /* success */ -+ -+out_dir: -+ dbgaufs_si_fin(sbinfo); -+out: -+ if (unlikely(err)) -+ pr_err("debugfs/aufs failed\n"); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+void dbgaufs_fin(void) -+{ -+ debugfs_remove(dbgaufs); -+} -+ -+int __init dbgaufs_init(void) -+{ -+ int err; -+ -+ err = -EIO; -+ dbgaufs = debugfs_create_dir(AUFS_NAME, NULL); -+ if (dbgaufs) -+ err = 0; -+ return err; -+} -diff -Nurp linux-5.10-rc6/fs/aufs/dbgaufs.h linux-5.10-rc6.aufs/fs/aufs/dbgaufs.h ---- linux-5.10-rc6/fs/aufs/dbgaufs.h 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/dbgaufs.h 2020-12-02 21:19:51.880036698 +0200 -@@ -0,0 +1,40 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * debugfs interface -+ */ -+ -+#ifndef __DBGAUFS_H__ -+#define __DBGAUFS_H__ -+ -+#ifdef __KERNEL__ -+ -+struct super_block; -+struct au_sbinfo; -+struct au_branch; -+ -+#ifdef CONFIG_DEBUG_FS -+/* dbgaufs.c */ -+void dbgaufs_xino_del(struct au_branch *br); -+void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex); -+void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex, int topdown); -+void dbgaufs_si_fin(struct au_sbinfo *sbinfo); -+int dbgaufs_si_init(struct au_sbinfo *sbinfo); -+void dbgaufs_fin(void); -+int __init dbgaufs_init(void); -+#else -+AuStubVoid(dbgaufs_xino_del, struct au_branch *br) -+AuStubVoid(dbgaufs_brs_del, struct super_block *sb, aufs_bindex_t bindex) -+AuStubVoid(dbgaufs_brs_add, struct super_block *sb, aufs_bindex_t bindex, -+ int topdown) -+AuStubVoid(dbgaufs_si_fin, struct au_sbinfo *sbinfo) -+AuStubInt0(dbgaufs_si_init, struct au_sbinfo *sbinfo) -+AuStubVoid(dbgaufs_fin, void) -+AuStubInt0(__init dbgaufs_init, void) -+#endif /* CONFIG_DEBUG_FS */ -+ -+#endif /* __KERNEL__ */ -+#endif /* __DBGAUFS_H__ */ -diff -Nurp linux-5.10-rc6/fs/aufs/dcsub.c linux-5.10-rc6.aufs/fs/aufs/dcsub.c ---- linux-5.10-rc6/fs/aufs/dcsub.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/dcsub.c 2020-12-02 21:19:51.880036698 +0200 -@@ -0,0 +1,212 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * sub-routines for dentry cache -+ */ -+ -+#include "aufs.h" -+ -+static void au_dpage_free(struct au_dpage *dpage) -+{ -+ int i; -+ struct dentry **p; -+ -+ p = dpage->dentries; -+ for (i = 0; i < dpage->ndentry; i++) -+ dput(*p++); -+ free_page((unsigned long)dpage->dentries); -+} -+ -+int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp) -+{ -+ int err; -+ void *p; -+ -+ err = -ENOMEM; -+ dpages->dpages = kmalloc(sizeof(*dpages->dpages), gfp); -+ if (unlikely(!dpages->dpages)) -+ goto out; -+ -+ p = (void *)__get_free_page(gfp); -+ if (unlikely(!p)) -+ goto out_dpages; -+ -+ dpages->dpages[0].ndentry = 0; -+ dpages->dpages[0].dentries = p; -+ dpages->ndpage = 1; -+ return 0; /* success */ -+ -+out_dpages: -+ au_kfree_try_rcu(dpages->dpages); -+out: -+ return err; -+} -+ -+void au_dpages_free(struct au_dcsub_pages *dpages) -+{ -+ int i; -+ struct au_dpage *p; -+ -+ p = dpages->dpages; -+ for (i = 0; i < dpages->ndpage; i++) -+ au_dpage_free(p++); -+ au_kfree_try_rcu(dpages->dpages); -+} -+ -+static int au_dpages_append(struct au_dcsub_pages *dpages, -+ struct dentry *dentry, gfp_t gfp) -+{ -+ int err, sz; -+ struct au_dpage *dpage; -+ void *p; -+ -+ dpage = dpages->dpages + dpages->ndpage - 1; -+ sz = PAGE_SIZE / sizeof(dentry); -+ if (unlikely(dpage->ndentry >= sz)) { -+ AuLabel(new dpage); -+ err = -ENOMEM; -+ sz = dpages->ndpage * sizeof(*dpages->dpages); -+ p = au_kzrealloc(dpages->dpages, sz, -+ sz + sizeof(*dpages->dpages), gfp, -+ /*may_shrink*/0); -+ if (unlikely(!p)) -+ goto out; -+ -+ dpages->dpages = p; -+ dpage = dpages->dpages + dpages->ndpage; -+ p = (void *)__get_free_page(gfp); -+ if (unlikely(!p)) -+ goto out; -+ -+ dpage->ndentry = 0; -+ dpage->dentries = p; -+ dpages->ndpage++; -+ } -+ -+ AuDebugOn(au_dcount(dentry) <= 0); -+ dpage->dentries[dpage->ndentry++] = dget_dlock(dentry); -+ return 0; /* success */ -+ -+out: -+ return err; -+} -+ -+/* todo: BAD approach */ -+/* copied from linux/fs/dcache.c */ -+enum d_walk_ret { -+ D_WALK_CONTINUE, -+ D_WALK_QUIT, -+ D_WALK_NORETRY, -+ D_WALK_SKIP, -+}; -+ -+extern void d_walk(struct dentry *parent, void *data, -+ enum d_walk_ret (*enter)(void *, struct dentry *)); -+ -+struct ac_dpages_arg { -+ int err; -+ struct au_dcsub_pages *dpages; -+ struct super_block *sb; -+ au_dpages_test test; -+ void *arg; -+}; -+ -+static enum d_walk_ret au_call_dpages_append(void *_arg, struct dentry *dentry) -+{ -+ enum d_walk_ret ret; -+ struct ac_dpages_arg *arg = _arg; -+ -+ ret = D_WALK_CONTINUE; -+ if (dentry->d_sb == arg->sb -+ && !IS_ROOT(dentry) -+ && au_dcount(dentry) > 0 -+ && au_di(dentry) -+ && (!arg->test || arg->test(dentry, arg->arg))) { -+ arg->err = au_dpages_append(arg->dpages, dentry, GFP_ATOMIC); -+ if (unlikely(arg->err)) -+ ret = D_WALK_QUIT; -+ } -+ -+ return ret; -+} -+ -+int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root, -+ au_dpages_test test, void *arg) -+{ -+ struct ac_dpages_arg args = { -+ .err = 0, -+ .dpages = dpages, -+ .sb = root->d_sb, -+ .test = test, -+ .arg = arg -+ }; -+ -+ d_walk(root, &args, au_call_dpages_append); -+ -+ return args.err; -+} -+ -+int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry, -+ int do_include, au_dpages_test test, void *arg) -+{ -+ int err; -+ -+ err = 0; -+ write_seqlock(&rename_lock); -+ spin_lock(&dentry->d_lock); -+ if (do_include -+ && au_dcount(dentry) > 0 -+ && (!test || test(dentry, arg))) -+ err = au_dpages_append(dpages, dentry, GFP_ATOMIC); -+ spin_unlock(&dentry->d_lock); -+ if (unlikely(err)) -+ goto out; -+ -+ /* -+ * RCU for vfsmount is unnecessary since this is a traverse in a single -+ * mount -+ */ -+ while (!IS_ROOT(dentry)) { -+ dentry = dentry->d_parent; /* rename_lock is locked */ -+ spin_lock(&dentry->d_lock); -+ if (au_dcount(dentry) > 0 -+ && (!test || test(dentry, arg))) -+ err = au_dpages_append(dpages, dentry, GFP_ATOMIC); -+ spin_unlock(&dentry->d_lock); -+ if (unlikely(err)) -+ break; -+ } -+ -+out: -+ write_sequnlock(&rename_lock); -+ return err; -+} -+ -+static inline int au_dcsub_dpages_aufs(struct dentry *dentry, void *arg) -+{ -+ return au_di(dentry) && dentry->d_sb == arg; -+} -+ -+int au_dcsub_pages_rev_aufs(struct au_dcsub_pages *dpages, -+ struct dentry *dentry, int do_include) -+{ -+ return au_dcsub_pages_rev(dpages, dentry, do_include, -+ au_dcsub_dpages_aufs, dentry->d_sb); -+} -+ -+int au_test_subdir(struct dentry *d1, struct dentry *d2) -+{ -+ struct path path[2] = { -+ { -+ .dentry = d1 -+ }, -+ { -+ .dentry = d2 -+ } -+ }; -+ -+ return path_is_under(path + 0, path + 1); -+} -diff -Nurp linux-5.10-rc6/fs/aufs/dcsub.h linux-5.10-rc6.aufs/fs/aufs/dcsub.h ---- linux-5.10-rc6/fs/aufs/dcsub.h 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/dcsub.h 2020-12-02 21:19:51.880036698 +0200 -@@ -0,0 +1,124 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * sub-routines for dentry cache -+ */ -+ -+#ifndef __AUFS_DCSUB_H__ -+#define __AUFS_DCSUB_H__ -+ -+#ifdef __KERNEL__ -+ -+#include -+#include -+ -+struct au_dpage { -+ int ndentry; -+ struct dentry **dentries; -+}; -+ -+struct au_dcsub_pages { -+ int ndpage; -+ struct au_dpage *dpages; -+}; -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* dcsub.c */ -+int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp); -+void au_dpages_free(struct au_dcsub_pages *dpages); -+typedef int (*au_dpages_test)(struct dentry *dentry, void *arg); -+int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root, -+ au_dpages_test test, void *arg); -+int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry, -+ int do_include, au_dpages_test test, void *arg); -+int au_dcsub_pages_rev_aufs(struct au_dcsub_pages *dpages, -+ struct dentry *dentry, int do_include); -+int au_test_subdir(struct dentry *d1, struct dentry *d2); -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * todo: in linux-3.13, several similar (but faster) helpers are added to -+ * include/linux/dcache.h. Try them (in the future). -+ */ -+ -+static inline int au_d_hashed_positive(struct dentry *d) -+{ -+ int err; -+ struct inode *inode = d_inode(d); -+ -+ err = 0; -+ if (unlikely(d_unhashed(d) -+ || d_is_negative(d) -+ || !inode->i_nlink)) -+ err = -ENOENT; -+ return err; -+} -+ -+static inline int au_d_linkable(struct dentry *d) -+{ -+ int err; -+ struct inode *inode = d_inode(d); -+ -+ err = au_d_hashed_positive(d); -+ if (err -+ && d_is_positive(d) -+ && (inode->i_state & I_LINKABLE)) -+ err = 0; -+ return err; -+} -+ -+static inline int au_d_alive(struct dentry *d) -+{ -+ int err; -+ struct inode *inode; -+ -+ err = 0; -+ if (!IS_ROOT(d)) -+ err = au_d_hashed_positive(d); -+ else { -+ inode = d_inode(d); -+ if (unlikely(d_unlinked(d) -+ || d_is_negative(d) -+ || !inode->i_nlink)) -+ err = -ENOENT; -+ } -+ return err; -+} -+ -+static inline int au_alive_dir(struct dentry *d) -+{ -+ int err; -+ -+ err = au_d_alive(d); -+ if (unlikely(err || IS_DEADDIR(d_inode(d)))) -+ err = -ENOENT; -+ return err; -+} -+ -+static inline int au_qstreq(struct qstr *a, struct qstr *b) -+{ -+ return a->len == b->len -+ && !memcmp(a->name, b->name, a->len); -+} -+ -+/* -+ * by the commit -+ * 360f547 2015-01-25 dcache: let the dentry count go down to zero without -+ * taking d_lock -+ * the type of d_lockref.count became int, but the inlined function d_count() -+ * still returns unsigned int. -+ * I don't know why. Maybe it is for every d_count() users? -+ * Anyway au_dcount() lives on. -+ */ -+static inline int au_dcount(struct dentry *d) -+{ -+ return (int)d_count(d); -+} -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_DCSUB_H__ */ -diff -Nurp linux-5.10-rc6/fs/aufs/debug.c linux-5.10-rc6.aufs/fs/aufs/debug.c ---- linux-5.10-rc6/fs/aufs/debug.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/debug.c 2020-12-02 21:19:51.880036698 +0200 -@@ -0,0 +1,428 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * debug print functions -+ */ -+ -+#include -+#include "aufs.h" -+ -+/* Returns 0, or -errno. arg is in kp->arg. */ -+static int param_atomic_t_set(const char *val, const struct kernel_param *kp) -+{ -+ int err, n; -+ -+ err = kstrtoint(val, 0, &n); -+ if (!err) { -+ if (n > 0) -+ au_debug_on(); -+ else -+ au_debug_off(); -+ } -+ return err; -+} -+ -+/* Returns length written or -errno. Buffer is 4k (ie. be short!) */ -+static int param_atomic_t_get(char *buffer, const struct kernel_param *kp) -+{ -+ atomic_t *a; -+ -+ a = kp->arg; -+ return sprintf(buffer, "%d", atomic_read(a)); -+} -+ -+static struct kernel_param_ops param_ops_atomic_t = { -+ .set = param_atomic_t_set, -+ .get = param_atomic_t_get -+ /* void (*free)(void *arg) */ -+}; -+ -+atomic_t aufs_debug = ATOMIC_INIT(0); -+MODULE_PARM_DESC(debug, "debug print"); -+module_param_named(debug, aufs_debug, atomic_t, 0664); -+ -+DEFINE_MUTEX(au_dbg_mtx); /* just to serialize the dbg msgs */ -+char *au_plevel = KERN_DEBUG; -+#define dpri(fmt, ...) do { \ -+ if ((au_plevel \ -+ && strcmp(au_plevel, KERN_DEBUG)) \ -+ || au_debug_test()) \ -+ printk("%s" fmt, au_plevel, ##__VA_ARGS__); \ -+} while (0) -+ -+/* ---------------------------------------------------------------------- */ -+ -+void au_dpri_whlist(struct au_nhash *whlist) -+{ -+ unsigned long ul, n; -+ struct hlist_head *head; -+ struct au_vdir_wh *pos; -+ -+ n = whlist->nh_num; -+ head = whlist->nh_head; -+ for (ul = 0; ul < n; ul++) { -+ hlist_for_each_entry(pos, head, wh_hash) -+ dpri("b%d, %.*s, %d\n", -+ pos->wh_bindex, -+ pos->wh_str.len, pos->wh_str.name, -+ pos->wh_str.len); -+ head++; -+ } -+} -+ -+void au_dpri_vdir(struct au_vdir *vdir) -+{ -+ unsigned long ul; -+ union au_vdir_deblk_p p; -+ unsigned char *o; -+ -+ if (!vdir || IS_ERR(vdir)) { -+ dpri("err %ld\n", PTR_ERR(vdir)); -+ return; -+ } -+ -+ dpri("deblk %u, nblk %lu, deblk %p, last{%lu, %p}, ver %llu\n", -+ vdir->vd_deblk_sz, vdir->vd_nblk, vdir->vd_deblk, -+ vdir->vd_last.ul, vdir->vd_last.p.deblk, vdir->vd_version); -+ for (ul = 0; ul < vdir->vd_nblk; ul++) { -+ p.deblk = vdir->vd_deblk[ul]; -+ o = p.deblk; -+ dpri("[%lu]: %p\n", ul, o); -+ } -+} -+ -+static int do_pri_inode(aufs_bindex_t bindex, struct inode *inode, int hn, -+ struct dentry *wh) -+{ -+ char *n = NULL; -+ int l = 0; -+ -+ if (!inode || IS_ERR(inode)) { -+ dpri("i%d: err %ld\n", bindex, PTR_ERR(inode)); -+ return -1; -+ } -+ -+ /* the type of i_blocks depends upon CONFIG_LBDAF */ -+ BUILD_BUG_ON(sizeof(inode->i_blocks) != sizeof(unsigned long) -+ && sizeof(inode->i_blocks) != sizeof(u64)); -+ if (wh) { -+ n = (void *)wh->d_name.name; -+ l = wh->d_name.len; -+ } -+ -+ dpri("i%d: %p, i%lu, %s, cnt %d, nl %u, 0%o, sz %llu, blk %llu," -+ " hn %d, ct %lld, np %lu, st 0x%lx, f 0x%x, v %llu, g %x%s%.*s\n", -+ bindex, inode, -+ inode->i_ino, inode->i_sb ? au_sbtype(inode->i_sb) : "??", -+ atomic_read(&inode->i_count), inode->i_nlink, inode->i_mode, -+ i_size_read(inode), (unsigned long long)inode->i_blocks, -+ hn, (long long)timespec64_to_ns(&inode->i_ctime) & 0x0ffff, -+ inode->i_mapping ? inode->i_mapping->nrpages : 0, -+ inode->i_state, inode->i_flags, inode_peek_iversion(inode), -+ inode->i_generation, -+ l ? ", wh " : "", l, n); -+ return 0; -+} -+ -+void au_dpri_inode(struct inode *inode) -+{ -+ struct au_iinfo *iinfo; -+ struct au_hinode *hi; -+ aufs_bindex_t bindex; -+ int err, hn; -+ -+ err = do_pri_inode(-1, inode, -1, NULL); -+ if (err || !au_test_aufs(inode->i_sb) || au_is_bad_inode(inode)) -+ return; -+ -+ iinfo = au_ii(inode); -+ dpri("i-1: btop %d, bbot %d, gen %d\n", -+ iinfo->ii_btop, iinfo->ii_bbot, au_iigen(inode, NULL)); -+ if (iinfo->ii_btop < 0) -+ return; -+ hn = 0; -+ for (bindex = iinfo->ii_btop; bindex <= iinfo->ii_bbot; bindex++) { -+ hi = au_hinode(iinfo, bindex); -+ hn = !!au_hn(hi); -+ do_pri_inode(bindex, hi->hi_inode, hn, hi->hi_whdentry); -+ } -+} -+ -+void au_dpri_dalias(struct inode *inode) -+{ -+ struct dentry *d; -+ -+ spin_lock(&inode->i_lock); -+ hlist_for_each_entry(d, &inode->i_dentry, d_u.d_alias) -+ au_dpri_dentry(d); -+ spin_unlock(&inode->i_lock); -+} -+ -+static int do_pri_dentry(aufs_bindex_t bindex, struct dentry *dentry) -+{ -+ struct dentry *wh = NULL; -+ int hn; -+ struct inode *inode; -+ struct au_iinfo *iinfo; -+ struct au_hinode *hi; -+ -+ if (!dentry || IS_ERR(dentry)) { -+ dpri("d%d: err %ld\n", bindex, PTR_ERR(dentry)); -+ return -1; -+ } -+ /* do not call dget_parent() here */ -+ /* note: access d_xxx without d_lock */ -+ dpri("d%d: %p, %pd2?, %s, cnt %d, flags 0x%x, %shashed\n", -+ bindex, dentry, dentry, -+ dentry->d_sb ? au_sbtype(dentry->d_sb) : "??", -+ au_dcount(dentry), dentry->d_flags, -+ d_unhashed(dentry) ? "un" : ""); -+ hn = -1; -+ inode = NULL; -+ if (d_is_positive(dentry)) -+ inode = d_inode(dentry); -+ if (inode -+ && au_test_aufs(dentry->d_sb) -+ && bindex >= 0 -+ && !au_is_bad_inode(inode)) { -+ iinfo = au_ii(inode); -+ hi = au_hinode(iinfo, bindex); -+ hn = !!au_hn(hi); -+ wh = hi->hi_whdentry; -+ } -+ do_pri_inode(bindex, inode, hn, wh); -+ return 0; -+} -+ -+void au_dpri_dentry(struct dentry *dentry) -+{ -+ struct au_dinfo *dinfo; -+ aufs_bindex_t bindex; -+ int err; -+ -+ err = do_pri_dentry(-1, dentry); -+ if (err || !au_test_aufs(dentry->d_sb)) -+ return; -+ -+ dinfo = au_di(dentry); -+ if (!dinfo) -+ return; -+ dpri("d-1: btop %d, bbot %d, bwh %d, bdiropq %d, gen %d, tmp %d\n", -+ dinfo->di_btop, dinfo->di_bbot, -+ dinfo->di_bwh, dinfo->di_bdiropq, au_digen(dentry), -+ dinfo->di_tmpfile); -+ if (dinfo->di_btop < 0) -+ return; -+ for (bindex = dinfo->di_btop; bindex <= dinfo->di_bbot; bindex++) -+ do_pri_dentry(bindex, au_hdentry(dinfo, bindex)->hd_dentry); -+} -+ -+static int do_pri_file(aufs_bindex_t bindex, struct file *file) -+{ -+ char a[32]; -+ -+ if (!file || IS_ERR(file)) { -+ dpri("f%d: err %ld\n", bindex, PTR_ERR(file)); -+ return -1; -+ } -+ a[0] = 0; -+ if (bindex < 0 -+ && !IS_ERR_OR_NULL(file->f_path.dentry) -+ && au_test_aufs(file->f_path.dentry->d_sb) -+ && au_fi(file)) -+ snprintf(a, sizeof(a), ", gen %d, mmapped %d", -+ au_figen(file), atomic_read(&au_fi(file)->fi_mmapped)); -+ dpri("f%d: mode 0x%x, flags 0%o, cnt %ld, v %llu, pos %llu%s\n", -+ bindex, file->f_mode, file->f_flags, (long)file_count(file), -+ file->f_version, file->f_pos, a); -+ if (!IS_ERR_OR_NULL(file->f_path.dentry)) -+ do_pri_dentry(bindex, file->f_path.dentry); -+ return 0; -+} -+ -+void au_dpri_file(struct file *file) -+{ -+ struct au_finfo *finfo; -+ struct au_fidir *fidir; -+ struct au_hfile *hfile; -+ aufs_bindex_t bindex; -+ int err; -+ -+ err = do_pri_file(-1, file); -+ if (err -+ || IS_ERR_OR_NULL(file->f_path.dentry) -+ || !au_test_aufs(file->f_path.dentry->d_sb)) -+ return; -+ -+ finfo = au_fi(file); -+ if (!finfo) -+ return; -+ if (finfo->fi_btop < 0) -+ return; -+ fidir = finfo->fi_hdir; -+ if (!fidir) -+ do_pri_file(finfo->fi_btop, finfo->fi_htop.hf_file); -+ else -+ for (bindex = finfo->fi_btop; -+ bindex >= 0 && bindex <= fidir->fd_bbot; -+ bindex++) { -+ hfile = fidir->fd_hfile + bindex; -+ do_pri_file(bindex, hfile ? hfile->hf_file : NULL); -+ } -+} -+ -+static int do_pri_br(aufs_bindex_t bindex, struct au_branch *br) -+{ -+ struct vfsmount *mnt; -+ struct super_block *sb; -+ -+ if (!br || IS_ERR(br)) -+ goto out; -+ mnt = au_br_mnt(br); -+ if (!mnt || IS_ERR(mnt)) -+ goto out; -+ sb = mnt->mnt_sb; -+ if (!sb || IS_ERR(sb)) -+ goto out; -+ -+ dpri("s%d: {perm 0x%x, id %d, wbr %p}, " -+ "%s, dev 0x%02x%02x, flags 0x%lx, cnt %d, active %d, " -+ "xino %d\n", -+ bindex, br->br_perm, br->br_id, br->br_wbr, -+ au_sbtype(sb), MAJOR(sb->s_dev), MINOR(sb->s_dev), -+ sb->s_flags, sb->s_count, -+ atomic_read(&sb->s_active), -+ !!au_xino_file(br->br_xino, /*idx*/-1)); -+ return 0; -+ -+out: -+ dpri("s%d: err %ld\n", bindex, PTR_ERR(br)); -+ return -1; -+} -+ -+void au_dpri_sb(struct super_block *sb) -+{ -+ struct au_sbinfo *sbinfo; -+ aufs_bindex_t bindex; -+ int err; -+ /* to reduce stack size */ -+ struct { -+ struct vfsmount mnt; -+ struct au_branch fake; -+ } *a; -+ -+ /* this function can be called from magic sysrq */ -+ a = kzalloc(sizeof(*a), GFP_ATOMIC); -+ if (unlikely(!a)) { -+ dpri("no memory\n"); -+ return; -+ } -+ -+ a->mnt.mnt_sb = sb; -+ a->fake.br_path.mnt = &a->mnt; -+ err = do_pri_br(-1, &a->fake); -+ au_kfree_rcu(a); -+ dpri("dev 0x%x\n", sb->s_dev); -+ if (err || !au_test_aufs(sb)) -+ return; -+ -+ sbinfo = au_sbi(sb); -+ if (!sbinfo) -+ return; -+ dpri("nw %d, gen %u, kobj %d\n", -+ atomic_read(&sbinfo->si_nowait.nw_len), sbinfo->si_generation, -+ kref_read(&sbinfo->si_kobj.kref)); -+ for (bindex = 0; bindex <= sbinfo->si_bbot; bindex++) -+ do_pri_br(bindex, sbinfo->si_branch[0 + bindex]); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+void __au_dbg_verify_dinode(struct dentry *dentry, const char *func, int line) -+{ -+ struct inode *h_inode, *inode = d_inode(dentry); -+ struct dentry *h_dentry; -+ aufs_bindex_t bindex, bbot, bi; -+ -+ if (!inode /* || au_di(dentry)->di_lsc == AuLsc_DI_TMP */) -+ return; -+ -+ bbot = au_dbbot(dentry); -+ bi = au_ibbot(inode); -+ if (bi < bbot) -+ bbot = bi; -+ bindex = au_dbtop(dentry); -+ bi = au_ibtop(inode); -+ if (bi > bindex) -+ bindex = bi; -+ -+ for (; bindex <= bbot; bindex++) { -+ h_dentry = au_h_dptr(dentry, bindex); -+ if (!h_dentry) -+ continue; -+ h_inode = au_h_iptr(inode, bindex); -+ if (unlikely(h_inode != d_inode(h_dentry))) { -+ au_debug_on(); -+ AuDbg("b%d, %s:%d\n", bindex, func, line); -+ AuDbgDentry(dentry); -+ AuDbgInode(inode); -+ au_debug_off(); -+ BUG(); -+ } -+ } -+} -+ -+void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen) -+{ -+ int err, i, j; -+ struct au_dcsub_pages dpages; -+ struct au_dpage *dpage; -+ struct dentry **dentries; -+ -+ err = au_dpages_init(&dpages, GFP_NOFS); -+ AuDebugOn(err); -+ err = au_dcsub_pages_rev_aufs(&dpages, parent, /*do_include*/1); -+ AuDebugOn(err); -+ for (i = dpages.ndpage - 1; !err && i >= 0; i--) { -+ dpage = dpages.dpages + i; -+ dentries = dpage->dentries; -+ for (j = dpage->ndentry - 1; !err && j >= 0; j--) -+ AuDebugOn(au_digen_test(dentries[j], sigen)); -+ } -+ au_dpages_free(&dpages); -+} -+ -+void au_dbg_verify_kthread(void) -+{ -+ if (au_wkq_test()) { -+ au_dbg_blocked(); -+ /* -+ * It may be recursive, but udba=notify between two aufs mounts, -+ * where a single ro branch is shared, is not a problem. -+ */ -+ /* WARN_ON(1); */ -+ } -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+int __init au_debug_init(void) -+{ -+ aufs_bindex_t bindex; -+ struct au_vdir_destr destr; -+ -+ bindex = -1; -+ AuDebugOn(bindex >= 0); -+ -+ destr.len = -1; -+ AuDebugOn(destr.len < NAME_MAX); -+ -+#ifdef CONFIG_4KSTACKS -+ pr_warn("CONFIG_4KSTACKS is defined.\n"); -+#endif -+ -+ return 0; -+} -diff -Nurp linux-5.10-rc6/fs/aufs/debug.h linux-5.10-rc6.aufs/fs/aufs/debug.h ---- linux-5.10-rc6/fs/aufs/debug.h 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/debug.h 2020-12-02 21:19:51.880036698 +0200 -@@ -0,0 +1,213 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * debug print functions -+ */ -+ -+#ifndef __AUFS_DEBUG_H__ -+#define __AUFS_DEBUG_H__ -+ -+#ifdef __KERNEL__ -+ -+#include -+#include -+#include -+#include -+ -+#ifdef CONFIG_AUFS_DEBUG -+#define AuDebugOn(a) BUG_ON(a) -+ -+/* module parameter */ -+extern atomic_t aufs_debug; -+static inline void au_debug_on(void) -+{ -+ atomic_inc(&aufs_debug); -+} -+static inline void au_debug_off(void) -+{ -+ atomic_dec_if_positive(&aufs_debug); -+} -+ -+static inline int au_debug_test(void) -+{ -+ return atomic_read(&aufs_debug) > 0; -+} -+#else -+#define AuDebugOn(a) do {} while (0) -+AuStubVoid(au_debug_on, void) -+AuStubVoid(au_debug_off, void) -+AuStubInt0(au_debug_test, void) -+#endif /* CONFIG_AUFS_DEBUG */ -+ -+#define param_check_atomic_t(name, p) __param_check(name, p, atomic_t) -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* debug print */ -+ -+#define AuDbg(fmt, ...) do { \ -+ if (au_debug_test()) \ -+ pr_debug("DEBUG: " fmt, ##__VA_ARGS__); \ -+} while (0) -+#define AuLabel(l) AuDbg(#l "\n") -+#define AuIOErr(fmt, ...) pr_err("I/O Error, " fmt, ##__VA_ARGS__) -+#define AuWarn1(fmt, ...) do { \ -+ static unsigned char _c; \ -+ if (!_c++) \ -+ pr_warn(fmt, ##__VA_ARGS__); \ -+} while (0) -+ -+#define AuErr1(fmt, ...) do { \ -+ static unsigned char _c; \ -+ if (!_c++) \ -+ pr_err(fmt, ##__VA_ARGS__); \ -+} while (0) -+ -+#define AuIOErr1(fmt, ...) do { \ -+ static unsigned char _c; \ -+ if (!_c++) \ -+ AuIOErr(fmt, ##__VA_ARGS__); \ -+} while (0) -+ -+#define AuUnsupportMsg "This operation is not supported." \ -+ " Please report this application to aufs-users ML." -+#define AuUnsupport(fmt, ...) do { \ -+ pr_err(AuUnsupportMsg "\n" fmt, ##__VA_ARGS__); \ -+ dump_stack(); \ -+} while (0) -+ -+#define AuTraceErr(e) do { \ -+ if (unlikely((e) < 0)) \ -+ AuDbg("err %d\n", (int)(e)); \ -+} while (0) -+ -+#define AuTraceErrPtr(p) do { \ -+ if (IS_ERR(p)) \ -+ AuDbg("err %ld\n", PTR_ERR(p)); \ -+} while (0) -+ -+/* dirty macros for debug print, use with "%.*s" and caution */ -+#define AuLNPair(qstr) (qstr)->len, (qstr)->name -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct dentry; -+#ifdef CONFIG_AUFS_DEBUG -+extern struct mutex au_dbg_mtx; -+extern char *au_plevel; -+struct au_nhash; -+void au_dpri_whlist(struct au_nhash *whlist); -+struct au_vdir; -+void au_dpri_vdir(struct au_vdir *vdir); -+struct inode; -+void au_dpri_inode(struct inode *inode); -+void au_dpri_dalias(struct inode *inode); -+void au_dpri_dentry(struct dentry *dentry); -+struct file; -+void au_dpri_file(struct file *filp); -+struct super_block; -+void au_dpri_sb(struct super_block *sb); -+ -+#define au_dbg_verify_dinode(d) __au_dbg_verify_dinode(d, __func__, __LINE__) -+void __au_dbg_verify_dinode(struct dentry *dentry, const char *func, int line); -+void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen); -+void au_dbg_verify_kthread(void); -+ -+int __init au_debug_init(void); -+ -+#define AuDbgWhlist(w) do { \ -+ mutex_lock(&au_dbg_mtx); \ -+ AuDbg(#w "\n"); \ -+ au_dpri_whlist(w); \ -+ mutex_unlock(&au_dbg_mtx); \ -+} while (0) -+ -+#define AuDbgVdir(v) do { \ -+ mutex_lock(&au_dbg_mtx); \ -+ AuDbg(#v "\n"); \ -+ au_dpri_vdir(v); \ -+ mutex_unlock(&au_dbg_mtx); \ -+} while (0) -+ -+#define AuDbgInode(i) do { \ -+ mutex_lock(&au_dbg_mtx); \ -+ AuDbg(#i "\n"); \ -+ au_dpri_inode(i); \ -+ mutex_unlock(&au_dbg_mtx); \ -+} while (0) -+ -+#define AuDbgDAlias(i) do { \ -+ mutex_lock(&au_dbg_mtx); \ -+ AuDbg(#i "\n"); \ -+ au_dpri_dalias(i); \ -+ mutex_unlock(&au_dbg_mtx); \ -+} while (0) -+ -+#define AuDbgDentry(d) do { \ -+ mutex_lock(&au_dbg_mtx); \ -+ AuDbg(#d "\n"); \ -+ au_dpri_dentry(d); \ -+ mutex_unlock(&au_dbg_mtx); \ -+} while (0) -+ -+#define AuDbgFile(f) do { \ -+ mutex_lock(&au_dbg_mtx); \ -+ AuDbg(#f "\n"); \ -+ au_dpri_file(f); \ -+ mutex_unlock(&au_dbg_mtx); \ -+} while (0) -+ -+#define AuDbgSb(sb) do { \ -+ mutex_lock(&au_dbg_mtx); \ -+ AuDbg(#sb "\n"); \ -+ au_dpri_sb(sb); \ -+ mutex_unlock(&au_dbg_mtx); \ -+} while (0) -+ -+#define AuDbgSym(addr) do { \ -+ char sym[KSYM_SYMBOL_LEN]; \ -+ sprint_symbol(sym, (unsigned long)addr); \ -+ AuDbg("%s\n", sym); \ -+} while (0) -+#else -+AuStubVoid(au_dbg_verify_dinode, struct dentry *dentry) -+AuStubVoid(au_dbg_verify_gen, struct dentry *parent, unsigned int sigen) -+AuStubVoid(au_dbg_verify_kthread, void) -+AuStubInt0(__init au_debug_init, void) -+ -+#define AuDbgWhlist(w) do {} while (0) -+#define AuDbgVdir(v) do {} while (0) -+#define AuDbgInode(i) do {} while (0) -+#define AuDbgDAlias(i) do {} while (0) -+#define AuDbgDentry(d) do {} while (0) -+#define AuDbgFile(f) do {} while (0) -+#define AuDbgSb(sb) do {} while (0) -+#define AuDbgSym(addr) do {} while (0) -+#endif /* CONFIG_AUFS_DEBUG */ -+ -+/* ---------------------------------------------------------------------- */ -+ -+#ifdef CONFIG_AUFS_MAGIC_SYSRQ -+int __init au_sysrq_init(void); -+void au_sysrq_fin(void); -+ -+#ifdef CONFIG_HW_CONSOLE -+#define au_dbg_blocked() do { \ -+ WARN_ON(1); \ -+ handle_sysrq('w'); \ -+} while (0) -+#else -+AuStubVoid(au_dbg_blocked, void) -+#endif -+ -+#else -+AuStubInt0(__init au_sysrq_init, void) -+AuStubVoid(au_sysrq_fin, void) -+AuStubVoid(au_dbg_blocked, void) -+#endif /* CONFIG_AUFS_MAGIC_SYSRQ */ -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_DEBUG_H__ */ -diff -Nurp linux-5.10-rc6/fs/aufs/dentry.c linux-5.10-rc6.aufs/fs/aufs/dentry.c ---- linux-5.10-rc6/fs/aufs/dentry.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/dentry.c 2020-12-02 21:19:51.880036698 +0200 -@@ -0,0 +1,1141 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * lookup and dentry operations -+ */ -+ -+#include -+#include -+#include "aufs.h" -+ -+/* -+ * returns positive/negative dentry, NULL or an error. -+ * NULL means whiteout-ed or not-found. -+ */ -+static struct dentry* -+au_do_lookup(struct dentry *h_parent, struct dentry *dentry, -+ aufs_bindex_t bindex, struct au_do_lookup_args *args) -+{ -+ struct dentry *h_dentry; -+ struct inode *h_inode; -+ struct au_branch *br; -+ int wh_found, opq; -+ unsigned char wh_able; -+ const unsigned char allow_neg = !!au_ftest_lkup(args->flags, ALLOW_NEG); -+ const unsigned char ignore_perm = !!au_ftest_lkup(args->flags, -+ IGNORE_PERM); -+ -+ wh_found = 0; -+ br = au_sbr(dentry->d_sb, bindex); -+ wh_able = !!au_br_whable(br->br_perm); -+ if (wh_able) -+ wh_found = au_wh_test(h_parent, &args->whname, ignore_perm); -+ h_dentry = ERR_PTR(wh_found); -+ if (!wh_found) -+ goto real_lookup; -+ if (unlikely(wh_found < 0)) -+ goto out; -+ -+ /* We found a whiteout */ -+ /* au_set_dbbot(dentry, bindex); */ -+ au_set_dbwh(dentry, bindex); -+ if (!allow_neg) -+ return NULL; /* success */ -+ -+real_lookup: -+ if (!ignore_perm) -+ h_dentry = vfsub_lkup_one(args->name, h_parent); -+ else -+ h_dentry = au_sio_lkup_one(args->name, h_parent); -+ if (IS_ERR(h_dentry)) { -+ if (PTR_ERR(h_dentry) == -ENAMETOOLONG -+ && !allow_neg) -+ h_dentry = NULL; -+ goto out; -+ } -+ -+ h_inode = d_inode(h_dentry); -+ if (d_is_negative(h_dentry)) { -+ if (!allow_neg) -+ goto out_neg; -+ } else if (wh_found -+ || (args->type && args->type != (h_inode->i_mode & S_IFMT))) -+ goto out_neg; -+ else if (au_ftest_lkup(args->flags, DIRREN) -+ /* && h_inode */ -+ && !au_dr_lkup_h_ino(args, bindex, h_inode->i_ino)) { -+ AuDbg("b%d %pd ignored hi%llu\n", bindex, h_dentry, -+ (unsigned long long)h_inode->i_ino); -+ goto out_neg; -+ } -+ -+ if (au_dbbot(dentry) <= bindex) -+ au_set_dbbot(dentry, bindex); -+ if (au_dbtop(dentry) < 0 || bindex < au_dbtop(dentry)) -+ au_set_dbtop(dentry, bindex); -+ au_set_h_dptr(dentry, bindex, h_dentry); -+ -+ if (!d_is_dir(h_dentry) -+ || !wh_able -+ || (d_really_is_positive(dentry) && !d_is_dir(dentry))) -+ goto out; /* success */ -+ -+ inode_lock_shared_nested(h_inode, AuLsc_I_CHILD); -+ opq = au_diropq_test(h_dentry); -+ inode_unlock_shared(h_inode); -+ if (opq > 0) -+ au_set_dbdiropq(dentry, bindex); -+ else if (unlikely(opq < 0)) { -+ au_set_h_dptr(dentry, bindex, NULL); -+ h_dentry = ERR_PTR(opq); -+ } -+ goto out; -+ -+out_neg: -+ dput(h_dentry); -+ h_dentry = NULL; -+out: -+ return h_dentry; -+} -+ -+static int au_test_shwh(struct super_block *sb, const struct qstr *name) -+{ -+ if (unlikely(!au_opt_test(au_mntflags(sb), SHWH) -+ && !strncmp(name->name, AUFS_WH_PFX, AUFS_WH_PFX_LEN))) -+ return -EPERM; -+ return 0; -+} -+ -+/* -+ * returns the number of lower positive dentries, -+ * otherwise an error. -+ * can be called at unlinking with @type is zero. -+ */ -+int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t btop, -+ unsigned int flags) -+{ -+ int npositive, err; -+ aufs_bindex_t bindex, btail, bdiropq; -+ unsigned char isdir, dirperm1, dirren; -+ struct au_do_lookup_args args = { -+ .flags = flags, -+ .name = &dentry->d_name -+ }; -+ struct dentry *parent; -+ struct super_block *sb; -+ -+ sb = dentry->d_sb; -+ err = au_test_shwh(sb, args.name); -+ if (unlikely(err)) -+ goto out; -+ -+ err = au_wh_name_alloc(&args.whname, args.name); -+ if (unlikely(err)) -+ goto out; -+ -+ isdir = !!d_is_dir(dentry); -+ dirperm1 = !!au_opt_test(au_mntflags(sb), DIRPERM1); -+ dirren = !!au_opt_test(au_mntflags(sb), DIRREN); -+ if (dirren) -+ au_fset_lkup(args.flags, DIRREN); -+ -+ npositive = 0; -+ parent = dget_parent(dentry); -+ btail = au_dbtaildir(parent); -+ for (bindex = btop; bindex <= btail; bindex++) { -+ struct dentry *h_parent, *h_dentry; -+ struct inode *h_inode, *h_dir; -+ struct au_branch *br; -+ -+ h_dentry = au_h_dptr(dentry, bindex); -+ if (h_dentry) { -+ if (d_is_positive(h_dentry)) -+ npositive++; -+ break; -+ } -+ h_parent = au_h_dptr(parent, bindex); -+ if (!h_parent || !d_is_dir(h_parent)) -+ continue; -+ -+ if (dirren) { -+ /* if the inum matches, then use the prepared name */ -+ err = au_dr_lkup_name(&args, bindex); -+ if (unlikely(err)) -+ goto out_parent; -+ } -+ -+ h_dir = d_inode(h_parent); -+ inode_lock_shared_nested(h_dir, AuLsc_I_PARENT); -+ h_dentry = au_do_lookup(h_parent, dentry, bindex, &args); -+ inode_unlock_shared(h_dir); -+ err = PTR_ERR(h_dentry); -+ if (IS_ERR(h_dentry)) -+ goto out_parent; -+ if (h_dentry) -+ au_fclr_lkup(args.flags, ALLOW_NEG); -+ if (dirperm1) -+ au_fset_lkup(args.flags, IGNORE_PERM); -+ -+ if (au_dbwh(dentry) == bindex) -+ break; -+ if (!h_dentry) -+ continue; -+ if (d_is_negative(h_dentry)) -+ continue; -+ h_inode = d_inode(h_dentry); -+ npositive++; -+ if (!args.type) -+ args.type = h_inode->i_mode & S_IFMT; -+ if (args.type != S_IFDIR) -+ break; -+ else if (isdir) { -+ /* the type of lower may be different */ -+ bdiropq = au_dbdiropq(dentry); -+ if (bdiropq >= 0 && bdiropq <= bindex) -+ break; -+ } -+ br = au_sbr(sb, bindex); -+ if (dirren -+ && au_dr_hino_test_add(&br->br_dirren, h_inode->i_ino, -+ /*add_ent*/NULL)) { -+ /* prepare next name to lookup */ -+ err = au_dr_lkup(&args, dentry, bindex); -+ if (unlikely(err)) -+ goto out_parent; -+ } -+ } -+ -+ if (npositive) { -+ AuLabel(positive); -+ au_update_dbtop(dentry); -+ } -+ err = npositive; -+ if (unlikely(!au_opt_test(au_mntflags(sb), UDBA_NONE) -+ && au_dbtop(dentry) < 0)) { -+ err = -EIO; -+ AuIOErr("both of real entry and whiteout found, %pd, err %d\n", -+ dentry, err); -+ } -+ -+out_parent: -+ dput(parent); -+ au_kfree_try_rcu(args.whname.name); -+ if (dirren) -+ au_dr_lkup_fin(&args); -+out: -+ return err; -+} -+ -+struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent) -+{ -+ struct dentry *dentry; -+ int wkq_err; -+ -+ if (!au_test_h_perm_sio(d_inode(parent), MAY_EXEC)) -+ dentry = vfsub_lkup_one(name, parent); -+ else { -+ struct vfsub_lkup_one_args args = { -+ .errp = &dentry, -+ .name = name, -+ .parent = parent -+ }; -+ -+ wkq_err = au_wkq_wait(vfsub_call_lkup_one, &args); -+ if (unlikely(wkq_err)) -+ dentry = ERR_PTR(wkq_err); -+ } -+ -+ return dentry; -+} -+ -+/* -+ * lookup @dentry on @bindex which should be negative. -+ */ -+int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex, int wh) -+{ -+ int err; -+ struct dentry *parent, *h_parent, *h_dentry; -+ struct au_branch *br; -+ -+ parent = dget_parent(dentry); -+ h_parent = au_h_dptr(parent, bindex); -+ br = au_sbr(dentry->d_sb, bindex); -+ if (wh) -+ h_dentry = au_whtmp_lkup(h_parent, br, &dentry->d_name); -+ else -+ h_dentry = au_sio_lkup_one(&dentry->d_name, h_parent); -+ err = PTR_ERR(h_dentry); -+ if (IS_ERR(h_dentry)) -+ goto out; -+ if (unlikely(d_is_positive(h_dentry))) { -+ err = -EIO; -+ AuIOErr("%pd should be negative on b%d.\n", h_dentry, bindex); -+ dput(h_dentry); -+ goto out; -+ } -+ -+ err = 0; -+ if (bindex < au_dbtop(dentry)) -+ au_set_dbtop(dentry, bindex); -+ if (au_dbbot(dentry) < bindex) -+ au_set_dbbot(dentry, bindex); -+ au_set_h_dptr(dentry, bindex, h_dentry); -+ -+out: -+ dput(parent); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* subset of struct inode */ -+struct au_iattr { -+ unsigned long i_ino; -+ /* unsigned int i_nlink; */ -+ kuid_t i_uid; -+ kgid_t i_gid; -+ u64 i_version; -+/* -+ loff_t i_size; -+ blkcnt_t i_blocks; -+*/ -+ umode_t i_mode; -+}; -+ -+static void au_iattr_save(struct au_iattr *ia, struct inode *h_inode) -+{ -+ ia->i_ino = h_inode->i_ino; -+ /* ia->i_nlink = h_inode->i_nlink; */ -+ ia->i_uid = h_inode->i_uid; -+ ia->i_gid = h_inode->i_gid; -+ ia->i_version = inode_query_iversion(h_inode); -+/* -+ ia->i_size = h_inode->i_size; -+ ia->i_blocks = h_inode->i_blocks; -+*/ -+ ia->i_mode = (h_inode->i_mode & S_IFMT); -+} -+ -+static int au_iattr_test(struct au_iattr *ia, struct inode *h_inode) -+{ -+ return ia->i_ino != h_inode->i_ino -+ /* || ia->i_nlink != h_inode->i_nlink */ -+ || !uid_eq(ia->i_uid, h_inode->i_uid) -+ || !gid_eq(ia->i_gid, h_inode->i_gid) -+ || !inode_eq_iversion(h_inode, ia->i_version) -+/* -+ || ia->i_size != h_inode->i_size -+ || ia->i_blocks != h_inode->i_blocks -+*/ -+ || ia->i_mode != (h_inode->i_mode & S_IFMT); -+} -+ -+static int au_h_verify_dentry(struct dentry *h_dentry, struct dentry *h_parent, -+ struct au_branch *br) -+{ -+ int err; -+ struct au_iattr ia; -+ struct inode *h_inode; -+ struct dentry *h_d; -+ struct super_block *h_sb; -+ -+ err = 0; -+ memset(&ia, -1, sizeof(ia)); -+ h_sb = h_dentry->d_sb; -+ h_inode = NULL; -+ if (d_is_positive(h_dentry)) { -+ h_inode = d_inode(h_dentry); -+ au_iattr_save(&ia, h_inode); -+ } else if (au_test_nfs(h_sb) || au_test_fuse(h_sb)) -+ /* nfs d_revalidate may return 0 for negative dentry */ -+ /* fuse d_revalidate always return 0 for negative dentry */ -+ goto out; -+ -+ /* main purpose is namei.c:cached_lookup() and d_revalidate */ -+ h_d = vfsub_lkup_one(&h_dentry->d_name, h_parent); -+ err = PTR_ERR(h_d); -+ if (IS_ERR(h_d)) -+ goto out; -+ -+ err = 0; -+ if (unlikely(h_d != h_dentry -+ || d_inode(h_d) != h_inode -+ || (h_inode && au_iattr_test(&ia, h_inode)))) -+ err = au_busy_or_stale(); -+ dput(h_d); -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir, -+ struct dentry *h_parent, struct au_branch *br) -+{ -+ int err; -+ -+ err = 0; -+ if (udba == AuOpt_UDBA_REVAL -+ && !au_test_fs_remote(h_dentry->d_sb)) { -+ IMustLock(h_dir); -+ err = (d_inode(h_dentry->d_parent) != h_dir); -+ } else if (udba != AuOpt_UDBA_NONE) -+ err = au_h_verify_dentry(h_dentry, h_parent, br); -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int au_do_refresh_hdentry(struct dentry *dentry, struct dentry *parent) -+{ -+ int err; -+ aufs_bindex_t new_bindex, bindex, bbot, bwh, bdiropq; -+ struct au_hdentry tmp, *p, *q; -+ struct au_dinfo *dinfo; -+ struct super_block *sb; -+ -+ DiMustWriteLock(dentry); -+ -+ sb = dentry->d_sb; -+ dinfo = au_di(dentry); -+ bbot = dinfo->di_bbot; -+ bwh = dinfo->di_bwh; -+ bdiropq = dinfo->di_bdiropq; -+ bindex = dinfo->di_btop; -+ p = au_hdentry(dinfo, bindex); -+ for (; bindex <= bbot; bindex++, p++) { -+ if (!p->hd_dentry) -+ continue; -+ -+ new_bindex = au_br_index(sb, p->hd_id); -+ if (new_bindex == bindex) -+ continue; -+ -+ if (dinfo->di_bwh == bindex) -+ bwh = new_bindex; -+ if (dinfo->di_bdiropq == bindex) -+ bdiropq = new_bindex; -+ if (new_bindex < 0) { -+ au_hdput(p); -+ p->hd_dentry = NULL; -+ continue; -+ } -+ -+ /* swap two lower dentries, and loop again */ -+ q = au_hdentry(dinfo, new_bindex); -+ tmp = *q; -+ *q = *p; -+ *p = tmp; -+ if (tmp.hd_dentry) { -+ bindex--; -+ p--; -+ } -+ } -+ -+ dinfo->di_bwh = -1; -+ if (bwh >= 0 && bwh <= au_sbbot(sb) && au_sbr_whable(sb, bwh)) -+ dinfo->di_bwh = bwh; -+ -+ dinfo->di_bdiropq = -1; -+ if (bdiropq >= 0 -+ && bdiropq <= au_sbbot(sb) -+ && au_sbr_whable(sb, bdiropq)) -+ dinfo->di_bdiropq = bdiropq; -+ -+ err = -EIO; -+ dinfo->di_btop = -1; -+ dinfo->di_bbot = -1; -+ bbot = au_dbbot(parent); -+ bindex = 0; -+ p = au_hdentry(dinfo, bindex); -+ for (; bindex <= bbot; bindex++, p++) -+ if (p->hd_dentry) { -+ dinfo->di_btop = bindex; -+ break; -+ } -+ -+ if (dinfo->di_btop >= 0) { -+ bindex = bbot; -+ p = au_hdentry(dinfo, bindex); -+ for (; bindex >= 0; bindex--, p--) -+ if (p->hd_dentry) { -+ dinfo->di_bbot = bindex; -+ err = 0; -+ break; -+ } -+ } -+ -+ return err; -+} -+ -+static void au_do_hide(struct dentry *dentry) -+{ -+ struct inode *inode; -+ -+ if (d_really_is_positive(dentry)) { -+ inode = d_inode(dentry); -+ if (!d_is_dir(dentry)) { -+ if (inode->i_nlink && !d_unhashed(dentry)) -+ drop_nlink(inode); -+ } else { -+ clear_nlink(inode); -+ /* stop next lookup */ -+ inode->i_flags |= S_DEAD; -+ } -+ smp_mb(); /* necessary? */ -+ } -+ d_drop(dentry); -+} -+ -+static int au_hide_children(struct dentry *parent) -+{ -+ int err, i, j, ndentry; -+ struct au_dcsub_pages dpages; -+ struct au_dpage *dpage; -+ struct dentry *dentry; -+ -+ err = au_dpages_init(&dpages, GFP_NOFS); -+ if (unlikely(err)) -+ goto out; -+ err = au_dcsub_pages(&dpages, parent, NULL, NULL); -+ if (unlikely(err)) -+ goto out_dpages; -+ -+ /* in reverse order */ -+ for (i = dpages.ndpage - 1; i >= 0; i--) { -+ dpage = dpages.dpages + i; -+ ndentry = dpage->ndentry; -+ for (j = ndentry - 1; j >= 0; j--) { -+ dentry = dpage->dentries[j]; -+ if (dentry != parent) -+ au_do_hide(dentry); -+ } -+ } -+ -+out_dpages: -+ au_dpages_free(&dpages); -+out: -+ return err; -+} -+ -+static void au_hide(struct dentry *dentry) -+{ -+ int err; -+ -+ AuDbgDentry(dentry); -+ if (d_is_dir(dentry)) { -+ /* shrink_dcache_parent(dentry); */ -+ err = au_hide_children(dentry); -+ if (unlikely(err)) -+ AuIOErr("%pd, failed hiding children, ignored %d\n", -+ dentry, err); -+ } -+ au_do_hide(dentry); -+} -+ -+/* -+ * By adding a dirty branch, a cached dentry may be affected in various ways. -+ * -+ * a dirty branch is added -+ * - on the top of layers -+ * - in the middle of layers -+ * - to the bottom of layers -+ * -+ * on the added branch there exists -+ * - a whiteout -+ * - a diropq -+ * - a same named entry -+ * + exist -+ * * negative --> positive -+ * * positive --> positive -+ * - type is unchanged -+ * - type is changed -+ * + doesn't exist -+ * * negative --> negative -+ * * positive --> negative (rejected by au_br_del() for non-dir case) -+ * - none -+ */ -+static int au_refresh_by_dinfo(struct dentry *dentry, struct au_dinfo *dinfo, -+ struct au_dinfo *tmp) -+{ -+ int err; -+ aufs_bindex_t bindex, bbot; -+ struct { -+ struct dentry *dentry; -+ struct inode *inode; -+ mode_t mode; -+ } orig_h, tmp_h = { -+ .dentry = NULL -+ }; -+ struct au_hdentry *hd; -+ struct inode *inode, *h_inode; -+ struct dentry *h_dentry; -+ -+ err = 0; -+ AuDebugOn(dinfo->di_btop < 0); -+ orig_h.mode = 0; -+ orig_h.dentry = au_hdentry(dinfo, dinfo->di_btop)->hd_dentry; -+ orig_h.inode = NULL; -+ if (d_is_positive(orig_h.dentry)) { -+ orig_h.inode = d_inode(orig_h.dentry); -+ orig_h.mode = orig_h.inode->i_mode & S_IFMT; -+ } -+ if (tmp->di_btop >= 0) { -+ tmp_h.dentry = au_hdentry(tmp, tmp->di_btop)->hd_dentry; -+ if (d_is_positive(tmp_h.dentry)) { -+ tmp_h.inode = d_inode(tmp_h.dentry); -+ tmp_h.mode = tmp_h.inode->i_mode & S_IFMT; -+ } -+ } -+ -+ inode = NULL; -+ if (d_really_is_positive(dentry)) -+ inode = d_inode(dentry); -+ if (!orig_h.inode) { -+ AuDbg("negative originally\n"); -+ if (inode) { -+ au_hide(dentry); -+ goto out; -+ } -+ AuDebugOn(inode); -+ AuDebugOn(dinfo->di_btop != dinfo->di_bbot); -+ AuDebugOn(dinfo->di_bdiropq != -1); -+ -+ if (!tmp_h.inode) { -+ AuDbg("negative --> negative\n"); -+ /* should have only one negative lower */ -+ if (tmp->di_btop >= 0 -+ && tmp->di_btop < dinfo->di_btop) { -+ AuDebugOn(tmp->di_btop != tmp->di_bbot); -+ AuDebugOn(dinfo->di_btop != dinfo->di_bbot); -+ au_set_h_dptr(dentry, dinfo->di_btop, NULL); -+ au_di_cp(dinfo, tmp); -+ hd = au_hdentry(tmp, tmp->di_btop); -+ au_set_h_dptr(dentry, tmp->di_btop, -+ dget(hd->hd_dentry)); -+ } -+ au_dbg_verify_dinode(dentry); -+ } else { -+ AuDbg("negative --> positive\n"); -+ /* -+ * similar to the behaviour of creating with bypassing -+ * aufs. -+ * unhash it in order to force an error in the -+ * succeeding create operation. -+ * we should not set S_DEAD here. -+ */ -+ d_drop(dentry); -+ /* au_di_swap(tmp, dinfo); */ -+ au_dbg_verify_dinode(dentry); -+ } -+ } else { -+ AuDbg("positive originally\n"); -+ /* inode may be NULL */ -+ AuDebugOn(inode && (inode->i_mode & S_IFMT) != orig_h.mode); -+ if (!tmp_h.inode) { -+ AuDbg("positive --> negative\n"); -+ /* or bypassing aufs */ -+ au_hide(dentry); -+ if (tmp->di_bwh >= 0 && tmp->di_bwh <= dinfo->di_btop) -+ dinfo->di_bwh = tmp->di_bwh; -+ if (inode) -+ err = au_refresh_hinode_self(inode); -+ au_dbg_verify_dinode(dentry); -+ } else if (orig_h.mode == tmp_h.mode) { -+ AuDbg("positive --> positive, same type\n"); -+ if (!S_ISDIR(orig_h.mode) -+ && dinfo->di_btop > tmp->di_btop) { -+ /* -+ * similar to the behaviour of removing and -+ * creating. -+ */ -+ au_hide(dentry); -+ if (inode) -+ err = au_refresh_hinode_self(inode); -+ au_dbg_verify_dinode(dentry); -+ } else { -+ /* fill empty slots */ -+ if (dinfo->di_btop > tmp->di_btop) -+ dinfo->di_btop = tmp->di_btop; -+ if (dinfo->di_bbot < tmp->di_bbot) -+ dinfo->di_bbot = tmp->di_bbot; -+ dinfo->di_bwh = tmp->di_bwh; -+ dinfo->di_bdiropq = tmp->di_bdiropq; -+ bbot = dinfo->di_bbot; -+ bindex = tmp->di_btop; -+ hd = au_hdentry(tmp, bindex); -+ for (; bindex <= bbot; bindex++, hd++) { -+ if (au_h_dptr(dentry, bindex)) -+ continue; -+ h_dentry = hd->hd_dentry; -+ if (!h_dentry) -+ continue; -+ AuDebugOn(d_is_negative(h_dentry)); -+ h_inode = d_inode(h_dentry); -+ AuDebugOn(orig_h.mode -+ != (h_inode->i_mode -+ & S_IFMT)); -+ au_set_h_dptr(dentry, bindex, -+ dget(h_dentry)); -+ } -+ if (inode) -+ err = au_refresh_hinode(inode, dentry); -+ au_dbg_verify_dinode(dentry); -+ } -+ } else { -+ AuDbg("positive --> positive, different type\n"); -+ /* similar to the behaviour of removing and creating */ -+ au_hide(dentry); -+ if (inode) -+ err = au_refresh_hinode_self(inode); -+ au_dbg_verify_dinode(dentry); -+ } -+ } -+ -+out: -+ return err; -+} -+ -+void au_refresh_dop(struct dentry *dentry, int force_reval) -+{ -+ const struct dentry_operations *dop -+ = force_reval ? &aufs_dop : dentry->d_sb->s_d_op; -+ static const unsigned int mask -+ = DCACHE_OP_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE; -+ -+ BUILD_BUG_ON(sizeof(mask) != sizeof(dentry->d_flags)); -+ -+ if (dentry->d_op == dop) -+ return; -+ -+ AuDbg("%pd\n", dentry); -+ spin_lock(&dentry->d_lock); -+ if (dop == &aufs_dop) -+ dentry->d_flags |= mask; -+ else -+ dentry->d_flags &= ~mask; -+ dentry->d_op = dop; -+ spin_unlock(&dentry->d_lock); -+} -+ -+int au_refresh_dentry(struct dentry *dentry, struct dentry *parent) -+{ -+ int err, ebrange, nbr; -+ unsigned int sigen; -+ struct au_dinfo *dinfo, *tmp; -+ struct super_block *sb; -+ struct inode *inode; -+ -+ DiMustWriteLock(dentry); -+ AuDebugOn(IS_ROOT(dentry)); -+ AuDebugOn(d_really_is_negative(parent)); -+ -+ sb = dentry->d_sb; -+ sigen = au_sigen(sb); -+ err = au_digen_test(parent, sigen); -+ if (unlikely(err)) -+ goto out; -+ -+ nbr = au_sbbot(sb) + 1; -+ dinfo = au_di(dentry); -+ err = au_di_realloc(dinfo, nbr, /*may_shrink*/0); -+ if (unlikely(err)) -+ goto out; -+ ebrange = au_dbrange_test(dentry); -+ if (!ebrange) -+ ebrange = au_do_refresh_hdentry(dentry, parent); -+ -+ if (d_unhashed(dentry) || ebrange /* || dinfo->di_tmpfile */) { -+ AuDebugOn(au_dbtop(dentry) < 0 && au_dbbot(dentry) >= 0); -+ if (d_really_is_positive(dentry)) { -+ inode = d_inode(dentry); -+ err = au_refresh_hinode_self(inode); -+ } -+ au_dbg_verify_dinode(dentry); -+ if (!err) -+ goto out_dgen; /* success */ -+ goto out; -+ } -+ -+ /* temporary dinfo */ -+ AuDbgDentry(dentry); -+ err = -ENOMEM; -+ tmp = au_di_alloc(sb, AuLsc_DI_TMP); -+ if (unlikely(!tmp)) -+ goto out; -+ au_di_swap(tmp, dinfo); -+ /* returns the number of positive dentries */ -+ /* -+ * if current working dir is removed, it returns an error. -+ * but the dentry is legal. -+ */ -+ err = au_lkup_dentry(dentry, /*btop*/0, AuLkup_ALLOW_NEG); -+ AuDbgDentry(dentry); -+ au_di_swap(tmp, dinfo); -+ if (err == -ENOENT) -+ err = 0; -+ if (err >= 0) { -+ /* compare/refresh by dinfo */ -+ AuDbgDentry(dentry); -+ err = au_refresh_by_dinfo(dentry, dinfo, tmp); -+ au_dbg_verify_dinode(dentry); -+ AuTraceErr(err); -+ } -+ au_di_realloc(dinfo, nbr, /*may_shrink*/1); /* harmless if err */ -+ au_rw_write_unlock(&tmp->di_rwsem); -+ au_di_free(tmp); -+ if (unlikely(err)) -+ goto out; -+ -+out_dgen: -+ au_update_digen(dentry); -+out: -+ if (unlikely(err && !(dentry->d_flags & DCACHE_NFSFS_RENAMED))) { -+ AuIOErr("failed refreshing %pd, %d\n", dentry, err); -+ AuDbgDentry(dentry); -+ } -+ AuTraceErr(err); -+ return err; -+} -+ -+static int au_do_h_d_reval(struct dentry *h_dentry, unsigned int flags, -+ struct dentry *dentry, aufs_bindex_t bindex) -+{ -+ int err, valid; -+ -+ err = 0; -+ if (!(h_dentry->d_flags & DCACHE_OP_REVALIDATE)) -+ goto out; -+ -+ AuDbg("b%d\n", bindex); -+ /* -+ * gave up supporting LOOKUP_CREATE/OPEN for lower fs, -+ * due to whiteout and branch permission. -+ */ -+ flags &= ~(/*LOOKUP_PARENT |*/ LOOKUP_OPEN | LOOKUP_CREATE -+ | LOOKUP_FOLLOW | LOOKUP_EXCL); -+ /* it may return tri-state */ -+ valid = h_dentry->d_op->d_revalidate(h_dentry, flags); -+ -+ if (unlikely(valid < 0)) -+ err = valid; -+ else if (!valid) -+ err = -EINVAL; -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+/* todo: remove this */ -+static int h_d_revalidate(struct dentry *dentry, struct inode *inode, -+ unsigned int flags, int do_udba, int dirren) -+{ -+ int err; -+ umode_t mode, h_mode; -+ aufs_bindex_t bindex, btail, btop, ibs, ibe; -+ unsigned char plus, unhashed, is_root, h_plus, h_nfs, tmpfile; -+ struct inode *h_inode, *h_cached_inode; -+ struct dentry *h_dentry; -+ struct qstr *name, *h_name; -+ -+ err = 0; -+ plus = 0; -+ mode = 0; -+ ibs = -1; -+ ibe = -1; -+ unhashed = !!d_unhashed(dentry); -+ is_root = !!IS_ROOT(dentry); -+ name = &dentry->d_name; -+ tmpfile = au_di(dentry)->di_tmpfile; -+ -+ /* -+ * Theoretically, REVAL test should be unnecessary in case of -+ * {FS,I}NOTIFY. -+ * But {fs,i}notify doesn't fire some necessary events, -+ * IN_ATTRIB for atime/nlink/pageio -+ * Let's do REVAL test too. -+ */ -+ if (do_udba && inode) { -+ mode = (inode->i_mode & S_IFMT); -+ plus = (inode->i_nlink > 0); -+ ibs = au_ibtop(inode); -+ ibe = au_ibbot(inode); -+ } -+ -+ btop = au_dbtop(dentry); -+ btail = btop; -+ if (inode && S_ISDIR(inode->i_mode)) -+ btail = au_dbtaildir(dentry); -+ for (bindex = btop; bindex <= btail; bindex++) { -+ h_dentry = au_h_dptr(dentry, bindex); -+ if (!h_dentry) -+ continue; -+ -+ AuDbg("b%d, %pd\n", bindex, h_dentry); -+ h_nfs = !!au_test_nfs(h_dentry->d_sb); -+ spin_lock(&h_dentry->d_lock); -+ h_name = &h_dentry->d_name; -+ if (unlikely(do_udba -+ && !is_root -+ && ((!h_nfs -+ && (unhashed != !!d_unhashed(h_dentry) -+ || (!tmpfile && !dirren -+ && !au_qstreq(name, h_name)) -+ )) -+ || (h_nfs -+ && !(flags & LOOKUP_OPEN) -+ && (h_dentry->d_flags -+ & DCACHE_NFSFS_RENAMED))) -+ )) { -+ int h_unhashed; -+ -+ h_unhashed = d_unhashed(h_dentry); -+ spin_unlock(&h_dentry->d_lock); -+ AuDbg("unhash 0x%x 0x%x, %pd %pd\n", -+ unhashed, h_unhashed, dentry, h_dentry); -+ goto err; -+ } -+ spin_unlock(&h_dentry->d_lock); -+ -+ err = au_do_h_d_reval(h_dentry, flags, dentry, bindex); -+ if (unlikely(err)) -+ /* do not goto err, to keep the errno */ -+ break; -+ -+ /* todo: plink too? */ -+ if (!do_udba) -+ continue; -+ -+ /* UDBA tests */ -+ if (unlikely(!!inode != d_is_positive(h_dentry))) -+ goto err; -+ -+ h_inode = NULL; -+ if (d_is_positive(h_dentry)) -+ h_inode = d_inode(h_dentry); -+ h_plus = plus; -+ h_mode = mode; -+ h_cached_inode = h_inode; -+ if (h_inode) { -+ h_mode = (h_inode->i_mode & S_IFMT); -+ h_plus = (h_inode->i_nlink > 0); -+ } -+ if (inode && ibs <= bindex && bindex <= ibe) -+ h_cached_inode = au_h_iptr(inode, bindex); -+ -+ if (!h_nfs) { -+ if (unlikely(plus != h_plus && !tmpfile)) -+ goto err; -+ } else { -+ if (unlikely(!(h_dentry->d_flags & DCACHE_NFSFS_RENAMED) -+ && !is_root -+ && !IS_ROOT(h_dentry) -+ && unhashed != d_unhashed(h_dentry))) -+ goto err; -+ } -+ if (unlikely(mode != h_mode -+ || h_cached_inode != h_inode)) -+ goto err; -+ continue; -+ -+err: -+ err = -EINVAL; -+ break; -+ } -+ -+ AuTraceErr(err); -+ return err; -+} -+ -+/* todo: consolidate with do_refresh() and au_reval_for_attr() */ -+static int simple_reval_dpath(struct dentry *dentry, unsigned int sigen) -+{ -+ int err; -+ struct dentry *parent; -+ -+ if (!au_digen_test(dentry, sigen)) -+ return 0; -+ -+ parent = dget_parent(dentry); -+ di_read_lock_parent(parent, AuLock_IR); -+ AuDebugOn(au_digen_test(parent, sigen)); -+ au_dbg_verify_gen(parent, sigen); -+ err = au_refresh_dentry(dentry, parent); -+ di_read_unlock(parent, AuLock_IR); -+ dput(parent); -+ AuTraceErr(err); -+ return err; -+} -+ -+int au_reval_dpath(struct dentry *dentry, unsigned int sigen) -+{ -+ int err; -+ struct dentry *d, *parent; -+ -+ if (!au_ftest_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIR)) -+ return simple_reval_dpath(dentry, sigen); -+ -+ /* slow loop, keep it simple and stupid */ -+ /* cf: au_cpup_dirs() */ -+ err = 0; -+ parent = NULL; -+ while (au_digen_test(dentry, sigen)) { -+ d = dentry; -+ while (1) { -+ dput(parent); -+ parent = dget_parent(d); -+ if (!au_digen_test(parent, sigen)) -+ break; -+ d = parent; -+ } -+ -+ if (d != dentry) -+ di_write_lock_child2(d); -+ -+ /* someone might update our dentry while we were sleeping */ -+ if (au_digen_test(d, sigen)) { -+ /* -+ * todo: consolidate with simple_reval_dpath(), -+ * do_refresh() and au_reval_for_attr(). -+ */ -+ di_read_lock_parent(parent, AuLock_IR); -+ err = au_refresh_dentry(d, parent); -+ di_read_unlock(parent, AuLock_IR); -+ } -+ -+ if (d != dentry) -+ di_write_unlock(d); -+ dput(parent); -+ if (unlikely(err)) -+ break; -+ } -+ -+ return err; -+} -+ -+/* -+ * if valid returns 1, otherwise 0. -+ */ -+static int aufs_d_revalidate(struct dentry *dentry, unsigned int flags) -+{ -+ int valid, err; -+ unsigned int sigen; -+ unsigned char do_udba, dirren; -+ struct super_block *sb; -+ struct inode *inode; -+ -+ /* todo: support rcu-walk? */ -+ if (flags & LOOKUP_RCU) -+ return -ECHILD; -+ -+ valid = 0; -+ if (unlikely(!au_di(dentry))) -+ goto out; -+ -+ valid = 1; -+ sb = dentry->d_sb; -+ /* -+ * todo: very ugly -+ * i_mutex of parent dir may be held, -+ * but we should not return 'invalid' due to busy. -+ */ -+ err = aufs_read_lock(dentry, AuLock_FLUSH | AuLock_DW | AuLock_NOPLM); -+ if (unlikely(err)) { -+ valid = err; -+ AuTraceErr(err); -+ goto out; -+ } -+ inode = NULL; -+ if (d_really_is_positive(dentry)) -+ inode = d_inode(dentry); -+ if (unlikely(inode && au_is_bad_inode(inode))) { -+ err = -EINVAL; -+ AuTraceErr(err); -+ goto out_dgrade; -+ } -+ if (unlikely(au_dbrange_test(dentry))) { -+ err = -EINVAL; -+ AuTraceErr(err); -+ goto out_dgrade; -+ } -+ -+ sigen = au_sigen(sb); -+ if (au_digen_test(dentry, sigen)) { -+ AuDebugOn(IS_ROOT(dentry)); -+ err = au_reval_dpath(dentry, sigen); -+ if (unlikely(err)) { -+ AuTraceErr(err); -+ goto out_dgrade; -+ } -+ } -+ di_downgrade_lock(dentry, AuLock_IR); -+ -+ err = -EINVAL; -+ if (!(flags & (LOOKUP_OPEN | LOOKUP_EMPTY)) -+ && inode -+ && !(inode->i_state && I_LINKABLE) -+ && (IS_DEADDIR(inode) || !inode->i_nlink)) { -+ AuTraceErr(err); -+ goto out_inval; -+ } -+ -+ do_udba = !au_opt_test(au_mntflags(sb), UDBA_NONE); -+ if (do_udba && inode) { -+ aufs_bindex_t btop = au_ibtop(inode); -+ struct inode *h_inode; -+ -+ if (btop >= 0) { -+ h_inode = au_h_iptr(inode, btop); -+ if (h_inode && au_test_higen(inode, h_inode)) { -+ AuTraceErr(err); -+ goto out_inval; -+ } -+ } -+ } -+ -+ dirren = !!au_opt_test(au_mntflags(sb), DIRREN); -+ err = h_d_revalidate(dentry, inode, flags, do_udba, dirren); -+ if (unlikely(!err && do_udba && au_dbtop(dentry) < 0)) { -+ err = -EIO; -+ AuDbg("both of real entry and whiteout found, %p, err %d\n", -+ dentry, err); -+ } -+ goto out_inval; -+ -+out_dgrade: -+ di_downgrade_lock(dentry, AuLock_IR); -+out_inval: -+ aufs_read_unlock(dentry, AuLock_IR); -+ AuTraceErr(err); -+ valid = !err; -+out: -+ if (!valid) { -+ AuDbg("%pd invalid, %d\n", dentry, valid); -+ d_drop(dentry); -+ } -+ return valid; -+} -+ -+static void aufs_d_release(struct dentry *dentry) -+{ -+ if (au_di(dentry)) { -+ au_di_fin(dentry); -+ au_hn_di_reinit(dentry); -+ } -+} -+ -+const struct dentry_operations aufs_dop = { -+ .d_revalidate = aufs_d_revalidate, -+ .d_weak_revalidate = aufs_d_revalidate, -+ .d_release = aufs_d_release -+}; -+ -+/* aufs_dop without d_revalidate */ -+const struct dentry_operations aufs_dop_noreval = { -+ .d_release = aufs_d_release -+}; -diff -Nurp linux-5.10-rc6/fs/aufs/dentry.h linux-5.10-rc6.aufs/fs/aufs/dentry.h ---- linux-5.10-rc6/fs/aufs/dentry.h 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/dentry.h 2020-12-02 21:19:51.880036698 +0200 -@@ -0,0 +1,255 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * lookup and dentry operations -+ */ -+ -+#ifndef __AUFS_DENTRY_H__ -+#define __AUFS_DENTRY_H__ -+ -+#ifdef __KERNEL__ -+ -+#include -+#include "dirren.h" -+#include "rwsem.h" -+ -+struct au_hdentry { -+ struct dentry *hd_dentry; -+ aufs_bindex_t hd_id; -+}; -+ -+struct au_dinfo { -+ atomic_t di_generation; -+ -+ struct au_rwsem di_rwsem; -+ aufs_bindex_t di_btop, di_bbot, di_bwh, di_bdiropq; -+ unsigned char di_tmpfile; /* to allow the different name */ -+ struct au_hdentry *di_hdentry; -+ struct rcu_head rcu; -+} ____cacheline_aligned_in_smp; -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* flags for au_lkup_dentry() */ -+#define AuLkup_ALLOW_NEG 1 -+#define AuLkup_IGNORE_PERM (1 << 1) -+#define AuLkup_DIRREN (1 << 2) -+#define au_ftest_lkup(flags, name) ((flags) & AuLkup_##name) -+#define au_fset_lkup(flags, name) \ -+ do { (flags) |= AuLkup_##name; } while (0) -+#define au_fclr_lkup(flags, name) \ -+ do { (flags) &= ~AuLkup_##name; } while (0) -+ -+#ifndef CONFIG_AUFS_DIRREN -+#undef AuLkup_DIRREN -+#define AuLkup_DIRREN 0 -+#endif -+ -+struct au_do_lookup_args { -+ unsigned int flags; -+ mode_t type; -+ struct qstr whname, *name; -+ struct au_dr_lookup dirren; -+}; -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* dentry.c */ -+extern const struct dentry_operations aufs_dop, aufs_dop_noreval; -+struct au_branch; -+struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent); -+int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir, -+ struct dentry *h_parent, struct au_branch *br); -+ -+int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t btop, -+ unsigned int flags); -+int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex, int wh); -+int au_refresh_dentry(struct dentry *dentry, struct dentry *parent); -+int au_reval_dpath(struct dentry *dentry, unsigned int sigen); -+void au_refresh_dop(struct dentry *dentry, int force_reval); -+ -+/* dinfo.c */ -+void au_di_init_once(void *_di); -+struct au_dinfo *au_di_alloc(struct super_block *sb, unsigned int lsc); -+void au_di_free(struct au_dinfo *dinfo); -+void au_di_swap(struct au_dinfo *a, struct au_dinfo *b); -+void au_di_cp(struct au_dinfo *dst, struct au_dinfo *src); -+int au_di_init(struct dentry *dentry); -+void au_di_fin(struct dentry *dentry); -+int au_di_realloc(struct au_dinfo *dinfo, int nbr, int may_shrink); -+ -+void di_read_lock(struct dentry *d, int flags, unsigned int lsc); -+void di_read_unlock(struct dentry *d, int flags); -+void di_downgrade_lock(struct dentry *d, int flags); -+void di_write_lock(struct dentry *d, unsigned int lsc); -+void di_write_unlock(struct dentry *d); -+void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir); -+void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir); -+void di_write_unlock2(struct dentry *d1, struct dentry *d2); -+ -+struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex); -+struct dentry *au_h_d_alias(struct dentry *dentry, aufs_bindex_t bindex); -+aufs_bindex_t au_dbtail(struct dentry *dentry); -+aufs_bindex_t au_dbtaildir(struct dentry *dentry); -+ -+void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex, -+ struct dentry *h_dentry); -+int au_digen_test(struct dentry *dentry, unsigned int sigen); -+int au_dbrange_test(struct dentry *dentry); -+void au_update_digen(struct dentry *dentry); -+void au_update_dbrange(struct dentry *dentry, int do_put_zero); -+void au_update_dbtop(struct dentry *dentry); -+void au_update_dbbot(struct dentry *dentry); -+int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry); -+ -+/* ---------------------------------------------------------------------- */ -+ -+static inline struct au_dinfo *au_di(struct dentry *dentry) -+{ -+ return dentry->d_fsdata; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* lock subclass for dinfo */ -+enum { -+ AuLsc_DI_CHILD, /* child first */ -+ AuLsc_DI_CHILD2, /* rename(2), link(2), and cpup at hnotify */ -+ AuLsc_DI_CHILD3, /* copyup dirs */ -+ AuLsc_DI_PARENT, -+ AuLsc_DI_PARENT2, -+ AuLsc_DI_PARENT3, -+ AuLsc_DI_TMP /* temp for replacing dinfo */ -+}; -+ -+/* -+ * di_read_lock_child, di_write_lock_child, -+ * di_read_lock_child2, di_write_lock_child2, -+ * di_read_lock_child3, di_write_lock_child3, -+ * di_read_lock_parent, di_write_lock_parent, -+ * di_read_lock_parent2, di_write_lock_parent2, -+ * di_read_lock_parent3, di_write_lock_parent3, -+ */ -+#define AuReadLockFunc(name, lsc) \ -+static inline void di_read_lock_##name(struct dentry *d, int flags) \ -+{ di_read_lock(d, flags, AuLsc_DI_##lsc); } -+ -+#define AuWriteLockFunc(name, lsc) \ -+static inline void di_write_lock_##name(struct dentry *d) \ -+{ di_write_lock(d, AuLsc_DI_##lsc); } -+ -+#define AuRWLockFuncs(name, lsc) \ -+ AuReadLockFunc(name, lsc) \ -+ AuWriteLockFunc(name, lsc) -+ -+AuRWLockFuncs(child, CHILD); -+AuRWLockFuncs(child2, CHILD2); -+AuRWLockFuncs(child3, CHILD3); -+AuRWLockFuncs(parent, PARENT); -+AuRWLockFuncs(parent2, PARENT2); -+AuRWLockFuncs(parent3, PARENT3); -+ -+#undef AuReadLockFunc -+#undef AuWriteLockFunc -+#undef AuRWLockFuncs -+ -+#define DiMustNoWaiters(d) AuRwMustNoWaiters(&au_di(d)->di_rwsem) -+#define DiMustAnyLock(d) AuRwMustAnyLock(&au_di(d)->di_rwsem) -+#define DiMustWriteLock(d) AuRwMustWriteLock(&au_di(d)->di_rwsem) -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* todo: memory barrier? */ -+static inline unsigned int au_digen(struct dentry *d) -+{ -+ return atomic_read(&au_di(d)->di_generation); -+} -+ -+static inline void au_h_dentry_init(struct au_hdentry *hdentry) -+{ -+ hdentry->hd_dentry = NULL; -+} -+ -+static inline struct au_hdentry *au_hdentry(struct au_dinfo *di, -+ aufs_bindex_t bindex) -+{ -+ return di->di_hdentry + bindex; -+} -+ -+static inline void au_hdput(struct au_hdentry *hd) -+{ -+ if (hd) -+ dput(hd->hd_dentry); -+} -+ -+static inline aufs_bindex_t au_dbtop(struct dentry *dentry) -+{ -+ DiMustAnyLock(dentry); -+ return au_di(dentry)->di_btop; -+} -+ -+static inline aufs_bindex_t au_dbbot(struct dentry *dentry) -+{ -+ DiMustAnyLock(dentry); -+ return au_di(dentry)->di_bbot; -+} -+ -+static inline aufs_bindex_t au_dbwh(struct dentry *dentry) -+{ -+ DiMustAnyLock(dentry); -+ return au_di(dentry)->di_bwh; -+} -+ -+static inline aufs_bindex_t au_dbdiropq(struct dentry *dentry) -+{ -+ DiMustAnyLock(dentry); -+ return au_di(dentry)->di_bdiropq; -+} -+ -+/* todo: hard/soft set? */ -+static inline void au_set_dbtop(struct dentry *dentry, aufs_bindex_t bindex) -+{ -+ DiMustWriteLock(dentry); -+ au_di(dentry)->di_btop = bindex; -+} -+ -+static inline void au_set_dbbot(struct dentry *dentry, aufs_bindex_t bindex) -+{ -+ DiMustWriteLock(dentry); -+ au_di(dentry)->di_bbot = bindex; -+} -+ -+static inline void au_set_dbwh(struct dentry *dentry, aufs_bindex_t bindex) -+{ -+ DiMustWriteLock(dentry); -+ /* dbwh can be outside of btop - bbot range */ -+ au_di(dentry)->di_bwh = bindex; -+} -+ -+static inline void au_set_dbdiropq(struct dentry *dentry, aufs_bindex_t bindex) -+{ -+ DiMustWriteLock(dentry); -+ au_di(dentry)->di_bdiropq = bindex; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+#ifdef CONFIG_AUFS_HNOTIFY -+static inline void au_digen_dec(struct dentry *d) -+{ -+ atomic_dec(&au_di(d)->di_generation); -+} -+ -+static inline void au_hn_di_reinit(struct dentry *dentry) -+{ -+ dentry->d_fsdata = NULL; -+} -+#else -+AuStubVoid(au_hn_di_reinit, struct dentry *dentry __maybe_unused) -+#endif /* CONFIG_AUFS_HNOTIFY */ -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_DENTRY_H__ */ -diff -Nurp linux-5.10-rc6/fs/aufs/dinfo.c linux-5.10-rc6.aufs/fs/aufs/dinfo.c ---- linux-5.10-rc6/fs/aufs/dinfo.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/dinfo.c 2020-12-02 21:19:51.880036698 +0200 -@@ -0,0 +1,541 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * dentry private data -+ */ -+ -+#include "aufs.h" -+ -+void au_di_init_once(void *_dinfo) -+{ -+ struct au_dinfo *dinfo = _dinfo; -+ -+ au_rw_init(&dinfo->di_rwsem); -+} -+ -+struct au_dinfo *au_di_alloc(struct super_block *sb, unsigned int lsc) -+{ -+ struct au_dinfo *dinfo; -+ int nbr, i; -+ -+ dinfo = au_cache_alloc_dinfo(); -+ if (unlikely(!dinfo)) -+ goto out; -+ -+ nbr = au_sbbot(sb) + 1; -+ if (nbr <= 0) -+ nbr = 1; -+ dinfo->di_hdentry = kcalloc(nbr, sizeof(*dinfo->di_hdentry), GFP_NOFS); -+ if (dinfo->di_hdentry) { -+ au_rw_write_lock_nested(&dinfo->di_rwsem, lsc); -+ dinfo->di_btop = -1; -+ dinfo->di_bbot = -1; -+ dinfo->di_bwh = -1; -+ dinfo->di_bdiropq = -1; -+ dinfo->di_tmpfile = 0; -+ for (i = 0; i < nbr; i++) -+ dinfo->di_hdentry[i].hd_id = -1; -+ goto out; -+ } -+ -+ au_cache_free_dinfo(dinfo); -+ dinfo = NULL; -+ -+out: -+ return dinfo; -+} -+ -+void au_di_free(struct au_dinfo *dinfo) -+{ -+ struct au_hdentry *p; -+ aufs_bindex_t bbot, bindex; -+ -+ /* dentry may not be revalidated */ -+ bindex = dinfo->di_btop; -+ if (bindex >= 0) { -+ bbot = dinfo->di_bbot; -+ p = au_hdentry(dinfo, bindex); -+ while (bindex++ <= bbot) -+ au_hdput(p++); -+ } -+ au_kfree_try_rcu(dinfo->di_hdentry); -+ au_cache_free_dinfo(dinfo); -+} -+ -+void au_di_swap(struct au_dinfo *a, struct au_dinfo *b) -+{ -+ struct au_hdentry *p; -+ aufs_bindex_t bi; -+ -+ AuRwMustWriteLock(&a->di_rwsem); -+ AuRwMustWriteLock(&b->di_rwsem); -+ -+#define DiSwap(v, name) \ -+ do { \ -+ v = a->di_##name; \ -+ a->di_##name = b->di_##name; \ -+ b->di_##name = v; \ -+ } while (0) -+ -+ DiSwap(p, hdentry); -+ DiSwap(bi, btop); -+ DiSwap(bi, bbot); -+ DiSwap(bi, bwh); -+ DiSwap(bi, bdiropq); -+ /* smp_mb(); */ -+ -+#undef DiSwap -+} -+ -+void au_di_cp(struct au_dinfo *dst, struct au_dinfo *src) -+{ -+ AuRwMustWriteLock(&dst->di_rwsem); -+ AuRwMustWriteLock(&src->di_rwsem); -+ -+ dst->di_btop = src->di_btop; -+ dst->di_bbot = src->di_bbot; -+ dst->di_bwh = src->di_bwh; -+ dst->di_bdiropq = src->di_bdiropq; -+ /* smp_mb(); */ -+} -+ -+int au_di_init(struct dentry *dentry) -+{ -+ int err; -+ struct super_block *sb; -+ struct au_dinfo *dinfo; -+ -+ err = 0; -+ sb = dentry->d_sb; -+ dinfo = au_di_alloc(sb, AuLsc_DI_CHILD); -+ if (dinfo) { -+ atomic_set(&dinfo->di_generation, au_sigen(sb)); -+ /* smp_mb(); */ /* atomic_set */ -+ dentry->d_fsdata = dinfo; -+ } else -+ err = -ENOMEM; -+ -+ return err; -+} -+ -+void au_di_fin(struct dentry *dentry) -+{ -+ struct au_dinfo *dinfo; -+ -+ dinfo = au_di(dentry); -+ AuRwDestroy(&dinfo->di_rwsem); -+ au_di_free(dinfo); -+} -+ -+int au_di_realloc(struct au_dinfo *dinfo, int nbr, int may_shrink) -+{ -+ int err, sz; -+ struct au_hdentry *hdp; -+ -+ AuRwMustWriteLock(&dinfo->di_rwsem); -+ -+ err = -ENOMEM; -+ sz = sizeof(*hdp) * (dinfo->di_bbot + 1); -+ if (!sz) -+ sz = sizeof(*hdp); -+ hdp = au_kzrealloc(dinfo->di_hdentry, sz, sizeof(*hdp) * nbr, GFP_NOFS, -+ may_shrink); -+ if (hdp) { -+ dinfo->di_hdentry = hdp; -+ err = 0; -+ } -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static void do_ii_write_lock(struct inode *inode, unsigned int lsc) -+{ -+ switch (lsc) { -+ case AuLsc_DI_CHILD: -+ ii_write_lock_child(inode); -+ break; -+ case AuLsc_DI_CHILD2: -+ ii_write_lock_child2(inode); -+ break; -+ case AuLsc_DI_CHILD3: -+ ii_write_lock_child3(inode); -+ break; -+ case AuLsc_DI_PARENT: -+ ii_write_lock_parent(inode); -+ break; -+ case AuLsc_DI_PARENT2: -+ ii_write_lock_parent2(inode); -+ break; -+ case AuLsc_DI_PARENT3: -+ ii_write_lock_parent3(inode); -+ break; -+ default: -+ BUG(); -+ } -+} -+ -+static void do_ii_read_lock(struct inode *inode, unsigned int lsc) -+{ -+ switch (lsc) { -+ case AuLsc_DI_CHILD: -+ ii_read_lock_child(inode); -+ break; -+ case AuLsc_DI_CHILD2: -+ ii_read_lock_child2(inode); -+ break; -+ case AuLsc_DI_CHILD3: -+ ii_read_lock_child3(inode); -+ break; -+ case AuLsc_DI_PARENT: -+ ii_read_lock_parent(inode); -+ break; -+ case AuLsc_DI_PARENT2: -+ ii_read_lock_parent2(inode); -+ break; -+ case AuLsc_DI_PARENT3: -+ ii_read_lock_parent3(inode); -+ break; -+ default: -+ BUG(); -+ } -+} -+ -+void di_read_lock(struct dentry *d, int flags, unsigned int lsc) -+{ -+ struct inode *inode; -+ -+ au_rw_read_lock_nested(&au_di(d)->di_rwsem, lsc); -+ if (d_really_is_positive(d)) { -+ inode = d_inode(d); -+ if (au_ftest_lock(flags, IW)) -+ do_ii_write_lock(inode, lsc); -+ else if (au_ftest_lock(flags, IR)) -+ do_ii_read_lock(inode, lsc); -+ } -+} -+ -+void di_read_unlock(struct dentry *d, int flags) -+{ -+ struct inode *inode; -+ -+ if (d_really_is_positive(d)) { -+ inode = d_inode(d); -+ if (au_ftest_lock(flags, IW)) { -+ au_dbg_verify_dinode(d); -+ ii_write_unlock(inode); -+ } else if (au_ftest_lock(flags, IR)) { -+ au_dbg_verify_dinode(d); -+ ii_read_unlock(inode); -+ } -+ } -+ au_rw_read_unlock(&au_di(d)->di_rwsem); -+} -+ -+void di_downgrade_lock(struct dentry *d, int flags) -+{ -+ if (d_really_is_positive(d) && au_ftest_lock(flags, IR)) -+ ii_downgrade_lock(d_inode(d)); -+ au_rw_dgrade_lock(&au_di(d)->di_rwsem); -+} -+ -+void di_write_lock(struct dentry *d, unsigned int lsc) -+{ -+ au_rw_write_lock_nested(&au_di(d)->di_rwsem, lsc); -+ if (d_really_is_positive(d)) -+ do_ii_write_lock(d_inode(d), lsc); -+} -+ -+void di_write_unlock(struct dentry *d) -+{ -+ au_dbg_verify_dinode(d); -+ if (d_really_is_positive(d)) -+ ii_write_unlock(d_inode(d)); -+ au_rw_write_unlock(&au_di(d)->di_rwsem); -+} -+ -+void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir) -+{ -+ AuDebugOn(d1 == d2 -+ || d_inode(d1) == d_inode(d2) -+ || d1->d_sb != d2->d_sb); -+ -+ if ((isdir && au_test_subdir(d1, d2)) -+ || d1 < d2) { -+ di_write_lock_child(d1); -+ di_write_lock_child2(d2); -+ } else { -+ di_write_lock_child(d2); -+ di_write_lock_child2(d1); -+ } -+} -+ -+void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir) -+{ -+ AuDebugOn(d1 == d2 -+ || d_inode(d1) == d_inode(d2) -+ || d1->d_sb != d2->d_sb); -+ -+ if ((isdir && au_test_subdir(d1, d2)) -+ || d1 < d2) { -+ di_write_lock_parent(d1); -+ di_write_lock_parent2(d2); -+ } else { -+ di_write_lock_parent(d2); -+ di_write_lock_parent2(d1); -+ } -+} -+ -+void di_write_unlock2(struct dentry *d1, struct dentry *d2) -+{ -+ di_write_unlock(d1); -+ if (d_inode(d1) == d_inode(d2)) -+ au_rw_write_unlock(&au_di(d2)->di_rwsem); -+ else -+ di_write_unlock(d2); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex) -+{ -+ struct dentry *d; -+ -+ DiMustAnyLock(dentry); -+ -+ if (au_dbtop(dentry) < 0 || bindex < au_dbtop(dentry)) -+ return NULL; -+ AuDebugOn(bindex < 0); -+ d = au_hdentry(au_di(dentry), bindex)->hd_dentry; -+ AuDebugOn(d && au_dcount(d) <= 0); -+ return d; -+} -+ -+/* -+ * extended version of au_h_dptr(). -+ * returns a hashed and positive (or linkable) h_dentry in bindex, NULL, or -+ * error. -+ */ -+struct dentry *au_h_d_alias(struct dentry *dentry, aufs_bindex_t bindex) -+{ -+ struct dentry *h_dentry; -+ struct inode *inode, *h_inode; -+ -+ AuDebugOn(d_really_is_negative(dentry)); -+ -+ h_dentry = NULL; -+ if (au_dbtop(dentry) <= bindex -+ && bindex <= au_dbbot(dentry)) -+ h_dentry = au_h_dptr(dentry, bindex); -+ if (h_dentry && !au_d_linkable(h_dentry)) { -+ dget(h_dentry); -+ goto out; /* success */ -+ } -+ -+ inode = d_inode(dentry); -+ AuDebugOn(bindex < au_ibtop(inode)); -+ AuDebugOn(au_ibbot(inode) < bindex); -+ h_inode = au_h_iptr(inode, bindex); -+ h_dentry = d_find_alias(h_inode); -+ if (h_dentry) { -+ if (!IS_ERR(h_dentry)) { -+ if (!au_d_linkable(h_dentry)) -+ goto out; /* success */ -+ dput(h_dentry); -+ } else -+ goto out; -+ } -+ -+ if (au_opt_test(au_mntflags(dentry->d_sb), PLINK)) { -+ h_dentry = au_plink_lkup(inode, bindex); -+ AuDebugOn(!h_dentry); -+ if (!IS_ERR(h_dentry)) { -+ if (!au_d_hashed_positive(h_dentry)) -+ goto out; /* success */ -+ dput(h_dentry); -+ h_dentry = NULL; -+ } -+ } -+ -+out: -+ AuDbgDentry(h_dentry); -+ return h_dentry; -+} -+ -+aufs_bindex_t au_dbtail(struct dentry *dentry) -+{ -+ aufs_bindex_t bbot, bwh; -+ -+ bbot = au_dbbot(dentry); -+ if (0 <= bbot) { -+ bwh = au_dbwh(dentry); -+ if (!bwh) -+ return bwh; -+ if (0 < bwh && bwh < bbot) -+ return bwh - 1; -+ } -+ return bbot; -+} -+ -+aufs_bindex_t au_dbtaildir(struct dentry *dentry) -+{ -+ aufs_bindex_t bbot, bopq; -+ -+ bbot = au_dbtail(dentry); -+ if (0 <= bbot) { -+ bopq = au_dbdiropq(dentry); -+ if (0 <= bopq && bopq < bbot) -+ bbot = bopq; -+ } -+ return bbot; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex, -+ struct dentry *h_dentry) -+{ -+ struct au_dinfo *dinfo; -+ struct au_hdentry *hd; -+ struct au_branch *br; -+ -+ DiMustWriteLock(dentry); -+ -+ dinfo = au_di(dentry); -+ hd = au_hdentry(dinfo, bindex); -+ au_hdput(hd); -+ hd->hd_dentry = h_dentry; -+ if (h_dentry) { -+ br = au_sbr(dentry->d_sb, bindex); -+ hd->hd_id = br->br_id; -+ } -+} -+ -+int au_dbrange_test(struct dentry *dentry) -+{ -+ int err; -+ aufs_bindex_t btop, bbot; -+ -+ err = 0; -+ btop = au_dbtop(dentry); -+ bbot = au_dbbot(dentry); -+ if (btop >= 0) -+ AuDebugOn(bbot < 0 && btop > bbot); -+ else { -+ err = -EIO; -+ AuDebugOn(bbot >= 0); -+ } -+ -+ return err; -+} -+ -+int au_digen_test(struct dentry *dentry, unsigned int sigen) -+{ -+ int err; -+ -+ err = 0; -+ if (unlikely(au_digen(dentry) != sigen -+ || au_iigen_test(d_inode(dentry), sigen))) -+ err = -EIO; -+ -+ return err; -+} -+ -+void au_update_digen(struct dentry *dentry) -+{ -+ atomic_set(&au_di(dentry)->di_generation, au_sigen(dentry->d_sb)); -+ /* smp_mb(); */ /* atomic_set */ -+} -+ -+void au_update_dbrange(struct dentry *dentry, int do_put_zero) -+{ -+ struct au_dinfo *dinfo; -+ struct dentry *h_d; -+ struct au_hdentry *hdp; -+ aufs_bindex_t bindex, bbot; -+ -+ DiMustWriteLock(dentry); -+ -+ dinfo = au_di(dentry); -+ if (!dinfo || dinfo->di_btop < 0) -+ return; -+ -+ if (do_put_zero) { -+ bbot = dinfo->di_bbot; -+ bindex = dinfo->di_btop; -+ hdp = au_hdentry(dinfo, bindex); -+ for (; bindex <= bbot; bindex++, hdp++) { -+ h_d = hdp->hd_dentry; -+ if (h_d && d_is_negative(h_d)) -+ au_set_h_dptr(dentry, bindex, NULL); -+ } -+ } -+ -+ dinfo->di_btop = 0; -+ hdp = au_hdentry(dinfo, dinfo->di_btop); -+ for (; dinfo->di_btop <= dinfo->di_bbot; dinfo->di_btop++, hdp++) -+ if (hdp->hd_dentry) -+ break; -+ if (dinfo->di_btop > dinfo->di_bbot) { -+ dinfo->di_btop = -1; -+ dinfo->di_bbot = -1; -+ return; -+ } -+ -+ hdp = au_hdentry(dinfo, dinfo->di_bbot); -+ for (; dinfo->di_bbot >= 0; dinfo->di_bbot--, hdp--) -+ if (hdp->hd_dentry) -+ break; -+ AuDebugOn(dinfo->di_btop > dinfo->di_bbot || dinfo->di_bbot < 0); -+} -+ -+void au_update_dbtop(struct dentry *dentry) -+{ -+ aufs_bindex_t bindex, bbot; -+ struct dentry *h_dentry; -+ -+ bbot = au_dbbot(dentry); -+ for (bindex = au_dbtop(dentry); bindex <= bbot; bindex++) { -+ h_dentry = au_h_dptr(dentry, bindex); -+ if (!h_dentry) -+ continue; -+ if (d_is_positive(h_dentry)) { -+ au_set_dbtop(dentry, bindex); -+ return; -+ } -+ au_set_h_dptr(dentry, bindex, NULL); -+ } -+} -+ -+void au_update_dbbot(struct dentry *dentry) -+{ -+ aufs_bindex_t bindex, btop; -+ struct dentry *h_dentry; -+ -+ btop = au_dbtop(dentry); -+ for (bindex = au_dbbot(dentry); bindex >= btop; bindex--) { -+ h_dentry = au_h_dptr(dentry, bindex); -+ if (!h_dentry) -+ continue; -+ if (d_is_positive(h_dentry)) { -+ au_set_dbbot(dentry, bindex); -+ return; -+ } -+ au_set_h_dptr(dentry, bindex, NULL); -+ } -+} -+ -+int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry) -+{ -+ aufs_bindex_t bindex, bbot; -+ -+ bbot = au_dbbot(dentry); -+ for (bindex = au_dbtop(dentry); bindex <= bbot; bindex++) -+ if (au_h_dptr(dentry, bindex) == h_dentry) -+ return bindex; -+ return -1; -+} -diff -Nurp linux-5.10-rc6/fs/aufs/dir.c linux-5.10-rc6.aufs/fs/aufs/dir.c ---- linux-5.10-rc6/fs/aufs/dir.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/dir.c 2020-12-02 21:19:51.881036743 +0200 -@@ -0,0 +1,750 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * directory operations -+ */ -+ -+#include -+#include -+#include "aufs.h" -+ -+void au_add_nlink(struct inode *dir, struct inode *h_dir) -+{ -+ unsigned int nlink; -+ -+ AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode)); -+ -+ nlink = dir->i_nlink; -+ nlink += h_dir->i_nlink - 2; -+ if (h_dir->i_nlink < 2) -+ nlink += 2; -+ smp_mb(); /* for i_nlink */ -+ /* 0 can happen in revaliding */ -+ set_nlink(dir, nlink); -+} -+ -+void au_sub_nlink(struct inode *dir, struct inode *h_dir) -+{ -+ unsigned int nlink; -+ -+ AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode)); -+ -+ nlink = dir->i_nlink; -+ nlink -= h_dir->i_nlink - 2; -+ if (h_dir->i_nlink < 2) -+ nlink -= 2; -+ smp_mb(); /* for i_nlink */ -+ /* nlink == 0 means the branch-fs is broken */ -+ set_nlink(dir, nlink); -+} -+ -+loff_t au_dir_size(struct file *file, struct dentry *dentry) -+{ -+ loff_t sz; -+ aufs_bindex_t bindex, bbot; -+ struct file *h_file; -+ struct dentry *h_dentry; -+ -+ sz = 0; -+ if (file) { -+ AuDebugOn(!d_is_dir(file->f_path.dentry)); -+ -+ bbot = au_fbbot_dir(file); -+ for (bindex = au_fbtop(file); -+ bindex <= bbot && sz < KMALLOC_MAX_SIZE; -+ bindex++) { -+ h_file = au_hf_dir(file, bindex); -+ if (h_file && file_inode(h_file)) -+ sz += vfsub_f_size_read(h_file); -+ } -+ } else { -+ AuDebugOn(!dentry); -+ AuDebugOn(!d_is_dir(dentry)); -+ -+ bbot = au_dbtaildir(dentry); -+ for (bindex = au_dbtop(dentry); -+ bindex <= bbot && sz < KMALLOC_MAX_SIZE; -+ bindex++) { -+ h_dentry = au_h_dptr(dentry, bindex); -+ if (h_dentry && d_is_positive(h_dentry)) -+ sz += i_size_read(d_inode(h_dentry)); -+ } -+ } -+ if (sz < KMALLOC_MAX_SIZE) -+ sz = roundup_pow_of_two(sz); -+ if (sz > KMALLOC_MAX_SIZE) -+ sz = KMALLOC_MAX_SIZE; -+ else if (sz < NAME_MAX) { -+ BUILD_BUG_ON(AUFS_RDBLK_DEF < NAME_MAX); -+ sz = AUFS_RDBLK_DEF; -+ } -+ return sz; -+} -+ -+struct au_dir_ts_arg { -+ struct dentry *dentry; -+ aufs_bindex_t brid; -+}; -+ -+static void au_do_dir_ts(void *arg) -+{ -+ struct au_dir_ts_arg *a = arg; -+ struct au_dtime dt; -+ struct path h_path; -+ struct inode *dir, *h_dir; -+ struct super_block *sb; -+ struct au_branch *br; -+ struct au_hinode *hdir; -+ int err; -+ aufs_bindex_t btop, bindex; -+ -+ sb = a->dentry->d_sb; -+ if (d_really_is_negative(a->dentry)) -+ goto out; -+ /* no dir->i_mutex lock */ -+ aufs_read_lock(a->dentry, AuLock_DW); /* noflush */ -+ -+ dir = d_inode(a->dentry); -+ btop = au_ibtop(dir); -+ bindex = au_br_index(sb, a->brid); -+ if (bindex < btop) -+ goto out_unlock; -+ -+ br = au_sbr(sb, bindex); -+ h_path.dentry = au_h_dptr(a->dentry, bindex); -+ if (!h_path.dentry) -+ goto out_unlock; -+ h_path.mnt = au_br_mnt(br); -+ au_dtime_store(&dt, a->dentry, &h_path); -+ -+ br = au_sbr(sb, btop); -+ if (!au_br_writable(br->br_perm)) -+ goto out_unlock; -+ h_path.dentry = au_h_dptr(a->dentry, btop); -+ h_path.mnt = au_br_mnt(br); -+ err = vfsub_mnt_want_write(h_path.mnt); -+ if (err) -+ goto out_unlock; -+ hdir = au_hi(dir, btop); -+ au_hn_inode_lock_nested(hdir, AuLsc_I_PARENT); -+ h_dir = au_h_iptr(dir, btop); -+ if (h_dir->i_nlink -+ && timespec64_compare(&h_dir->i_mtime, &dt.dt_mtime) < 0) { -+ dt.dt_h_path = h_path; -+ au_dtime_revert(&dt); -+ } -+ au_hn_inode_unlock(hdir); -+ vfsub_mnt_drop_write(h_path.mnt); -+ au_cpup_attr_timesizes(dir); -+ -+out_unlock: -+ aufs_read_unlock(a->dentry, AuLock_DW); -+out: -+ dput(a->dentry); -+ au_nwt_done(&au_sbi(sb)->si_nowait); -+ au_kfree_try_rcu(arg); -+} -+ -+void au_dir_ts(struct inode *dir, aufs_bindex_t bindex) -+{ -+ int perm, wkq_err; -+ aufs_bindex_t btop; -+ struct au_dir_ts_arg *arg; -+ struct dentry *dentry; -+ struct super_block *sb; -+ -+ IMustLock(dir); -+ -+ dentry = d_find_any_alias(dir); -+ AuDebugOn(!dentry); -+ sb = dentry->d_sb; -+ btop = au_ibtop(dir); -+ if (btop == bindex) { -+ au_cpup_attr_timesizes(dir); -+ goto out; -+ } -+ -+ perm = au_sbr_perm(sb, btop); -+ if (!au_br_writable(perm)) -+ goto out; -+ -+ arg = kmalloc(sizeof(*arg), GFP_NOFS); -+ if (!arg) -+ goto out; -+ -+ arg->dentry = dget(dentry); /* will be dput-ted by au_do_dir_ts() */ -+ arg->brid = au_sbr_id(sb, bindex); -+ wkq_err = au_wkq_nowait(au_do_dir_ts, arg, sb, /*flags*/0); -+ if (unlikely(wkq_err)) { -+ pr_err("wkq %d\n", wkq_err); -+ dput(dentry); -+ au_kfree_try_rcu(arg); -+ } -+ -+out: -+ dput(dentry); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int reopen_dir(struct file *file) -+{ -+ int err; -+ unsigned int flags; -+ aufs_bindex_t bindex, btail, btop; -+ struct dentry *dentry, *h_dentry; -+ struct file *h_file; -+ -+ /* open all lower dirs */ -+ dentry = file->f_path.dentry; -+ btop = au_dbtop(dentry); -+ for (bindex = au_fbtop(file); bindex < btop; bindex++) -+ au_set_h_fptr(file, bindex, NULL); -+ au_set_fbtop(file, btop); -+ -+ btail = au_dbtaildir(dentry); -+ for (bindex = au_fbbot_dir(file); btail < bindex; bindex--) -+ au_set_h_fptr(file, bindex, NULL); -+ au_set_fbbot_dir(file, btail); -+ -+ flags = vfsub_file_flags(file); -+ for (bindex = btop; bindex <= btail; bindex++) { -+ h_dentry = au_h_dptr(dentry, bindex); -+ if (!h_dentry) -+ continue; -+ h_file = au_hf_dir(file, bindex); -+ if (h_file) -+ continue; -+ -+ h_file = au_h_open(dentry, bindex, flags, file, /*force_wr*/0); -+ err = PTR_ERR(h_file); -+ if (IS_ERR(h_file)) -+ goto out; /* close all? */ -+ au_set_h_fptr(file, bindex, h_file); -+ } -+ au_update_figen(file); -+ /* todo: necessary? */ -+ /* file->f_ra = h_file->f_ra; */ -+ err = 0; -+ -+out: -+ return err; -+} -+ -+static int do_open_dir(struct file *file, int flags, struct file *h_file) -+{ -+ int err; -+ aufs_bindex_t bindex, btail; -+ struct dentry *dentry, *h_dentry; -+ struct vfsmount *mnt; -+ -+ FiMustWriteLock(file); -+ AuDebugOn(h_file); -+ -+ err = 0; -+ mnt = file->f_path.mnt; -+ dentry = file->f_path.dentry; -+ file->f_version = inode_query_iversion(d_inode(dentry)); -+ bindex = au_dbtop(dentry); -+ au_set_fbtop(file, bindex); -+ btail = au_dbtaildir(dentry); -+ au_set_fbbot_dir(file, btail); -+ for (; !err && bindex <= btail; bindex++) { -+ h_dentry = au_h_dptr(dentry, bindex); -+ if (!h_dentry) -+ continue; -+ -+ err = vfsub_test_mntns(mnt, h_dentry->d_sb); -+ if (unlikely(err)) -+ break; -+ h_file = au_h_open(dentry, bindex, flags, file, /*force_wr*/0); -+ if (IS_ERR(h_file)) { -+ err = PTR_ERR(h_file); -+ break; -+ } -+ au_set_h_fptr(file, bindex, h_file); -+ } -+ au_update_figen(file); -+ /* todo: necessary? */ -+ /* file->f_ra = h_file->f_ra; */ -+ if (!err) -+ return 0; /* success */ -+ -+ /* close all */ -+ for (bindex = au_fbtop(file); bindex <= btail; bindex++) -+ au_set_h_fptr(file, bindex, NULL); -+ au_set_fbtop(file, -1); -+ au_set_fbbot_dir(file, -1); -+ -+ return err; -+} -+ -+static int aufs_open_dir(struct inode *inode __maybe_unused, -+ struct file *file) -+{ -+ int err; -+ struct super_block *sb; -+ struct au_fidir *fidir; -+ -+ err = -ENOMEM; -+ sb = file->f_path.dentry->d_sb; -+ si_read_lock(sb, AuLock_FLUSH); -+ fidir = au_fidir_alloc(sb); -+ if (fidir) { -+ struct au_do_open_args args = { -+ .open = do_open_dir, -+ .fidir = fidir -+ }; -+ err = au_do_open(file, &args); -+ if (unlikely(err)) -+ au_kfree_rcu(fidir); -+ } -+ si_read_unlock(sb); -+ return err; -+} -+ -+static int aufs_release_dir(struct inode *inode __maybe_unused, -+ struct file *file) -+{ -+ struct au_vdir *vdir_cache; -+ struct au_finfo *finfo; -+ struct au_fidir *fidir; -+ struct au_hfile *hf; -+ aufs_bindex_t bindex, bbot; -+ -+ finfo = au_fi(file); -+ fidir = finfo->fi_hdir; -+ if (fidir) { -+ au_hbl_del(&finfo->fi_hlist, -+ &au_sbi(file->f_path.dentry->d_sb)->si_files); -+ vdir_cache = fidir->fd_vdir_cache; /* lock-free */ -+ if (vdir_cache) -+ au_vdir_free(vdir_cache); -+ -+ bindex = finfo->fi_btop; -+ if (bindex >= 0) { -+ hf = fidir->fd_hfile + bindex; -+ /* -+ * calls fput() instead of filp_close(), -+ * since no dnotify or lock for the lower file. -+ */ -+ bbot = fidir->fd_bbot; -+ for (; bindex <= bbot; bindex++, hf++) -+ if (hf->hf_file) -+ au_hfput(hf, /*execed*/0); -+ } -+ au_kfree_rcu(fidir); -+ finfo->fi_hdir = NULL; -+ } -+ au_finfo_fin(file); -+ return 0; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int au_do_flush_dir(struct file *file, fl_owner_t id) -+{ -+ int err; -+ aufs_bindex_t bindex, bbot; -+ struct file *h_file; -+ -+ err = 0; -+ bbot = au_fbbot_dir(file); -+ for (bindex = au_fbtop(file); !err && bindex <= bbot; bindex++) { -+ h_file = au_hf_dir(file, bindex); -+ if (h_file) -+ err = vfsub_flush(h_file, id); -+ } -+ return err; -+} -+ -+static int aufs_flush_dir(struct file *file, fl_owner_t id) -+{ -+ return au_do_flush(file, id, au_do_flush_dir); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int au_do_fsync_dir_no_file(struct dentry *dentry, int datasync) -+{ -+ int err; -+ aufs_bindex_t bbot, bindex; -+ struct inode *inode; -+ struct super_block *sb; -+ -+ err = 0; -+ sb = dentry->d_sb; -+ inode = d_inode(dentry); -+ IMustLock(inode); -+ bbot = au_dbbot(dentry); -+ for (bindex = au_dbtop(dentry); !err && bindex <= bbot; bindex++) { -+ struct path h_path; -+ -+ if (au_test_ro(sb, bindex, inode)) -+ continue; -+ h_path.dentry = au_h_dptr(dentry, bindex); -+ if (!h_path.dentry) -+ continue; -+ -+ h_path.mnt = au_sbr_mnt(sb, bindex); -+ err = vfsub_fsync(NULL, &h_path, datasync); -+ } -+ -+ return err; -+} -+ -+static int au_do_fsync_dir(struct file *file, int datasync) -+{ -+ int err; -+ aufs_bindex_t bbot, bindex; -+ struct file *h_file; -+ struct super_block *sb; -+ struct inode *inode; -+ -+ err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1, /*fi_lsc*/0); -+ if (unlikely(err)) -+ goto out; -+ -+ inode = file_inode(file); -+ sb = inode->i_sb; -+ bbot = au_fbbot_dir(file); -+ for (bindex = au_fbtop(file); !err && bindex <= bbot; bindex++) { -+ h_file = au_hf_dir(file, bindex); -+ if (!h_file || au_test_ro(sb, bindex, inode)) -+ continue; -+ -+ err = vfsub_fsync(h_file, &h_file->f_path, datasync); -+ } -+ -+out: -+ return err; -+} -+ -+/* -+ * @file may be NULL -+ */ -+static int aufs_fsync_dir(struct file *file, loff_t start, loff_t end, -+ int datasync) -+{ -+ int err; -+ struct dentry *dentry; -+ struct inode *inode; -+ struct super_block *sb; -+ -+ err = 0; -+ dentry = file->f_path.dentry; -+ inode = d_inode(dentry); -+ inode_lock(inode); -+ sb = dentry->d_sb; -+ si_noflush_read_lock(sb); -+ if (file) -+ err = au_do_fsync_dir(file, datasync); -+ else { -+ di_write_lock_child(dentry); -+ err = au_do_fsync_dir_no_file(dentry, datasync); -+ } -+ au_cpup_attr_timesizes(inode); -+ di_write_unlock(dentry); -+ if (file) -+ fi_write_unlock(file); -+ -+ si_read_unlock(sb); -+ inode_unlock(inode); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int aufs_iterate_shared(struct file *file, struct dir_context *ctx) -+{ -+ int err; -+ struct dentry *dentry; -+ struct inode *inode, *h_inode; -+ struct super_block *sb; -+ -+ AuDbg("%pD, ctx{%ps, %llu}\n", file, ctx->actor, ctx->pos); -+ -+ dentry = file->f_path.dentry; -+ inode = d_inode(dentry); -+ IMustLock(inode); -+ -+ sb = dentry->d_sb; -+ si_read_lock(sb, AuLock_FLUSH); -+ err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1, /*fi_lsc*/0); -+ if (unlikely(err)) -+ goto out; -+ err = au_alive_dir(dentry); -+ if (!err) -+ err = au_vdir_init(file); -+ di_downgrade_lock(dentry, AuLock_IR); -+ if (unlikely(err)) -+ goto out_unlock; -+ -+ h_inode = au_h_iptr(inode, au_ibtop(inode)); -+ if (!au_test_nfsd()) { -+ err = au_vdir_fill_de(file, ctx); -+ fsstack_copy_attr_atime(inode, h_inode); -+ } else { -+ /* -+ * nfsd filldir may call lookup_one_len(), vfs_getattr(), -+ * encode_fh() and others. -+ */ -+ atomic_inc(&h_inode->i_count); -+ di_read_unlock(dentry, AuLock_IR); -+ si_read_unlock(sb); -+ err = au_vdir_fill_de(file, ctx); -+ fsstack_copy_attr_atime(inode, h_inode); -+ fi_write_unlock(file); -+ iput(h_inode); -+ -+ AuTraceErr(err); -+ return err; -+ } -+ -+out_unlock: -+ di_read_unlock(dentry, AuLock_IR); -+ fi_write_unlock(file); -+out: -+ si_read_unlock(sb); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+#define AuTestEmpty_WHONLY 1 -+#define AuTestEmpty_CALLED (1 << 1) -+#define AuTestEmpty_SHWH (1 << 2) -+#define au_ftest_testempty(flags, name) ((flags) & AuTestEmpty_##name) -+#define au_fset_testempty(flags, name) \ -+ do { (flags) |= AuTestEmpty_##name; } while (0) -+#define au_fclr_testempty(flags, name) \ -+ do { (flags) &= ~AuTestEmpty_##name; } while (0) -+ -+#ifndef CONFIG_AUFS_SHWH -+#undef AuTestEmpty_SHWH -+#define AuTestEmpty_SHWH 0 -+#endif -+ -+struct test_empty_arg { -+ struct dir_context ctx; -+ struct au_nhash *whlist; -+ unsigned int flags; -+ int err; -+ aufs_bindex_t bindex; -+}; -+ -+static int test_empty_cb(struct dir_context *ctx, const char *__name, -+ int namelen, loff_t offset __maybe_unused, u64 ino, -+ unsigned int d_type) -+{ -+ struct test_empty_arg *arg = container_of(ctx, struct test_empty_arg, -+ ctx); -+ char *name = (void *)__name; -+ -+ arg->err = 0; -+ au_fset_testempty(arg->flags, CALLED); -+ /* smp_mb(); */ -+ if (name[0] == '.' -+ && (namelen == 1 || (name[1] == '.' && namelen == 2))) -+ goto out; /* success */ -+ -+ if (namelen <= AUFS_WH_PFX_LEN -+ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) { -+ if (au_ftest_testempty(arg->flags, WHONLY) -+ && !au_nhash_test_known_wh(arg->whlist, name, namelen)) -+ arg->err = -ENOTEMPTY; -+ goto out; -+ } -+ -+ name += AUFS_WH_PFX_LEN; -+ namelen -= AUFS_WH_PFX_LEN; -+ if (!au_nhash_test_known_wh(arg->whlist, name, namelen)) -+ arg->err = au_nhash_append_wh -+ (arg->whlist, name, namelen, ino, d_type, arg->bindex, -+ au_ftest_testempty(arg->flags, SHWH)); -+ -+out: -+ /* smp_mb(); */ -+ AuTraceErr(arg->err); -+ return arg->err; -+} -+ -+static int do_test_empty(struct dentry *dentry, struct test_empty_arg *arg) -+{ -+ int err; -+ struct file *h_file; -+ struct au_branch *br; -+ -+ h_file = au_h_open(dentry, arg->bindex, -+ O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_LARGEFILE, -+ /*file*/NULL, /*force_wr*/0); -+ err = PTR_ERR(h_file); -+ if (IS_ERR(h_file)) -+ goto out; -+ -+ err = 0; -+ if (!au_opt_test(au_mntflags(dentry->d_sb), UDBA_NONE) -+ && !file_inode(h_file)->i_nlink) -+ goto out_put; -+ -+ do { -+ arg->err = 0; -+ au_fclr_testempty(arg->flags, CALLED); -+ /* smp_mb(); */ -+ err = vfsub_iterate_dir(h_file, &arg->ctx); -+ if (err >= 0) -+ err = arg->err; -+ } while (!err && au_ftest_testempty(arg->flags, CALLED)); -+ -+out_put: -+ fput(h_file); -+ br = au_sbr(dentry->d_sb, arg->bindex); -+ au_lcnt_dec(&br->br_nfiles); -+out: -+ return err; -+} -+ -+struct do_test_empty_args { -+ int *errp; -+ struct dentry *dentry; -+ struct test_empty_arg *arg; -+}; -+ -+static void call_do_test_empty(void *args) -+{ -+ struct do_test_empty_args *a = args; -+ *a->errp = do_test_empty(a->dentry, a->arg); -+} -+ -+static int sio_test_empty(struct dentry *dentry, struct test_empty_arg *arg) -+{ -+ int err, wkq_err; -+ struct dentry *h_dentry; -+ struct inode *h_inode; -+ -+ h_dentry = au_h_dptr(dentry, arg->bindex); -+ h_inode = d_inode(h_dentry); -+ /* todo: i_mode changes anytime? */ -+ inode_lock_shared_nested(h_inode, AuLsc_I_CHILD); -+ err = au_test_h_perm_sio(h_inode, MAY_EXEC | MAY_READ); -+ inode_unlock_shared(h_inode); -+ if (!err) -+ err = do_test_empty(dentry, arg); -+ else { -+ struct do_test_empty_args args = { -+ .errp = &err, -+ .dentry = dentry, -+ .arg = arg -+ }; -+ unsigned int flags = arg->flags; -+ -+ wkq_err = au_wkq_wait(call_do_test_empty, &args); -+ if (unlikely(wkq_err)) -+ err = wkq_err; -+ arg->flags = flags; -+ } -+ -+ return err; -+} -+ -+int au_test_empty_lower(struct dentry *dentry) -+{ -+ int err; -+ unsigned int rdhash; -+ aufs_bindex_t bindex, btop, btail; -+ struct au_nhash whlist; -+ struct test_empty_arg arg = { -+ .ctx = { -+ .actor = test_empty_cb -+ } -+ }; -+ int (*test_empty)(struct dentry *dentry, struct test_empty_arg *arg); -+ -+ SiMustAnyLock(dentry->d_sb); -+ -+ rdhash = au_sbi(dentry->d_sb)->si_rdhash; -+ if (!rdhash) -+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, dentry)); -+ err = au_nhash_alloc(&whlist, rdhash, GFP_NOFS); -+ if (unlikely(err)) -+ goto out; -+ -+ arg.flags = 0; -+ arg.whlist = &whlist; -+ btop = au_dbtop(dentry); -+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH)) -+ au_fset_testempty(arg.flags, SHWH); -+ test_empty = do_test_empty; -+ if (au_opt_test(au_mntflags(dentry->d_sb), DIRPERM1)) -+ test_empty = sio_test_empty; -+ arg.bindex = btop; -+ err = test_empty(dentry, &arg); -+ if (unlikely(err)) -+ goto out_whlist; -+ -+ au_fset_testempty(arg.flags, WHONLY); -+ btail = au_dbtaildir(dentry); -+ for (bindex = btop + 1; !err && bindex <= btail; bindex++) { -+ struct dentry *h_dentry; -+ -+ h_dentry = au_h_dptr(dentry, bindex); -+ if (h_dentry && d_is_positive(h_dentry)) { -+ arg.bindex = bindex; -+ err = test_empty(dentry, &arg); -+ } -+ } -+ -+out_whlist: -+ au_nhash_wh_free(&whlist); -+out: -+ return err; -+} -+ -+int au_test_empty(struct dentry *dentry, struct au_nhash *whlist) -+{ -+ int err; -+ struct test_empty_arg arg = { -+ .ctx = { -+ .actor = test_empty_cb -+ } -+ }; -+ aufs_bindex_t bindex, btail; -+ -+ err = 0; -+ arg.whlist = whlist; -+ arg.flags = AuTestEmpty_WHONLY; -+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH)) -+ au_fset_testempty(arg.flags, SHWH); -+ btail = au_dbtaildir(dentry); -+ for (bindex = au_dbtop(dentry); !err && bindex <= btail; bindex++) { -+ struct dentry *h_dentry; -+ -+ h_dentry = au_h_dptr(dentry, bindex); -+ if (h_dentry && d_is_positive(h_dentry)) { -+ arg.bindex = bindex; -+ err = sio_test_empty(dentry, &arg); -+ } -+ } -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+const struct file_operations aufs_dir_fop = { -+ .owner = THIS_MODULE, -+ .llseek = default_llseek, -+ .read = generic_read_dir, -+ .iterate_shared = aufs_iterate_shared, -+ .unlocked_ioctl = aufs_ioctl_dir, -+#ifdef CONFIG_COMPAT -+ .compat_ioctl = aufs_compat_ioctl_dir, -+#endif -+ .open = aufs_open_dir, -+ .release = aufs_release_dir, -+ .flush = aufs_flush_dir, -+ .fsync = aufs_fsync_dir -+}; -diff -Nurp linux-5.10-rc6/fs/aufs/dir.h linux-5.10-rc6.aufs/fs/aufs/dir.h ---- linux-5.10-rc6/fs/aufs/dir.h 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/dir.h 2020-12-02 21:19:51.881036743 +0200 -@@ -0,0 +1,121 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * directory operations -+ */ -+ -+#ifndef __AUFS_DIR_H__ -+#define __AUFS_DIR_H__ -+ -+#ifdef __KERNEL__ -+ -+#include -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* need to be faster and smaller */ -+ -+struct au_nhash { -+ unsigned int nh_num; -+ struct hlist_head *nh_head; -+}; -+ -+struct au_vdir_destr { -+ unsigned char len; -+ unsigned char name[]; -+} __packed; -+ -+struct au_vdir_dehstr { -+ struct hlist_node hash; -+ struct au_vdir_destr *str; -+ struct rcu_head rcu; -+} ____cacheline_aligned_in_smp; -+ -+struct au_vdir_de { -+ ino_t de_ino; -+ unsigned char de_type; -+ /* caution: packed */ -+ struct au_vdir_destr de_str; -+} __packed; -+ -+struct au_vdir_wh { -+ struct hlist_node wh_hash; -+#ifdef CONFIG_AUFS_SHWH -+ ino_t wh_ino; -+ aufs_bindex_t wh_bindex; -+ unsigned char wh_type; -+#else -+ aufs_bindex_t wh_bindex; -+#endif -+ /* caution: packed */ -+ struct au_vdir_destr wh_str; -+} __packed; -+ -+union au_vdir_deblk_p { -+ unsigned char *deblk; -+ struct au_vdir_de *de; -+}; -+ -+struct au_vdir { -+ unsigned char **vd_deblk; -+ unsigned long vd_nblk; -+ struct { -+ unsigned long ul; -+ union au_vdir_deblk_p p; -+ } vd_last; -+ -+ u64 vd_version; -+ unsigned int vd_deblk_sz; -+ unsigned long vd_jiffy; -+ struct rcu_head rcu; -+} ____cacheline_aligned_in_smp; -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* dir.c */ -+extern const struct file_operations aufs_dir_fop; -+void au_add_nlink(struct inode *dir, struct inode *h_dir); -+void au_sub_nlink(struct inode *dir, struct inode *h_dir); -+loff_t au_dir_size(struct file *file, struct dentry *dentry); -+void au_dir_ts(struct inode *dir, aufs_bindex_t bsrc); -+int au_test_empty_lower(struct dentry *dentry); -+int au_test_empty(struct dentry *dentry, struct au_nhash *whlist); -+ -+/* vdir.c */ -+unsigned int au_rdhash_est(loff_t sz); -+int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp); -+void au_nhash_wh_free(struct au_nhash *whlist); -+int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt, -+ int limit); -+int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen); -+int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino, -+ unsigned int d_type, aufs_bindex_t bindex, -+ unsigned char shwh); -+void au_vdir_free(struct au_vdir *vdir); -+int au_vdir_init(struct file *file); -+int au_vdir_fill_de(struct file *file, struct dir_context *ctx); -+ -+/* ioctl.c */ -+long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg); -+ -+#ifdef CONFIG_AUFS_RDU -+/* rdu.c */ -+long au_rdu_ioctl(struct file *file, unsigned int cmd, unsigned long arg); -+#ifdef CONFIG_COMPAT -+long au_rdu_compat_ioctl(struct file *file, unsigned int cmd, -+ unsigned long arg); -+#endif -+#else -+AuStub(long, au_rdu_ioctl, return -EINVAL, struct file *file, -+ unsigned int cmd, unsigned long arg) -+#ifdef CONFIG_COMPAT -+AuStub(long, au_rdu_compat_ioctl, return -EINVAL, struct file *file, -+ unsigned int cmd, unsigned long arg) -+#endif -+#endif -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_DIR_H__ */ -diff -Nurp linux-5.10-rc6/fs/aufs/dirren.c linux-5.10-rc6.aufs/fs/aufs/dirren.c ---- linux-5.10-rc6/fs/aufs/dirren.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/dirren.c 2020-12-02 21:19:51.881036743 +0200 -@@ -0,0 +1,1303 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2017-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * special handling in renaming a directory -+ * in order to support looking-up the before-renamed name on the lower readonly -+ * branches -+ */ -+ -+#include -+#include "aufs.h" -+ -+static void au_dr_hino_del(struct au_dr_br *dr, struct au_dr_hino *ent) -+{ -+ int idx; -+ -+ idx = au_dr_ihash(ent->dr_h_ino); -+ au_hbl_del(&ent->dr_hnode, dr->dr_h_ino + idx); -+} -+ -+static int au_dr_hino_test_empty(struct au_dr_br *dr) -+{ -+ int ret, i; -+ struct hlist_bl_head *hbl; -+ -+ ret = 1; -+ for (i = 0; ret && i < AuDirren_NHASH; i++) { -+ hbl = dr->dr_h_ino + i; -+ hlist_bl_lock(hbl); -+ ret &= hlist_bl_empty(hbl); -+ hlist_bl_unlock(hbl); -+ } -+ -+ return ret; -+} -+ -+static struct au_dr_hino *au_dr_hino_find(struct au_dr_br *dr, ino_t ino) -+{ -+ struct au_dr_hino *found, *ent; -+ struct hlist_bl_head *hbl; -+ struct hlist_bl_node *pos; -+ int idx; -+ -+ found = NULL; -+ idx = au_dr_ihash(ino); -+ hbl = dr->dr_h_ino + idx; -+ hlist_bl_lock(hbl); -+ hlist_bl_for_each_entry(ent, pos, hbl, dr_hnode) -+ if (ent->dr_h_ino == ino) { -+ found = ent; -+ break; -+ } -+ hlist_bl_unlock(hbl); -+ -+ return found; -+} -+ -+int au_dr_hino_test_add(struct au_dr_br *dr, ino_t ino, -+ struct au_dr_hino *add_ent) -+{ -+ int found, idx; -+ struct hlist_bl_head *hbl; -+ struct hlist_bl_node *pos; -+ struct au_dr_hino *ent; -+ -+ found = 0; -+ idx = au_dr_ihash(ino); -+ hbl = dr->dr_h_ino + idx; -+#if 0 /* debug print */ -+ { -+ struct hlist_bl_node *tmp; -+ -+ hlist_bl_for_each_entry_safe(ent, pos, tmp, hbl, dr_hnode) -+ AuDbg("hi%llu\n", (unsigned long long)ent->dr_h_ino); -+ } -+#endif -+ hlist_bl_lock(hbl); -+ hlist_bl_for_each_entry(ent, pos, hbl, dr_hnode) -+ if (ent->dr_h_ino == ino) { -+ found = 1; -+ break; -+ } -+ if (!found && add_ent) -+ hlist_bl_add_head(&add_ent->dr_hnode, hbl); -+ hlist_bl_unlock(hbl); -+ -+ if (!found && add_ent) -+ AuDbg("i%llu added\n", (unsigned long long)add_ent->dr_h_ino); -+ -+ return found; -+} -+ -+void au_dr_hino_free(struct au_dr_br *dr) -+{ -+ int i; -+ struct hlist_bl_head *hbl; -+ struct hlist_bl_node *pos, *tmp; -+ struct au_dr_hino *ent; -+ -+ /* SiMustWriteLock(sb); */ -+ -+ for (i = 0; i < AuDirren_NHASH; i++) { -+ hbl = dr->dr_h_ino + i; -+ /* no spinlock since sbinfo must be write-locked */ -+ hlist_bl_for_each_entry_safe(ent, pos, tmp, hbl, dr_hnode) -+ au_kfree_rcu(ent); -+ INIT_HLIST_BL_HEAD(hbl); -+ } -+} -+ -+/* returns the number of inodes or an error */ -+static int au_dr_hino_store(struct super_block *sb, struct au_branch *br, -+ struct file *hinofile) -+{ -+ int err, i; -+ ssize_t ssz; -+ loff_t pos, oldsize; -+ __be64 u64; -+ struct inode *hinoinode; -+ struct hlist_bl_head *hbl; -+ struct hlist_bl_node *n1, *n2; -+ struct au_dr_hino *ent; -+ -+ SiMustWriteLock(sb); -+ AuDebugOn(!au_br_writable(br->br_perm)); -+ -+ hinoinode = file_inode(hinofile); -+ oldsize = i_size_read(hinoinode); -+ -+ err = 0; -+ pos = 0; -+ hbl = br->br_dirren.dr_h_ino; -+ for (i = 0; !err && i < AuDirren_NHASH; i++, hbl++) { -+ /* no bit-lock since sbinfo must be write-locked */ -+ hlist_bl_for_each_entry_safe(ent, n1, n2, hbl, dr_hnode) { -+ AuDbg("hi%llu, %pD2\n", -+ (unsigned long long)ent->dr_h_ino, hinofile); -+ u64 = cpu_to_be64(ent->dr_h_ino); -+ ssz = vfsub_write_k(hinofile, &u64, sizeof(u64), &pos); -+ if (ssz == sizeof(u64)) -+ continue; -+ -+ /* write error */ -+ pr_err("ssz %zd, %pD2\n", ssz, hinofile); -+ err = -ENOSPC; -+ if (ssz < 0) -+ err = ssz; -+ break; -+ } -+ } -+ /* regardless the error */ -+ if (pos < oldsize) { -+ err = vfsub_trunc(&hinofile->f_path, pos, /*attr*/0, hinofile); -+ AuTraceErr(err); -+ } -+ -+ AuTraceErr(err); -+ return err; -+} -+ -+static int au_dr_hino_load(struct au_dr_br *dr, struct file *hinofile) -+{ -+ int err, hidx; -+ ssize_t ssz; -+ size_t sz, n; -+ loff_t pos; -+ uint64_t u64; -+ struct au_dr_hino *ent; -+ struct inode *hinoinode; -+ struct hlist_bl_head *hbl; -+ -+ err = 0; -+ pos = 0; -+ hbl = dr->dr_h_ino; -+ hinoinode = file_inode(hinofile); -+ sz = i_size_read(hinoinode); -+ AuDebugOn(sz % sizeof(u64)); -+ n = sz / sizeof(u64); -+ while (n--) { -+ ssz = vfsub_read_k(hinofile, &u64, sizeof(u64), &pos); -+ if (unlikely(ssz != sizeof(u64))) { -+ pr_err("ssz %zd, %pD2\n", ssz, hinofile); -+ err = -EINVAL; -+ if (ssz < 0) -+ err = ssz; -+ goto out_free; -+ } -+ -+ ent = kmalloc(sizeof(*ent), GFP_NOFS); -+ if (!ent) { -+ err = -ENOMEM; -+ AuTraceErr(err); -+ goto out_free; -+ } -+ ent->dr_h_ino = be64_to_cpu((__force __be64)u64); -+ AuDbg("hi%llu, %pD2\n", -+ (unsigned long long)ent->dr_h_ino, hinofile); -+ hidx = au_dr_ihash(ent->dr_h_ino); -+ au_hbl_add(&ent->dr_hnode, hbl + hidx); -+ } -+ goto out; /* success */ -+ -+out_free: -+ au_dr_hino_free(dr); -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+/* -+ * @bindex/@br is a switch to distinguish whether suspending hnotify or not. -+ * @path is a switch to distinguish load and store. -+ */ -+static int au_dr_hino(struct super_block *sb, aufs_bindex_t bindex, -+ struct au_branch *br, const struct path *path) -+{ -+ int err, flags; -+ unsigned char load, suspend; -+ struct file *hinofile; -+ struct au_hinode *hdir; -+ struct inode *dir, *delegated; -+ struct path hinopath; -+ struct qstr hinoname = QSTR_INIT(AUFS_WH_DR_BRHINO, -+ sizeof(AUFS_WH_DR_BRHINO) - 1); -+ -+ AuDebugOn(bindex < 0 && !br); -+ AuDebugOn(bindex >= 0 && br); -+ -+ err = -EINVAL; -+ suspend = !br; -+ if (suspend) -+ br = au_sbr(sb, bindex); -+ load = !!path; -+ if (!load) { -+ path = &br->br_path; -+ AuDebugOn(!au_br_writable(br->br_perm)); -+ if (unlikely(!au_br_writable(br->br_perm))) -+ goto out; -+ } -+ -+ hdir = NULL; -+ if (suspend) { -+ dir = d_inode(sb->s_root); -+ hdir = au_hinode(au_ii(dir), bindex); -+ dir = hdir->hi_inode; -+ au_hn_inode_lock_nested(hdir, AuLsc_I_CHILD); -+ } else { -+ dir = d_inode(path->dentry); -+ inode_lock_nested(dir, AuLsc_I_CHILD); -+ } -+ hinopath.dentry = vfsub_lkup_one(&hinoname, path->dentry); -+ err = PTR_ERR(hinopath.dentry); -+ if (IS_ERR(hinopath.dentry)) -+ goto out_unlock; -+ -+ err = 0; -+ flags = O_RDONLY; -+ if (load) { -+ if (d_is_negative(hinopath.dentry)) -+ goto out_dput; /* success */ -+ } else { -+ if (au_dr_hino_test_empty(&br->br_dirren)) { -+ if (d_is_positive(hinopath.dentry)) { -+ delegated = NULL; -+ err = vfsub_unlink(dir, &hinopath, &delegated, -+ /*force*/0); -+ AuTraceErr(err); -+ if (unlikely(err)) -+ pr_err("ignored err %d, %pd2\n", -+ err, hinopath.dentry); -+ if (unlikely(err == -EWOULDBLOCK)) -+ iput(delegated); -+ err = 0; -+ } -+ goto out_dput; -+ } else if (!d_is_positive(hinopath.dentry)) { -+ err = vfsub_create(dir, &hinopath, 0600, -+ /*want_excl*/false); -+ AuTraceErr(err); -+ if (unlikely(err)) -+ goto out_dput; -+ } -+ flags = O_WRONLY; -+ } -+ hinopath.mnt = path->mnt; -+ hinofile = vfsub_dentry_open(&hinopath, flags); -+ if (suspend) -+ au_hn_inode_unlock(hdir); -+ else -+ inode_unlock(dir); -+ dput(hinopath.dentry); -+ AuTraceErrPtr(hinofile); -+ if (IS_ERR(hinofile)) { -+ err = PTR_ERR(hinofile); -+ goto out; -+ } -+ -+ if (load) -+ err = au_dr_hino_load(&br->br_dirren, hinofile); -+ else -+ err = au_dr_hino_store(sb, br, hinofile); -+ fput(hinofile); -+ goto out; -+ -+out_dput: -+ dput(hinopath.dentry); -+out_unlock: -+ if (suspend) -+ au_hn_inode_unlock(hdir); -+ else -+ inode_unlock(dir); -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int au_dr_brid_init(struct au_dr_brid *brid, const struct path *path) -+{ -+ int err; -+ struct kstatfs kstfs; -+ dev_t dev; -+ struct dentry *dentry; -+ struct super_block *sb; -+ -+ err = vfs_statfs((void *)path, &kstfs); -+ AuTraceErr(err); -+ if (unlikely(err)) -+ goto out; -+ -+ /* todo: support for UUID */ -+ -+ if (kstfs.f_fsid.val[0] || kstfs.f_fsid.val[1]) { -+ brid->type = AuBrid_FSID; -+ brid->fsid = kstfs.f_fsid; -+ } else { -+ dentry = path->dentry; -+ sb = dentry->d_sb; -+ dev = sb->s_dev; -+ if (dev) { -+ brid->type = AuBrid_DEV; -+ brid->dev = dev; -+ } -+ } -+ -+out: -+ return err; -+} -+ -+int au_dr_br_init(struct super_block *sb, struct au_branch *br, -+ const struct path *path) -+{ -+ int err, i; -+ struct au_dr_br *dr; -+ struct hlist_bl_head *hbl; -+ -+ dr = &br->br_dirren; -+ hbl = dr->dr_h_ino; -+ for (i = 0; i < AuDirren_NHASH; i++, hbl++) -+ INIT_HLIST_BL_HEAD(hbl); -+ -+ err = au_dr_brid_init(&dr->dr_brid, path); -+ if (unlikely(err)) -+ goto out; -+ -+ if (au_opt_test(au_mntflags(sb), DIRREN)) -+ err = au_dr_hino(sb, /*bindex*/-1, br, path); -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+int au_dr_br_fin(struct super_block *sb, struct au_branch *br) -+{ -+ int err; -+ -+ err = 0; -+ if (au_br_writable(br->br_perm)) -+ err = au_dr_hino(sb, /*bindex*/-1, br, /*path*/NULL); -+ if (!err) -+ au_dr_hino_free(&br->br_dirren); -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int au_brid_str(struct au_dr_brid *brid, struct inode *h_inode, -+ char *buf, size_t sz) -+{ -+ int err; -+ unsigned int major, minor; -+ char *p; -+ -+ p = buf; -+ err = snprintf(p, sz, "%d_", brid->type); -+ AuDebugOn(err > sz); -+ p += err; -+ sz -= err; -+ switch (brid->type) { -+ case AuBrid_Unset: -+ return -EINVAL; -+ case AuBrid_UUID: -+ err = snprintf(p, sz, "%pU", brid->uuid.b); -+ break; -+ case AuBrid_FSID: -+ err = snprintf(p, sz, "%08x-%08x", -+ brid->fsid.val[0], brid->fsid.val[1]); -+ break; -+ case AuBrid_DEV: -+ major = MAJOR(brid->dev); -+ minor = MINOR(brid->dev); -+ if (major <= 0xff && minor <= 0xff) -+ err = snprintf(p, sz, "%02x%02x", major, minor); -+ else -+ err = snprintf(p, sz, "%03x:%05x", major, minor); -+ break; -+ } -+ AuDebugOn(err > sz); -+ p += err; -+ sz -= err; -+ err = snprintf(p, sz, "_%llu", (unsigned long long)h_inode->i_ino); -+ AuDebugOn(err > sz); -+ p += err; -+ sz -= err; -+ -+ return p - buf; -+} -+ -+static int au_drinfo_name(struct au_branch *br, char *name, int len) -+{ -+ int rlen; -+ struct dentry *br_dentry; -+ struct inode *br_inode; -+ -+ br_dentry = au_br_dentry(br); -+ br_inode = d_inode(br_dentry); -+ rlen = au_brid_str(&br->br_dirren.dr_brid, br_inode, name, len); -+ AuDebugOn(rlen >= AUFS_DIRREN_ENV_VAL_SZ); -+ AuDebugOn(rlen > len); -+ -+ return rlen; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * from the given @h_dentry, construct drinfo at @*fdata. -+ * when the size of @*fdata is not enough, reallocate and return new @fdata and -+ * @allocated. -+ */ -+static int au_drinfo_construct(struct au_drinfo_fdata **fdata, -+ struct dentry *h_dentry, -+ unsigned char *allocated) -+{ -+ int err, v; -+ struct au_drinfo_fdata *f, *p; -+ struct au_drinfo *drinfo; -+ struct inode *h_inode; -+ struct qstr *qname; -+ -+ err = 0; -+ f = *fdata; -+ h_inode = d_inode(h_dentry); -+ qname = &h_dentry->d_name; -+ drinfo = &f->drinfo; -+ drinfo->ino = (__force uint64_t)cpu_to_be64(h_inode->i_ino); -+ drinfo->oldnamelen = qname->len; -+ if (*allocated < sizeof(*f) + qname->len) { -+ v = roundup_pow_of_two(*allocated + qname->len); -+ p = au_krealloc(f, v, GFP_NOFS, /*may_shrink*/0); -+ if (unlikely(!p)) { -+ err = -ENOMEM; -+ AuTraceErr(err); -+ goto out; -+ } -+ f = p; -+ *fdata = f; -+ *allocated = v; -+ drinfo = &f->drinfo; -+ } -+ memcpy(drinfo->oldname, qname->name, qname->len); -+ AuDbg("i%llu, %.*s\n", -+ be64_to_cpu((__force __be64)drinfo->ino), drinfo->oldnamelen, -+ drinfo->oldname); -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+/* callers have to free the return value */ -+static struct au_drinfo *au_drinfo_read_k(struct file *file, ino_t h_ino) -+{ -+ struct au_drinfo *ret, *drinfo; -+ struct au_drinfo_fdata fdata; -+ int len; -+ loff_t pos; -+ ssize_t ssz; -+ -+ ret = ERR_PTR(-EIO); -+ pos = 0; -+ ssz = vfsub_read_k(file, &fdata, sizeof(fdata), &pos); -+ if (unlikely(ssz != sizeof(fdata))) { -+ AuIOErr("ssz %zd, %u, %pD2\n", -+ ssz, (unsigned int)sizeof(fdata), file); -+ goto out; -+ } -+ -+ fdata.magic = ntohl((__force __be32)fdata.magic); -+ switch (fdata.magic) { -+ case AUFS_DRINFO_MAGIC_V1: -+ break; -+ default: -+ AuIOErr("magic-num 0x%x, 0x%x, %pD2\n", -+ fdata.magic, AUFS_DRINFO_MAGIC_V1, file); -+ goto out; -+ } -+ -+ drinfo = &fdata.drinfo; -+ len = drinfo->oldnamelen; -+ if (!len) { -+ AuIOErr("broken drinfo %pD2\n", file); -+ goto out; -+ } -+ -+ ret = NULL; -+ drinfo->ino = be64_to_cpu((__force __be64)drinfo->ino); -+ if (unlikely(h_ino && drinfo->ino != h_ino)) { -+ AuDbg("ignored i%llu, i%llu, %pD2\n", -+ (unsigned long long)drinfo->ino, -+ (unsigned long long)h_ino, file); -+ goto out; /* success */ -+ } -+ -+ ret = kmalloc(sizeof(*ret) + len, GFP_NOFS); -+ if (unlikely(!ret)) { -+ ret = ERR_PTR(-ENOMEM); -+ AuTraceErrPtr(ret); -+ goto out; -+ } -+ -+ *ret = *drinfo; -+ ssz = vfsub_read_k(file, (void *)ret->oldname, len, &pos); -+ if (unlikely(ssz != len)) { -+ au_kfree_rcu(ret); -+ ret = ERR_PTR(-EIO); -+ AuIOErr("ssz %zd, %u, %pD2\n", ssz, len, file); -+ goto out; -+ } -+ -+ AuDbg("oldname %.*s\n", ret->oldnamelen, ret->oldname); -+ -+out: -+ return ret; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* in order to be revertible */ -+struct au_drinfo_rev_elm { -+ int created; -+ struct dentry *info_dentry; -+ struct au_drinfo *info_last; -+}; -+ -+struct au_drinfo_rev { -+ unsigned char already; -+ aufs_bindex_t nelm; -+ struct au_drinfo_rev_elm elm[]; -+}; -+ -+/* todo: isn't it too large? */ -+struct au_drinfo_store { -+ struct path h_ppath; -+ struct dentry *h_dentry; -+ struct au_drinfo_fdata *fdata; -+ char *infoname; /* inside of whname, just after PFX */ -+ char whname[sizeof(AUFS_WH_DR_INFO_PFX) + AUFS_DIRREN_ENV_VAL_SZ]; -+ aufs_bindex_t btgt, btail; -+ unsigned char no_sio, -+ allocated, /* current size of *fdata */ -+ infonamelen, /* room size for p */ -+ whnamelen, /* length of the generated name */ -+ renameback; /* renamed back */ -+}; -+ -+/* on rename(2) error, the caller should revert it using @elm */ -+static int au_drinfo_do_store(struct au_drinfo_store *w, -+ struct au_drinfo_rev_elm *elm) -+{ -+ int err, len; -+ ssize_t ssz; -+ loff_t pos; -+ struct path infopath = { -+ .mnt = w->h_ppath.mnt -+ }; -+ struct inode *h_dir, *h_inode, *delegated; -+ struct file *infofile; -+ struct qstr *qname; -+ -+ AuDebugOn(elm -+ && memcmp(elm, page_address(ZERO_PAGE(0)), sizeof(*elm))); -+ -+ infopath.dentry = vfsub_lookup_one_len(w->whname, w->h_ppath.dentry, -+ w->whnamelen); -+ AuTraceErrPtr(infopath.dentry); -+ if (IS_ERR(infopath.dentry)) { -+ err = PTR_ERR(infopath.dentry); -+ goto out; -+ } -+ -+ err = 0; -+ h_dir = d_inode(w->h_ppath.dentry); -+ if (elm && d_is_negative(infopath.dentry)) { -+ err = vfsub_create(h_dir, &infopath, 0600, /*want_excl*/true); -+ AuTraceErr(err); -+ if (unlikely(err)) -+ goto out_dput; -+ elm->created = 1; -+ elm->info_dentry = dget(infopath.dentry); -+ } -+ -+ infofile = vfsub_dentry_open(&infopath, O_RDWR); -+ AuTraceErrPtr(infofile); -+ if (IS_ERR(infofile)) { -+ err = PTR_ERR(infofile); -+ goto out_dput; -+ } -+ -+ h_inode = d_inode(infopath.dentry); -+ if (elm && i_size_read(h_inode)) { -+ h_inode = d_inode(w->h_dentry); -+ elm->info_last = au_drinfo_read_k(infofile, h_inode->i_ino); -+ AuTraceErrPtr(elm->info_last); -+ if (IS_ERR(elm->info_last)) { -+ err = PTR_ERR(elm->info_last); -+ elm->info_last = NULL; -+ AuDebugOn(elm->info_dentry); -+ goto out_fput; -+ } -+ } -+ -+ if (elm && w->renameback) { -+ delegated = NULL; -+ err = vfsub_unlink(h_dir, &infopath, &delegated, /*force*/0); -+ AuTraceErr(err); -+ if (unlikely(err == -EWOULDBLOCK)) -+ iput(delegated); -+ goto out_fput; -+ } -+ -+ pos = 0; -+ qname = &w->h_dentry->d_name; -+ len = sizeof(*w->fdata) + qname->len; -+ if (!elm) -+ len = sizeof(*w->fdata) + w->fdata->drinfo.oldnamelen; -+ ssz = vfsub_write_k(infofile, w->fdata, len, &pos); -+ if (ssz == len) { -+ AuDbg("hi%llu, %.*s\n", w->fdata->drinfo.ino, -+ w->fdata->drinfo.oldnamelen, w->fdata->drinfo.oldname); -+ goto out_fput; /* success */ -+ } else { -+ err = -EIO; -+ if (ssz < 0) -+ err = ssz; -+ /* the caller should revert it using @elm */ -+ } -+ -+out_fput: -+ fput(infofile); -+out_dput: -+ dput(infopath.dentry); -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+struct au_call_drinfo_do_store_args { -+ int *errp; -+ struct au_drinfo_store *w; -+ struct au_drinfo_rev_elm *elm; -+}; -+ -+static void au_call_drinfo_do_store(void *args) -+{ -+ struct au_call_drinfo_do_store_args *a = args; -+ -+ *a->errp = au_drinfo_do_store(a->w, a->elm); -+} -+ -+static int au_drinfo_store_sio(struct au_drinfo_store *w, -+ struct au_drinfo_rev_elm *elm) -+{ -+ int err, wkq_err; -+ -+ if (w->no_sio) -+ err = au_drinfo_do_store(w, elm); -+ else { -+ struct au_call_drinfo_do_store_args a = { -+ .errp = &err, -+ .w = w, -+ .elm = elm -+ }; -+ wkq_err = au_wkq_wait(au_call_drinfo_do_store, &a); -+ if (unlikely(wkq_err)) -+ err = wkq_err; -+ } -+ AuTraceErr(err); -+ -+ return err; -+} -+ -+static int au_drinfo_store_work_init(struct au_drinfo_store *w, -+ aufs_bindex_t btgt) -+{ -+ int err; -+ -+ memset(w, 0, sizeof(*w)); -+ w->allocated = roundup_pow_of_two(sizeof(*w->fdata) + 40); -+ strcpy(w->whname, AUFS_WH_DR_INFO_PFX); -+ w->infoname = w->whname + sizeof(AUFS_WH_DR_INFO_PFX) - 1; -+ w->infonamelen = sizeof(w->whname) - sizeof(AUFS_WH_DR_INFO_PFX); -+ w->btgt = btgt; -+ w->no_sio = !!uid_eq(current_fsuid(), GLOBAL_ROOT_UID); -+ -+ err = -ENOMEM; -+ w->fdata = kcalloc(1, w->allocated, GFP_NOFS); -+ if (unlikely(!w->fdata)) { -+ AuTraceErr(err); -+ goto out; -+ } -+ w->fdata->magic = (__force uint32_t)htonl(AUFS_DRINFO_MAGIC_V1); -+ err = 0; -+ -+out: -+ return err; -+} -+ -+static void au_drinfo_store_work_fin(struct au_drinfo_store *w) -+{ -+ au_kfree_rcu(w->fdata); -+} -+ -+static void au_drinfo_store_rev(struct au_drinfo_rev *rev, -+ struct au_drinfo_store *w) -+{ -+ struct au_drinfo_rev_elm *elm; -+ struct inode *h_dir, *delegated; -+ int err, nelm; -+ struct path infopath = { -+ .mnt = w->h_ppath.mnt -+ }; -+ -+ h_dir = d_inode(w->h_ppath.dentry); -+ IMustLock(h_dir); -+ -+ err = 0; -+ elm = rev->elm; -+ for (nelm = rev->nelm; nelm > 0; nelm--, elm++) { -+ AuDebugOn(elm->created && elm->info_last); -+ if (elm->created) { -+ AuDbg("here\n"); -+ delegated = NULL; -+ infopath.dentry = elm->info_dentry; -+ err = vfsub_unlink(h_dir, &infopath, &delegated, -+ !w->no_sio); -+ AuTraceErr(err); -+ if (unlikely(err == -EWOULDBLOCK)) -+ iput(delegated); -+ dput(elm->info_dentry); -+ } else if (elm->info_last) { -+ AuDbg("here\n"); -+ w->fdata->drinfo = *elm->info_last; -+ memcpy(w->fdata->drinfo.oldname, -+ elm->info_last->oldname, -+ elm->info_last->oldnamelen); -+ err = au_drinfo_store_sio(w, /*elm*/NULL); -+ au_kfree_rcu(elm->info_last); -+ } -+ if (unlikely(err)) -+ AuIOErr("%d, %s\n", err, w->whname); -+ /* go on even if err */ -+ } -+} -+ -+/* caller has to call au_dr_rename_fin() later */ -+static int au_drinfo_store(struct dentry *dentry, aufs_bindex_t btgt, -+ struct qstr *dst_name, void *_rev) -+{ -+ int err, sz, nelm; -+ aufs_bindex_t bindex, btail; -+ struct au_drinfo_store work; -+ struct au_drinfo_rev *rev, **p; -+ struct au_drinfo_rev_elm *elm; -+ struct super_block *sb; -+ struct au_branch *br; -+ struct au_hinode *hdir; -+ -+ err = au_drinfo_store_work_init(&work, btgt); -+ AuTraceErr(err); -+ if (unlikely(err)) -+ goto out; -+ -+ err = -ENOMEM; -+ btail = au_dbtaildir(dentry); -+ nelm = btail - btgt; -+ sz = sizeof(*rev) + sizeof(*elm) * nelm; -+ rev = kcalloc(1, sz, GFP_NOFS); -+ if (unlikely(!rev)) { -+ AuTraceErr(err); -+ goto out_args; -+ } -+ rev->nelm = nelm; -+ elm = rev->elm; -+ p = _rev; -+ *p = rev; -+ -+ err = 0; -+ sb = dentry->d_sb; -+ work.h_ppath.dentry = au_h_dptr(dentry, btgt); -+ work.h_ppath.mnt = au_sbr_mnt(sb, btgt); -+ hdir = au_hi(d_inode(dentry), btgt); -+ au_hn_inode_lock_nested(hdir, AuLsc_I_CHILD); -+ for (bindex = btgt + 1; bindex <= btail; bindex++, elm++) { -+ work.h_dentry = au_h_dptr(dentry, bindex); -+ if (!work.h_dentry) -+ continue; -+ -+ err = au_drinfo_construct(&work.fdata, work.h_dentry, -+ &work.allocated); -+ AuTraceErr(err); -+ if (unlikely(err)) -+ break; -+ -+ work.renameback = au_qstreq(&work.h_dentry->d_name, dst_name); -+ br = au_sbr(sb, bindex); -+ work.whnamelen = sizeof(AUFS_WH_DR_INFO_PFX) - 1; -+ work.whnamelen += au_drinfo_name(br, work.infoname, -+ work.infonamelen); -+ AuDbg("whname %.*s, i%llu, %.*s\n", -+ work.whnamelen, work.whname, -+ be64_to_cpu((__force __be64)work.fdata->drinfo.ino), -+ work.fdata->drinfo.oldnamelen, -+ work.fdata->drinfo.oldname); -+ -+ err = au_drinfo_store_sio(&work, elm); -+ AuTraceErr(err); -+ if (unlikely(err)) -+ break; -+ } -+ if (unlikely(err)) { -+ /* revert all drinfo */ -+ au_drinfo_store_rev(rev, &work); -+ au_kfree_try_rcu(rev); -+ *p = NULL; -+ } -+ au_hn_inode_unlock(hdir); -+ -+out_args: -+ au_drinfo_store_work_fin(&work); -+out: -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+int au_dr_rename(struct dentry *src, aufs_bindex_t bindex, -+ struct qstr *dst_name, void *_rev) -+{ -+ int err, already; -+ ino_t ino; -+ struct super_block *sb; -+ struct au_branch *br; -+ struct au_dr_br *dr; -+ struct dentry *h_dentry; -+ struct inode *h_inode; -+ struct au_dr_hino *ent; -+ struct au_drinfo_rev *rev, **p; -+ -+ AuDbg("bindex %d\n", bindex); -+ -+ err = -ENOMEM; -+ ent = kmalloc(sizeof(*ent), GFP_NOFS); -+ if (unlikely(!ent)) -+ goto out; -+ -+ sb = src->d_sb; -+ br = au_sbr(sb, bindex); -+ dr = &br->br_dirren; -+ h_dentry = au_h_dptr(src, bindex); -+ h_inode = d_inode(h_dentry); -+ ino = h_inode->i_ino; -+ ent->dr_h_ino = ino; -+ already = au_dr_hino_test_add(dr, ino, ent); -+ AuDbg("b%d, hi%llu, already %d\n", -+ bindex, (unsigned long long)ino, already); -+ -+ err = au_drinfo_store(src, bindex, dst_name, _rev); -+ AuTraceErr(err); -+ if (!err) { -+ p = _rev; -+ rev = *p; -+ rev->already = already; -+ goto out; /* success */ -+ } -+ -+ /* revert */ -+ if (!already) -+ au_dr_hino_del(dr, ent); -+ au_kfree_rcu(ent); -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+void au_dr_rename_fin(struct dentry *src, aufs_bindex_t btgt, void *_rev) -+{ -+ struct au_drinfo_rev *rev; -+ struct au_drinfo_rev_elm *elm; -+ int nelm; -+ -+ rev = _rev; -+ elm = rev->elm; -+ for (nelm = rev->nelm; nelm > 0; nelm--, elm++) { -+ dput(elm->info_dentry); -+ au_kfree_rcu(elm->info_last); -+ } -+ au_kfree_try_rcu(rev); -+} -+ -+void au_dr_rename_rev(struct dentry *src, aufs_bindex_t btgt, void *_rev) -+{ -+ int err; -+ struct au_drinfo_store work; -+ struct au_drinfo_rev *rev = _rev; -+ struct super_block *sb; -+ struct au_branch *br; -+ struct inode *h_inode; -+ struct au_dr_br *dr; -+ struct au_dr_hino *ent; -+ -+ err = au_drinfo_store_work_init(&work, btgt); -+ if (unlikely(err)) -+ goto out; -+ -+ sb = src->d_sb; -+ br = au_sbr(sb, btgt); -+ work.h_ppath.dentry = au_h_dptr(src, btgt); -+ work.h_ppath.mnt = au_br_mnt(br); -+ au_drinfo_store_rev(rev, &work); -+ au_drinfo_store_work_fin(&work); -+ if (rev->already) -+ goto out; -+ -+ dr = &br->br_dirren; -+ h_inode = d_inode(work.h_ppath.dentry); -+ ent = au_dr_hino_find(dr, h_inode->i_ino); -+ BUG_ON(!ent); -+ au_dr_hino_del(dr, ent); -+ au_kfree_rcu(ent); -+ -+out: -+ au_kfree_try_rcu(rev); -+ if (unlikely(err)) -+ pr_err("failed to remove dirren info\n"); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static struct au_drinfo *au_drinfo_do_load(struct path *h_ppath, -+ char *whname, int whnamelen, -+ struct dentry **info_dentry) -+{ -+ struct au_drinfo *drinfo; -+ struct file *f; -+ struct inode *h_dir; -+ struct path infopath; -+ int unlocked; -+ -+ AuDbg("%pd/%.*s\n", h_ppath->dentry, whnamelen, whname); -+ -+ *info_dentry = NULL; -+ drinfo = NULL; -+ unlocked = 0; -+ h_dir = d_inode(h_ppath->dentry); -+ inode_lock_shared_nested(h_dir, AuLsc_I_PARENT); -+ infopath.dentry = vfsub_lookup_one_len(whname, h_ppath->dentry, -+ whnamelen); -+ if (IS_ERR(infopath.dentry)) { -+ drinfo = (void *)infopath.dentry; -+ goto out; -+ } -+ -+ if (d_is_negative(infopath.dentry)) -+ goto out_dput; /* success */ -+ -+ infopath.mnt = h_ppath->mnt; -+ f = vfsub_dentry_open(&infopath, O_RDONLY); -+ inode_unlock_shared(h_dir); -+ unlocked = 1; -+ if (IS_ERR(f)) { -+ drinfo = (void *)f; -+ goto out_dput; -+ } -+ -+ drinfo = au_drinfo_read_k(f, /*h_ino*/0); -+ if (IS_ERR_OR_NULL(drinfo)) -+ goto out_fput; -+ -+ AuDbg("oldname %.*s\n", drinfo->oldnamelen, drinfo->oldname); -+ *info_dentry = dget(infopath.dentry); /* keep it alive */ -+ -+out_fput: -+ fput(f); -+out_dput: -+ dput(infopath.dentry); -+out: -+ if (!unlocked) -+ inode_unlock_shared(h_dir); -+ AuTraceErrPtr(drinfo); -+ return drinfo; -+} -+ -+struct au_drinfo_do_load_args { -+ struct au_drinfo **drinfop; -+ struct path *h_ppath; -+ char *whname; -+ int whnamelen; -+ struct dentry **info_dentry; -+}; -+ -+static void au_call_drinfo_do_load(void *args) -+{ -+ struct au_drinfo_do_load_args *a = args; -+ -+ *a->drinfop = au_drinfo_do_load(a->h_ppath, a->whname, a->whnamelen, -+ a->info_dentry); -+} -+ -+struct au_drinfo_load { -+ struct path h_ppath; -+ struct qstr *qname; -+ unsigned char no_sio; -+ -+ aufs_bindex_t ninfo; -+ struct au_drinfo **drinfo; -+}; -+ -+static int au_drinfo_load(struct au_drinfo_load *w, aufs_bindex_t bindex, -+ struct au_branch *br) -+{ -+ int err, wkq_err, whnamelen, e; -+ char whname[sizeof(AUFS_WH_DR_INFO_PFX) + AUFS_DIRREN_ENV_VAL_SZ] -+ = AUFS_WH_DR_INFO_PFX; -+ struct au_drinfo *drinfo; -+ struct qstr oldname; -+ struct inode *h_dir, *delegated; -+ struct dentry *info_dentry; -+ struct path infopath; -+ -+ whnamelen = sizeof(AUFS_WH_DR_INFO_PFX) - 1; -+ whnamelen += au_drinfo_name(br, whname + whnamelen, -+ sizeof(whname) - whnamelen); -+ if (w->no_sio) -+ drinfo = au_drinfo_do_load(&w->h_ppath, whname, whnamelen, -+ &info_dentry); -+ else { -+ struct au_drinfo_do_load_args args = { -+ .drinfop = &drinfo, -+ .h_ppath = &w->h_ppath, -+ .whname = whname, -+ .whnamelen = whnamelen, -+ .info_dentry = &info_dentry -+ }; -+ wkq_err = au_wkq_wait(au_call_drinfo_do_load, &args); -+ if (unlikely(wkq_err)) -+ drinfo = ERR_PTR(wkq_err); -+ } -+ err = PTR_ERR(drinfo); -+ if (IS_ERR_OR_NULL(drinfo)) -+ goto out; -+ -+ err = 0; -+ oldname.len = drinfo->oldnamelen; -+ oldname.name = drinfo->oldname; -+ if (au_qstreq(w->qname, &oldname)) { -+ /* the name is renamed back */ -+ au_kfree_rcu(drinfo); -+ drinfo = NULL; -+ -+ infopath.dentry = info_dentry; -+ infopath.mnt = w->h_ppath.mnt; -+ h_dir = d_inode(w->h_ppath.dentry); -+ delegated = NULL; -+ inode_lock_nested(h_dir, AuLsc_I_PARENT); -+ e = vfsub_unlink(h_dir, &infopath, &delegated, !w->no_sio); -+ inode_unlock(h_dir); -+ if (unlikely(e)) -+ AuIOErr("ignored %d, %pd2\n", e, &infopath.dentry); -+ if (unlikely(e == -EWOULDBLOCK)) -+ iput(delegated); -+ } -+ au_kfree_rcu(w->drinfo[bindex]); -+ w->drinfo[bindex] = drinfo; -+ dput(info_dentry); -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static void au_dr_lkup_free(struct au_drinfo **drinfo, int n) -+{ -+ struct au_drinfo **p = drinfo; -+ -+ while (n-- > 0) -+ au_kfree_rcu(*drinfo++); -+ au_kfree_try_rcu(p); -+} -+ -+int au_dr_lkup(struct au_do_lookup_args *lkup, struct dentry *dentry, -+ aufs_bindex_t btgt) -+{ -+ int err, ninfo; -+ struct au_drinfo_load w; -+ aufs_bindex_t bindex, bbot; -+ struct au_branch *br; -+ struct inode *h_dir; -+ struct au_dr_hino *ent; -+ struct super_block *sb; -+ -+ AuDbg("%.*s, name %.*s, whname %.*s, b%d\n", -+ AuLNPair(&dentry->d_name), AuLNPair(&lkup->dirren.dr_name), -+ AuLNPair(&lkup->whname), btgt); -+ -+ sb = dentry->d_sb; -+ bbot = au_sbbot(sb); -+ w.ninfo = bbot + 1; -+ if (!lkup->dirren.drinfo) { -+ lkup->dirren.drinfo = kcalloc(w.ninfo, -+ sizeof(*lkup->dirren.drinfo), -+ GFP_NOFS); -+ if (unlikely(!lkup->dirren.drinfo)) { -+ err = -ENOMEM; -+ goto out; -+ } -+ lkup->dirren.ninfo = w.ninfo; -+ } -+ w.drinfo = lkup->dirren.drinfo; -+ w.no_sio = !!uid_eq(current_fsuid(), GLOBAL_ROOT_UID); -+ w.h_ppath.dentry = au_h_dptr(dentry, btgt); -+ AuDebugOn(!w.h_ppath.dentry); -+ w.h_ppath.mnt = au_sbr_mnt(sb, btgt); -+ w.qname = &dentry->d_name; -+ -+ ninfo = 0; -+ for (bindex = btgt + 1; bindex <= bbot; bindex++) { -+ br = au_sbr(sb, bindex); -+ err = au_drinfo_load(&w, bindex, br); -+ if (unlikely(err)) -+ goto out_free; -+ if (w.drinfo[bindex]) -+ ninfo++; -+ } -+ if (!ninfo) { -+ br = au_sbr(sb, btgt); -+ h_dir = d_inode(w.h_ppath.dentry); -+ ent = au_dr_hino_find(&br->br_dirren, h_dir->i_ino); -+ AuDebugOn(!ent); -+ au_dr_hino_del(&br->br_dirren, ent); -+ au_kfree_rcu(ent); -+ } -+ goto out; /* success */ -+ -+out_free: -+ au_dr_lkup_free(lkup->dirren.drinfo, lkup->dirren.ninfo); -+ lkup->dirren.ninfo = 0; -+ lkup->dirren.drinfo = NULL; -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+void au_dr_lkup_fin(struct au_do_lookup_args *lkup) -+{ -+ au_dr_lkup_free(lkup->dirren.drinfo, lkup->dirren.ninfo); -+} -+ -+int au_dr_lkup_name(struct au_do_lookup_args *lkup, aufs_bindex_t btgt) -+{ -+ int err; -+ struct au_drinfo *drinfo; -+ -+ err = 0; -+ if (!lkup->dirren.drinfo) -+ goto out; -+ AuDebugOn(lkup->dirren.ninfo <= btgt); -+ drinfo = lkup->dirren.drinfo[btgt]; -+ if (!drinfo) -+ goto out; -+ -+ au_kfree_try_rcu(lkup->whname.name); -+ lkup->whname.name = NULL; -+ lkup->dirren.dr_name.len = drinfo->oldnamelen; -+ lkup->dirren.dr_name.name = drinfo->oldname; -+ lkup->name = &lkup->dirren.dr_name; -+ err = au_wh_name_alloc(&lkup->whname, lkup->name); -+ if (!err) -+ AuDbg("name %.*s, whname %.*s, b%d\n", -+ AuLNPair(lkup->name), AuLNPair(&lkup->whname), -+ btgt); -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+int au_dr_lkup_h_ino(struct au_do_lookup_args *lkup, aufs_bindex_t bindex, -+ ino_t h_ino) -+{ -+ int match; -+ struct au_drinfo *drinfo; -+ -+ match = 1; -+ if (!lkup->dirren.drinfo) -+ goto out; -+ AuDebugOn(lkup->dirren.ninfo <= bindex); -+ drinfo = lkup->dirren.drinfo[bindex]; -+ if (!drinfo) -+ goto out; -+ -+ match = (drinfo->ino == h_ino); -+ AuDbg("match %d\n", match); -+ -+out: -+ return match; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+int au_dr_opt_set(struct super_block *sb) -+{ -+ int err; -+ aufs_bindex_t bindex, bbot; -+ struct au_branch *br; -+ -+ err = 0; -+ bbot = au_sbbot(sb); -+ for (bindex = 0; !err && bindex <= bbot; bindex++) { -+ br = au_sbr(sb, bindex); -+ err = au_dr_hino(sb, bindex, /*br*/NULL, &br->br_path); -+ } -+ -+ return err; -+} -+ -+int au_dr_opt_flush(struct super_block *sb) -+{ -+ int err; -+ aufs_bindex_t bindex, bbot; -+ struct au_branch *br; -+ -+ err = 0; -+ bbot = au_sbbot(sb); -+ for (bindex = 0; !err && bindex <= bbot; bindex++) { -+ br = au_sbr(sb, bindex); -+ if (au_br_writable(br->br_perm)) -+ err = au_dr_hino(sb, bindex, /*br*/NULL, /*path*/NULL); -+ } -+ -+ return err; -+} -+ -+int au_dr_opt_clr(struct super_block *sb, int no_flush) -+{ -+ int err; -+ aufs_bindex_t bindex, bbot; -+ struct au_branch *br; -+ -+ err = 0; -+ if (!no_flush) { -+ err = au_dr_opt_flush(sb); -+ if (unlikely(err)) -+ goto out; -+ } -+ -+ bbot = au_sbbot(sb); -+ for (bindex = 0; bindex <= bbot; bindex++) { -+ br = au_sbr(sb, bindex); -+ au_dr_hino_free(&br->br_dirren); -+ } -+ -+out: -+ return err; -+} -diff -Nurp linux-5.10-rc6/fs/aufs/dirren.h linux-5.10-rc6.aufs/fs/aufs/dirren.h ---- linux-5.10-rc6/fs/aufs/dirren.h 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/dirren.h 2020-12-02 21:19:51.881036743 +0200 -@@ -0,0 +1,127 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2017-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * renamed dir info -+ */ -+ -+#ifndef __AUFS_DIRREN_H__ -+#define __AUFS_DIRREN_H__ -+ -+#ifdef __KERNEL__ -+ -+#include -+#include -+#include -+#include "hbl.h" -+ -+#define AuDirren_NHASH 100 -+ -+#ifdef CONFIG_AUFS_DIRREN -+enum au_brid_type { -+ AuBrid_Unset, -+ AuBrid_UUID, -+ AuBrid_FSID, -+ AuBrid_DEV -+}; -+ -+struct au_dr_brid { -+ enum au_brid_type type; -+ union { -+ uuid_t uuid; /* unimplemented yet */ -+ fsid_t fsid; -+ dev_t dev; -+ }; -+}; -+ -+/* 20 is the max digits length of ulong 64 */ -+/* brid-type "_" uuid "_" inum */ -+#define AUFS_DIRREN_FNAME_SZ (1 + 1 + UUID_STRING_LEN + 20) -+#define AUFS_DIRREN_ENV_VAL_SZ (AUFS_DIRREN_FNAME_SZ + 1 + 20) -+ -+struct au_dr_hino { -+ struct hlist_bl_node dr_hnode; -+ ino_t dr_h_ino; -+}; -+ -+struct au_dr_br { -+ struct hlist_bl_head dr_h_ino[AuDirren_NHASH]; -+ struct au_dr_brid dr_brid; -+}; -+ -+struct au_dr_lookup { -+ /* dr_name is pointed by struct au_do_lookup_args.name */ -+ struct qstr dr_name; /* subset of dr_info */ -+ aufs_bindex_t ninfo; -+ struct au_drinfo **drinfo; -+}; -+#else -+struct au_dr_hino; -+/* empty */ -+struct au_dr_br { }; -+struct au_dr_lookup { }; -+#endif -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct au_branch; -+struct au_do_lookup_args; -+struct au_hinode; -+#ifdef CONFIG_AUFS_DIRREN -+int au_dr_hino_test_add(struct au_dr_br *dr, ino_t h_ino, -+ struct au_dr_hino *add_ent); -+void au_dr_hino_free(struct au_dr_br *dr); -+int au_dr_br_init(struct super_block *sb, struct au_branch *br, -+ const struct path *path); -+int au_dr_br_fin(struct super_block *sb, struct au_branch *br); -+int au_dr_rename(struct dentry *src, aufs_bindex_t bindex, -+ struct qstr *dst_name, void *_rev); -+void au_dr_rename_fin(struct dentry *src, aufs_bindex_t btgt, void *rev); -+void au_dr_rename_rev(struct dentry *src, aufs_bindex_t bindex, void *rev); -+int au_dr_lkup(struct au_do_lookup_args *lkup, struct dentry *dentry, -+ aufs_bindex_t bindex); -+int au_dr_lkup_name(struct au_do_lookup_args *lkup, aufs_bindex_t btgt); -+int au_dr_lkup_h_ino(struct au_do_lookup_args *lkup, aufs_bindex_t bindex, -+ ino_t h_ino); -+void au_dr_lkup_fin(struct au_do_lookup_args *lkup); -+int au_dr_opt_set(struct super_block *sb); -+int au_dr_opt_flush(struct super_block *sb); -+int au_dr_opt_clr(struct super_block *sb, int no_flush); -+#else -+AuStubInt0(au_dr_hino_test_add, struct au_dr_br *dr, ino_t h_ino, -+ struct au_dr_hino *add_ent); -+AuStubVoid(au_dr_hino_free, struct au_dr_br *dr); -+AuStubInt0(au_dr_br_init, struct super_block *sb, struct au_branch *br, -+ const struct path *path); -+AuStubInt0(au_dr_br_fin, struct super_block *sb, struct au_branch *br); -+AuStubInt0(au_dr_rename, struct dentry *src, aufs_bindex_t bindex, -+ struct qstr *dst_name, void *_rev); -+AuStubVoid(au_dr_rename_fin, struct dentry *src, aufs_bindex_t btgt, void *rev); -+AuStubVoid(au_dr_rename_rev, struct dentry *src, aufs_bindex_t bindex, -+ void *rev); -+AuStubInt0(au_dr_lkup, struct au_do_lookup_args *lkup, struct dentry *dentry, -+ aufs_bindex_t bindex); -+AuStubInt0(au_dr_lkup_name, struct au_do_lookup_args *lkup, aufs_bindex_t btgt); -+AuStubInt0(au_dr_lkup_h_ino, struct au_do_lookup_args *lkup, -+ aufs_bindex_t bindex, ino_t h_ino); -+AuStubVoid(au_dr_lkup_fin, struct au_do_lookup_args *lkup); -+AuStubInt0(au_dr_opt_set, struct super_block *sb); -+AuStubInt0(au_dr_opt_flush, struct super_block *sb); -+AuStubInt0(au_dr_opt_clr, struct super_block *sb, int no_flush); -+#endif -+ -+/* ---------------------------------------------------------------------- */ -+ -+#ifdef CONFIG_AUFS_DIRREN -+static inline int au_dr_ihash(ino_t h_ino) -+{ -+ return h_ino % AuDirren_NHASH; -+} -+#else -+AuStubInt0(au_dr_ihash, ino_t h_ino); -+#endif -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_DIRREN_H__ */ -diff -Nurp linux-5.10-rc6/fs/aufs/dynop.c linux-5.10-rc6.aufs/fs/aufs/dynop.c ---- linux-5.10-rc6/fs/aufs/dynop.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/dynop.c 2020-12-02 21:19:51.881036743 +0200 -@@ -0,0 +1,354 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2010-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * dynamically customizable operations for regular files -+ */ -+ -+#include "aufs.h" -+ -+#define DyPrSym(key) AuDbgSym(key->dk_op.dy_hop) -+ -+/* -+ * How large will these lists be? -+ * Usually just a few elements, 20-30 at most for each, I guess. -+ */ -+static struct hlist_bl_head dynop[AuDyLast]; -+ -+static struct au_dykey *dy_gfind_get(struct hlist_bl_head *hbl, -+ const void *h_op) -+{ -+ struct au_dykey *key, *tmp; -+ struct hlist_bl_node *pos; -+ -+ key = NULL; -+ hlist_bl_lock(hbl); -+ hlist_bl_for_each_entry(tmp, pos, hbl, dk_hnode) -+ if (tmp->dk_op.dy_hop == h_op) { -+ if (kref_get_unless_zero(&tmp->dk_kref)) -+ key = tmp; -+ break; -+ } -+ hlist_bl_unlock(hbl); -+ -+ return key; -+} -+ -+static struct au_dykey *dy_bradd(struct au_branch *br, struct au_dykey *key) -+{ -+ struct au_dykey **k, *found; -+ const void *h_op = key->dk_op.dy_hop; -+ int i; -+ -+ found = NULL; -+ k = br->br_dykey; -+ for (i = 0; i < AuBrDynOp; i++) -+ if (k[i]) { -+ if (k[i]->dk_op.dy_hop == h_op) { -+ found = k[i]; -+ break; -+ } -+ } else -+ break; -+ if (!found) { -+ spin_lock(&br->br_dykey_lock); -+ for (; i < AuBrDynOp; i++) -+ if (k[i]) { -+ if (k[i]->dk_op.dy_hop == h_op) { -+ found = k[i]; -+ break; -+ } -+ } else { -+ k[i] = key; -+ break; -+ } -+ spin_unlock(&br->br_dykey_lock); -+ BUG_ON(i == AuBrDynOp); /* expand the array */ -+ } -+ -+ return found; -+} -+ -+/* kref_get() if @key is already added */ -+static struct au_dykey *dy_gadd(struct hlist_bl_head *hbl, struct au_dykey *key) -+{ -+ struct au_dykey *tmp, *found; -+ struct hlist_bl_node *pos; -+ const void *h_op = key->dk_op.dy_hop; -+ -+ found = NULL; -+ hlist_bl_lock(hbl); -+ hlist_bl_for_each_entry(tmp, pos, hbl, dk_hnode) -+ if (tmp->dk_op.dy_hop == h_op) { -+ if (kref_get_unless_zero(&tmp->dk_kref)) -+ found = tmp; -+ break; -+ } -+ if (!found) -+ hlist_bl_add_head(&key->dk_hnode, hbl); -+ hlist_bl_unlock(hbl); -+ -+ if (!found) -+ DyPrSym(key); -+ return found; -+} -+ -+static void dy_free_rcu(struct rcu_head *rcu) -+{ -+ struct au_dykey *key; -+ -+ key = container_of(rcu, struct au_dykey, dk_rcu); -+ DyPrSym(key); -+ kfree(key); -+} -+ -+static void dy_free(struct kref *kref) -+{ -+ struct au_dykey *key; -+ struct hlist_bl_head *hbl; -+ -+ key = container_of(kref, struct au_dykey, dk_kref); -+ hbl = dynop + key->dk_op.dy_type; -+ au_hbl_del(&key->dk_hnode, hbl); -+ call_rcu(&key->dk_rcu, dy_free_rcu); -+} -+ -+void au_dy_put(struct au_dykey *key) -+{ -+ kref_put(&key->dk_kref, dy_free); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+#define DyDbgSize(cnt, op) AuDebugOn(cnt != sizeof(op)/sizeof(void *)) -+ -+#ifdef CONFIG_AUFS_DEBUG -+#define DyDbgDeclare(cnt) unsigned int cnt = 0 -+#define DyDbgInc(cnt) do { cnt++; } while (0) -+#else -+#define DyDbgDeclare(cnt) do {} while (0) -+#define DyDbgInc(cnt) do {} while (0) -+#endif -+ -+#define DySet(func, dst, src, h_op, h_sb) do { \ -+ DyDbgInc(cnt); \ -+ if (h_op->func) { \ -+ if (src.func) \ -+ dst.func = src.func; \ -+ else \ -+ AuDbg("%s %s\n", au_sbtype(h_sb), #func); \ -+ } \ -+} while (0) -+ -+#define DySetForce(func, dst, src) do { \ -+ AuDebugOn(!src.func); \ -+ DyDbgInc(cnt); \ -+ dst.func = src.func; \ -+} while (0) -+ -+#define DySetAop(func) \ -+ DySet(func, dyaop->da_op, aufs_aop, h_aop, h_sb) -+#define DySetAopForce(func) \ -+ DySetForce(func, dyaop->da_op, aufs_aop) -+ -+static void dy_aop(struct au_dykey *key, const void *h_op, -+ struct super_block *h_sb __maybe_unused) -+{ -+ struct au_dyaop *dyaop = (void *)key; -+ const struct address_space_operations *h_aop = h_op; -+ DyDbgDeclare(cnt); -+ -+ AuDbg("%s\n", au_sbtype(h_sb)); -+ -+ DySetAop(writepage); -+ DySetAopForce(readpage); /* force */ -+ DySetAop(writepages); -+ DySetAop(set_page_dirty); -+ DySetAop(readpages); -+ DySetAop(write_begin); -+ DySetAop(write_end); -+ DySetAop(bmap); -+ DySetAop(invalidatepage); -+ DySetAop(releasepage); -+ DySetAop(freepage); -+ /* this one will be changed according to an aufs mount option */ -+ DySetAop(direct_IO); -+ DySetAop(migratepage); -+ DySetAop(isolate_page); -+ DySetAop(putback_page); -+ DySetAop(launder_page); -+ DySetAop(is_partially_uptodate); -+ DySetAop(is_dirty_writeback); -+ DySetAop(error_remove_page); -+ DySetAop(swap_activate); -+ DySetAop(swap_deactivate); -+ -+ DyDbgSize(cnt, *h_aop); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static void dy_bug(struct kref *kref) -+{ -+ BUG(); -+} -+ -+static struct au_dykey *dy_get(struct au_dynop *op, struct au_branch *br) -+{ -+ struct au_dykey *key, *old; -+ struct hlist_bl_head *hbl; -+ struct op { -+ unsigned int sz; -+ void (*set)(struct au_dykey *key, const void *h_op, -+ struct super_block *h_sb __maybe_unused); -+ }; -+ static const struct op a[] = { -+ [AuDy_AOP] = { -+ .sz = sizeof(struct au_dyaop), -+ .set = dy_aop -+ } -+ }; -+ const struct op *p; -+ -+ hbl = dynop + op->dy_type; -+ key = dy_gfind_get(hbl, op->dy_hop); -+ if (key) -+ goto out_add; /* success */ -+ -+ p = a + op->dy_type; -+ key = kzalloc(p->sz, GFP_NOFS); -+ if (unlikely(!key)) { -+ key = ERR_PTR(-ENOMEM); -+ goto out; -+ } -+ -+ key->dk_op.dy_hop = op->dy_hop; -+ kref_init(&key->dk_kref); -+ p->set(key, op->dy_hop, au_br_sb(br)); -+ old = dy_gadd(hbl, key); -+ if (old) { -+ au_kfree_rcu(key); -+ key = old; -+ } -+ -+out_add: -+ old = dy_bradd(br, key); -+ if (old) -+ /* its ref-count should never be zero here */ -+ kref_put(&key->dk_kref, dy_bug); -+out: -+ return key; -+} -+ -+/* ---------------------------------------------------------------------- */ -+/* -+ * Aufs prohibits O_DIRECT by default even if the branch supports it. -+ * This behaviour is necessary to return an error from open(O_DIRECT) instead -+ * of the succeeding I/O. The dio mount option enables O_DIRECT and makes -+ * open(O_DIRECT) always succeed, but the succeeding I/O may return an error. -+ * See the aufs manual in detail. -+ */ -+static void dy_adx(struct au_dyaop *dyaop, int do_dx) -+{ -+ if (!do_dx) -+ dyaop->da_op.direct_IO = NULL; -+ else -+ dyaop->da_op.direct_IO = aufs_aop.direct_IO; -+} -+ -+static struct au_dyaop *dy_aget(struct au_branch *br, -+ const struct address_space_operations *h_aop, -+ int do_dx) -+{ -+ struct au_dyaop *dyaop; -+ struct au_dynop op; -+ -+ op.dy_type = AuDy_AOP; -+ op.dy_haop = h_aop; -+ dyaop = (void *)dy_get(&op, br); -+ if (IS_ERR(dyaop)) -+ goto out; -+ dy_adx(dyaop, do_dx); -+ -+out: -+ return dyaop; -+} -+ -+int au_dy_iaop(struct inode *inode, aufs_bindex_t bindex, -+ struct inode *h_inode) -+{ -+ int err, do_dx; -+ struct super_block *sb; -+ struct au_branch *br; -+ struct au_dyaop *dyaop; -+ -+ AuDebugOn(!S_ISREG(h_inode->i_mode)); -+ IiMustWriteLock(inode); -+ -+ sb = inode->i_sb; -+ br = au_sbr(sb, bindex); -+ do_dx = !!au_opt_test(au_mntflags(sb), DIO); -+ dyaop = dy_aget(br, h_inode->i_mapping->a_ops, do_dx); -+ err = PTR_ERR(dyaop); -+ if (IS_ERR(dyaop)) -+ /* unnecessary to call dy_fput() */ -+ goto out; -+ -+ err = 0; -+ inode->i_mapping->a_ops = &dyaop->da_op; -+ -+out: -+ return err; -+} -+ -+/* -+ * Is it safe to replace a_ops during the inode/file is in operation? -+ * Yes, I hope so. -+ */ -+int au_dy_irefresh(struct inode *inode) -+{ -+ int err; -+ aufs_bindex_t btop; -+ struct inode *h_inode; -+ -+ err = 0; -+ if (S_ISREG(inode->i_mode)) { -+ btop = au_ibtop(inode); -+ h_inode = au_h_iptr(inode, btop); -+ err = au_dy_iaop(inode, btop, h_inode); -+ } -+ return err; -+} -+ -+void au_dy_arefresh(int do_dx) -+{ -+ struct hlist_bl_head *hbl; -+ struct hlist_bl_node *pos; -+ struct au_dykey *key; -+ -+ hbl = dynop + AuDy_AOP; -+ hlist_bl_lock(hbl); -+ hlist_bl_for_each_entry(key, pos, hbl, dk_hnode) -+ dy_adx((void *)key, do_dx); -+ hlist_bl_unlock(hbl); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+void __init au_dy_init(void) -+{ -+ int i; -+ -+ for (i = 0; i < AuDyLast; i++) -+ INIT_HLIST_BL_HEAD(dynop + i); -+} -+ -+void au_dy_fin(void) -+{ -+ int i; -+ -+ for (i = 0; i < AuDyLast; i++) -+ WARN_ON(!hlist_bl_empty(dynop + i)); -+} -diff -Nurp linux-5.10-rc6/fs/aufs/dynop.h linux-5.10-rc6.aufs/fs/aufs/dynop.h ---- linux-5.10-rc6/fs/aufs/dynop.h 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/dynop.h 2020-12-02 21:19:51.881036743 +0200 -@@ -0,0 +1,64 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2010-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * dynamically customizable operations (for regular files only) -+ */ -+ -+#ifndef __AUFS_DYNOP_H__ -+#define __AUFS_DYNOP_H__ -+ -+#ifdef __KERNEL__ -+ -+#include -+#include -+ -+enum {AuDy_AOP, AuDyLast}; -+ -+struct au_dynop { -+ int dy_type; -+ union { -+ const void *dy_hop; -+ const struct address_space_operations *dy_haop; -+ }; -+}; -+ -+struct au_dykey { -+ union { -+ struct hlist_bl_node dk_hnode; -+ struct rcu_head dk_rcu; -+ }; -+ struct au_dynop dk_op; -+ -+ /* -+ * during I am in the branch local array, kref is gotten. when the -+ * branch is removed, kref is put. -+ */ -+ struct kref dk_kref; -+}; -+ -+/* stop unioning since their sizes are very different from each other */ -+struct au_dyaop { -+ struct au_dykey da_key; -+ struct address_space_operations da_op; /* not const */ -+}; -+/* make sure that 'struct au_dykey *' can be any type */ -+static_assert(!offsetof(struct au_dyaop, da_key)); -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* dynop.c */ -+struct au_branch; -+void au_dy_put(struct au_dykey *key); -+int au_dy_iaop(struct inode *inode, aufs_bindex_t bindex, -+ struct inode *h_inode); -+int au_dy_irefresh(struct inode *inode); -+void au_dy_arefresh(int do_dio); -+ -+void __init au_dy_init(void); -+void au_dy_fin(void); -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_DYNOP_H__ */ -diff -Nurp linux-5.10-rc6/fs/aufs/export.c linux-5.10-rc6.aufs/fs/aufs/export.c ---- linux-5.10-rc6/fs/aufs/export.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/export.c 2020-12-02 21:19:51.881036743 +0200 -@@ -0,0 +1,825 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * export via nfs -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include "aufs.h" -+ -+union conv { -+#ifdef CONFIG_AUFS_INO_T_64 -+ __u32 a[2]; -+#else -+ __u32 a[1]; -+#endif -+ ino_t ino; -+}; -+ -+static ino_t decode_ino(__u32 *a) -+{ -+ union conv u; -+ -+ BUILD_BUG_ON(sizeof(u.ino) != sizeof(u.a)); -+ u.a[0] = a[0]; -+#ifdef CONFIG_AUFS_INO_T_64 -+ u.a[1] = a[1]; -+#endif -+ return u.ino; -+} -+ -+static void encode_ino(__u32 *a, ino_t ino) -+{ -+ union conv u; -+ -+ u.ino = ino; -+ a[0] = u.a[0]; -+#ifdef CONFIG_AUFS_INO_T_64 -+ a[1] = u.a[1]; -+#endif -+} -+ -+/* NFS file handle */ -+enum { -+ Fh_br_id, -+ Fh_sigen, -+#ifdef CONFIG_AUFS_INO_T_64 -+ /* support 64bit inode number */ -+ Fh_ino1, -+ Fh_ino2, -+ Fh_dir_ino1, -+ Fh_dir_ino2, -+#else -+ Fh_ino1, -+ Fh_dir_ino1, -+#endif -+ Fh_igen, -+ Fh_h_type, -+ Fh_tail, -+ -+ Fh_ino = Fh_ino1, -+ Fh_dir_ino = Fh_dir_ino1 -+}; -+ -+static int au_test_anon(struct dentry *dentry) -+{ -+ /* note: read d_flags without d_lock */ -+ return !!(dentry->d_flags & DCACHE_DISCONNECTED); -+} -+ -+int au_test_nfsd(void) -+{ -+ int ret; -+ struct task_struct *tsk = current; -+ char comm[sizeof(tsk->comm)]; -+ -+ ret = 0; -+ if (tsk->flags & PF_KTHREAD) { -+ get_task_comm(comm, tsk); -+ ret = !strcmp(comm, "nfsd"); -+ } -+ -+ return ret; -+} -+ -+/* ---------------------------------------------------------------------- */ -+/* inode generation external table */ -+ -+void au_xigen_inc(struct inode *inode) -+{ -+ loff_t pos; -+ ssize_t sz; -+ __u32 igen; -+ struct super_block *sb; -+ struct au_sbinfo *sbinfo; -+ -+ sb = inode->i_sb; -+ AuDebugOn(!au_opt_test(au_mntflags(sb), XINO)); -+ -+ sbinfo = au_sbi(sb); -+ pos = inode->i_ino; -+ pos *= sizeof(igen); -+ igen = inode->i_generation + 1; -+ sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xigen, &igen, -+ sizeof(igen), &pos); -+ if (sz == sizeof(igen)) -+ return; /* success */ -+ -+ if (unlikely(sz >= 0)) -+ AuIOErr("xigen error (%zd)\n", sz); -+} -+ -+int au_xigen_new(struct inode *inode) -+{ -+ int err; -+ loff_t pos; -+ ssize_t sz; -+ struct super_block *sb; -+ struct au_sbinfo *sbinfo; -+ struct file *file; -+ -+ err = 0; -+ /* todo: dirty, at mount time */ -+ if (inode->i_ino == AUFS_ROOT_INO) -+ goto out; -+ sb = inode->i_sb; -+ SiMustAnyLock(sb); -+ if (unlikely(!au_opt_test(au_mntflags(sb), XINO))) -+ goto out; -+ -+ err = -EFBIG; -+ pos = inode->i_ino; -+ if (unlikely(au_loff_max / sizeof(inode->i_generation) - 1 < pos)) { -+ AuIOErr1("too large i%lld\n", pos); -+ goto out; -+ } -+ pos *= sizeof(inode->i_generation); -+ -+ err = 0; -+ sbinfo = au_sbi(sb); -+ file = sbinfo->si_xigen; -+ BUG_ON(!file); -+ -+ if (vfsub_f_size_read(file) -+ < pos + sizeof(inode->i_generation)) { -+ inode->i_generation = atomic_inc_return(&sbinfo->si_xigen_next); -+ sz = xino_fwrite(sbinfo->si_xwrite, file, &inode->i_generation, -+ sizeof(inode->i_generation), &pos); -+ } else -+ sz = xino_fread(sbinfo->si_xread, file, &inode->i_generation, -+ sizeof(inode->i_generation), &pos); -+ if (sz == sizeof(inode->i_generation)) -+ goto out; /* success */ -+ -+ err = sz; -+ if (unlikely(sz >= 0)) { -+ err = -EIO; -+ AuIOErr("xigen error (%zd)\n", sz); -+ } -+ -+out: -+ return err; -+} -+ -+int au_xigen_set(struct super_block *sb, struct path *path) -+{ -+ int err; -+ struct au_sbinfo *sbinfo; -+ struct file *file; -+ -+ SiMustWriteLock(sb); -+ -+ sbinfo = au_sbi(sb); -+ file = au_xino_create2(sb, path, sbinfo->si_xigen); -+ err = PTR_ERR(file); -+ if (IS_ERR(file)) -+ goto out; -+ err = 0; -+ if (sbinfo->si_xigen) -+ fput(sbinfo->si_xigen); -+ sbinfo->si_xigen = file; -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+void au_xigen_clr(struct super_block *sb) -+{ -+ struct au_sbinfo *sbinfo; -+ -+ SiMustWriteLock(sb); -+ -+ sbinfo = au_sbi(sb); -+ if (sbinfo->si_xigen) { -+ fput(sbinfo->si_xigen); -+ sbinfo->si_xigen = NULL; -+ } -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static struct dentry *decode_by_ino(struct super_block *sb, ino_t ino, -+ ino_t dir_ino) -+{ -+ struct dentry *dentry, *d; -+ struct inode *inode; -+ unsigned int sigen; -+ -+ dentry = NULL; -+ inode = ilookup(sb, ino); -+ if (!inode) -+ goto out; -+ -+ dentry = ERR_PTR(-ESTALE); -+ sigen = au_sigen(sb); -+ if (unlikely(au_is_bad_inode(inode) -+ || IS_DEADDIR(inode) -+ || sigen != au_iigen(inode, NULL))) -+ goto out_iput; -+ -+ dentry = NULL; -+ if (!dir_ino || S_ISDIR(inode->i_mode)) -+ dentry = d_find_alias(inode); -+ else { -+ spin_lock(&inode->i_lock); -+ hlist_for_each_entry(d, &inode->i_dentry, d_u.d_alias) { -+ spin_lock(&d->d_lock); -+ if (!au_test_anon(d) -+ && d_inode(d->d_parent)->i_ino == dir_ino) { -+ dentry = dget_dlock(d); -+ spin_unlock(&d->d_lock); -+ break; -+ } -+ spin_unlock(&d->d_lock); -+ } -+ spin_unlock(&inode->i_lock); -+ } -+ if (unlikely(dentry && au_digen_test(dentry, sigen))) { -+ /* need to refresh */ -+ dput(dentry); -+ dentry = NULL; -+ } -+ -+out_iput: -+ iput(inode); -+out: -+ AuTraceErrPtr(dentry); -+ return dentry; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* todo: dirty? */ -+/* if exportfs_decode_fh() passed vfsmount*, we could be happy */ -+ -+struct au_compare_mnt_args { -+ /* input */ -+ struct super_block *sb; -+ -+ /* output */ -+ struct vfsmount *mnt; -+}; -+ -+static int au_compare_mnt(struct vfsmount *mnt, void *arg) -+{ -+ struct au_compare_mnt_args *a = arg; -+ -+ if (mnt->mnt_sb != a->sb) -+ return 0; -+ a->mnt = mntget(mnt); -+ return 1; -+} -+ -+static struct vfsmount *au_mnt_get(struct super_block *sb) -+{ -+ int err; -+ struct path root; -+ struct au_compare_mnt_args args = { -+ .sb = sb -+ }; -+ -+ get_fs_root(current->fs, &root); -+ rcu_read_lock(); -+ err = iterate_mounts(au_compare_mnt, &args, root.mnt); -+ rcu_read_unlock(); -+ path_put(&root); -+ AuDebugOn(!err); -+ AuDebugOn(!args.mnt); -+ return args.mnt; -+} -+ -+struct au_nfsd_si_lock { -+ unsigned int sigen; -+ aufs_bindex_t bindex, br_id; -+ unsigned char force_lock; -+}; -+ -+static int si_nfsd_read_lock(struct super_block *sb, -+ struct au_nfsd_si_lock *nsi_lock) -+{ -+ int err; -+ aufs_bindex_t bindex; -+ -+ si_read_lock(sb, AuLock_FLUSH); -+ -+ /* branch id may be wrapped around */ -+ err = 0; -+ bindex = au_br_index(sb, nsi_lock->br_id); -+ if (bindex >= 0 && nsi_lock->sigen + AUFS_BRANCH_MAX > au_sigen(sb)) -+ goto out; /* success */ -+ -+ err = -ESTALE; -+ bindex = -1; -+ if (!nsi_lock->force_lock) -+ si_read_unlock(sb); -+ -+out: -+ nsi_lock->bindex = bindex; -+ return err; -+} -+ -+struct find_name_by_ino { -+ struct dir_context ctx; -+ int called, found; -+ ino_t ino; -+ char *name; -+ int namelen; -+}; -+ -+static int -+find_name_by_ino(struct dir_context *ctx, const char *name, int namelen, -+ loff_t offset, u64 ino, unsigned int d_type) -+{ -+ struct find_name_by_ino *a = container_of(ctx, struct find_name_by_ino, -+ ctx); -+ -+ a->called++; -+ if (a->ino != ino) -+ return 0; -+ -+ memcpy(a->name, name, namelen); -+ a->namelen = namelen; -+ a->found = 1; -+ return 1; -+} -+ -+static struct dentry *au_lkup_by_ino(struct path *path, ino_t ino, -+ struct au_nfsd_si_lock *nsi_lock) -+{ -+ struct dentry *dentry, *parent; -+ struct file *file; -+ struct inode *dir; -+ struct find_name_by_ino arg = { -+ .ctx = { -+ .actor = find_name_by_ino -+ } -+ }; -+ int err; -+ -+ parent = path->dentry; -+ if (nsi_lock) -+ si_read_unlock(parent->d_sb); -+ file = vfsub_dentry_open(path, au_dir_roflags); -+ dentry = (void *)file; -+ if (IS_ERR(file)) -+ goto out; -+ -+ dentry = ERR_PTR(-ENOMEM); -+ arg.name = (void *)__get_free_page(GFP_NOFS); -+ if (unlikely(!arg.name)) -+ goto out_file; -+ arg.ino = ino; -+ arg.found = 0; -+ do { -+ arg.called = 0; -+ /* smp_mb(); */ -+ err = vfsub_iterate_dir(file, &arg.ctx); -+ } while (!err && !arg.found && arg.called); -+ dentry = ERR_PTR(err); -+ if (unlikely(err)) -+ goto out_name; -+ /* instead of ENOENT */ -+ dentry = ERR_PTR(-ESTALE); -+ if (!arg.found) -+ goto out_name; -+ -+ /* do not call vfsub_lkup_one() */ -+ dir = d_inode(parent); -+ dentry = vfsub_lookup_one_len_unlocked(arg.name, parent, arg.namelen); -+ AuTraceErrPtr(dentry); -+ if (IS_ERR(dentry)) -+ goto out_name; -+ AuDebugOn(au_test_anon(dentry)); -+ if (unlikely(d_really_is_negative(dentry))) { -+ dput(dentry); -+ dentry = ERR_PTR(-ENOENT); -+ } -+ -+out_name: -+ free_page((unsigned long)arg.name); -+out_file: -+ fput(file); -+out: -+ if (unlikely(nsi_lock -+ && si_nfsd_read_lock(parent->d_sb, nsi_lock) < 0)) -+ if (!IS_ERR(dentry)) { -+ dput(dentry); -+ dentry = ERR_PTR(-ESTALE); -+ } -+ AuTraceErrPtr(dentry); -+ return dentry; -+} -+ -+static struct dentry *decode_by_dir_ino(struct super_block *sb, ino_t ino, -+ ino_t dir_ino, -+ struct au_nfsd_si_lock *nsi_lock) -+{ -+ struct dentry *dentry; -+ struct path path; -+ -+ if (dir_ino != AUFS_ROOT_INO) { -+ path.dentry = decode_by_ino(sb, dir_ino, 0); -+ dentry = path.dentry; -+ if (!path.dentry || IS_ERR(path.dentry)) -+ goto out; -+ AuDebugOn(au_test_anon(path.dentry)); -+ } else -+ path.dentry = dget(sb->s_root); -+ -+ path.mnt = au_mnt_get(sb); -+ dentry = au_lkup_by_ino(&path, ino, nsi_lock); -+ path_put(&path); -+ -+out: -+ AuTraceErrPtr(dentry); -+ return dentry; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int h_acceptable(void *expv, struct dentry *dentry) -+{ -+ return 1; -+} -+ -+static char *au_build_path(struct dentry *h_parent, struct path *h_rootpath, -+ char *buf, int len, struct super_block *sb) -+{ -+ char *p; -+ int n; -+ struct path path; -+ -+ p = d_path(h_rootpath, buf, len); -+ if (IS_ERR(p)) -+ goto out; -+ n = strlen(p); -+ -+ path.mnt = h_rootpath->mnt; -+ path.dentry = h_parent; -+ p = d_path(&path, buf, len); -+ if (IS_ERR(p)) -+ goto out; -+ if (n != 1) -+ p += n; -+ -+ path.mnt = au_mnt_get(sb); -+ path.dentry = sb->s_root; -+ p = d_path(&path, buf, len - strlen(p)); -+ mntput(path.mnt); -+ if (IS_ERR(p)) -+ goto out; -+ if (n != 1) -+ p[strlen(p)] = '/'; -+ -+out: -+ AuTraceErrPtr(p); -+ return p; -+} -+ -+static -+struct dentry *decode_by_path(struct super_block *sb, ino_t ino, __u32 *fh, -+ int fh_len, struct au_nfsd_si_lock *nsi_lock) -+{ -+ struct dentry *dentry, *h_parent, *root; -+ struct super_block *h_sb; -+ char *pathname, *p; -+ struct vfsmount *h_mnt; -+ struct au_branch *br; -+ int err; -+ struct path path; -+ -+ br = au_sbr(sb, nsi_lock->bindex); -+ h_mnt = au_br_mnt(br); -+ h_sb = h_mnt->mnt_sb; -+ /* todo: call lower fh_to_dentry()? fh_to_parent()? */ -+ lockdep_off(); -+ h_parent = exportfs_decode_fh(h_mnt, (void *)(fh + Fh_tail), -+ fh_len - Fh_tail, fh[Fh_h_type], -+ h_acceptable, /*context*/NULL); -+ lockdep_on(); -+ dentry = h_parent; -+ if (unlikely(!h_parent || IS_ERR(h_parent))) { -+ AuWarn1("%s decode_fh failed, %ld\n", -+ au_sbtype(h_sb), PTR_ERR(h_parent)); -+ goto out; -+ } -+ dentry = NULL; -+ if (unlikely(au_test_anon(h_parent))) { -+ AuWarn1("%s decode_fh returned a disconnected dentry\n", -+ au_sbtype(h_sb)); -+ goto out_h_parent; -+ } -+ -+ dentry = ERR_PTR(-ENOMEM); -+ pathname = (void *)__get_free_page(GFP_NOFS); -+ if (unlikely(!pathname)) -+ goto out_h_parent; -+ -+ root = sb->s_root; -+ path.mnt = h_mnt; -+ di_read_lock_parent(root, !AuLock_IR); -+ path.dentry = au_h_dptr(root, nsi_lock->bindex); -+ di_read_unlock(root, !AuLock_IR); -+ p = au_build_path(h_parent, &path, pathname, PAGE_SIZE, sb); -+ dentry = (void *)p; -+ if (IS_ERR(p)) -+ goto out_pathname; -+ -+ si_read_unlock(sb); -+ err = vfsub_kern_path(p, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path); -+ dentry = ERR_PTR(err); -+ if (unlikely(err)) -+ goto out_relock; -+ -+ dentry = ERR_PTR(-ENOENT); -+ AuDebugOn(au_test_anon(path.dentry)); -+ if (unlikely(d_really_is_negative(path.dentry))) -+ goto out_path; -+ -+ if (ino != d_inode(path.dentry)->i_ino) -+ dentry = au_lkup_by_ino(&path, ino, /*nsi_lock*/NULL); -+ else -+ dentry = dget(path.dentry); -+ -+out_path: -+ path_put(&path); -+out_relock: -+ if (unlikely(si_nfsd_read_lock(sb, nsi_lock) < 0)) -+ if (!IS_ERR(dentry)) { -+ dput(dentry); -+ dentry = ERR_PTR(-ESTALE); -+ } -+out_pathname: -+ free_page((unsigned long)pathname); -+out_h_parent: -+ dput(h_parent); -+out: -+ AuTraceErrPtr(dentry); -+ return dentry; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static struct dentry * -+aufs_fh_to_dentry(struct super_block *sb, struct fid *fid, int fh_len, -+ int fh_type) -+{ -+ struct dentry *dentry; -+ __u32 *fh = fid->raw; -+ struct au_branch *br; -+ ino_t ino, dir_ino; -+ struct au_nfsd_si_lock nsi_lock = { -+ .force_lock = 0 -+ }; -+ -+ dentry = ERR_PTR(-ESTALE); -+ /* it should never happen, but the file handle is unreliable */ -+ if (unlikely(fh_len < Fh_tail)) -+ goto out; -+ nsi_lock.sigen = fh[Fh_sigen]; -+ nsi_lock.br_id = fh[Fh_br_id]; -+ -+ /* branch id may be wrapped around */ -+ br = NULL; -+ if (unlikely(si_nfsd_read_lock(sb, &nsi_lock))) -+ goto out; -+ nsi_lock.force_lock = 1; -+ -+ /* is this inode still cached? */ -+ ino = decode_ino(fh + Fh_ino); -+ /* it should never happen */ -+ if (unlikely(ino == AUFS_ROOT_INO)) -+ goto out_unlock; -+ -+ dir_ino = decode_ino(fh + Fh_dir_ino); -+ dentry = decode_by_ino(sb, ino, dir_ino); -+ if (IS_ERR(dentry)) -+ goto out_unlock; -+ if (dentry) -+ goto accept; -+ -+ /* is the parent dir cached? */ -+ br = au_sbr(sb, nsi_lock.bindex); -+ au_lcnt_inc(&br->br_nfiles); -+ dentry = decode_by_dir_ino(sb, ino, dir_ino, &nsi_lock); -+ if (IS_ERR(dentry)) -+ goto out_unlock; -+ if (dentry) -+ goto accept; -+ -+ /* lookup path */ -+ dentry = decode_by_path(sb, ino, fh, fh_len, &nsi_lock); -+ if (IS_ERR(dentry)) -+ goto out_unlock; -+ if (unlikely(!dentry)) -+ /* todo?: make it ESTALE */ -+ goto out_unlock; -+ -+accept: -+ if (!au_digen_test(dentry, au_sigen(sb)) -+ && d_inode(dentry)->i_generation == fh[Fh_igen]) -+ goto out_unlock; /* success */ -+ -+ dput(dentry); -+ dentry = ERR_PTR(-ESTALE); -+out_unlock: -+ if (br) -+ au_lcnt_dec(&br->br_nfiles); -+ si_read_unlock(sb); -+out: -+ AuTraceErrPtr(dentry); -+ return dentry; -+} -+ -+#if 0 /* reserved for future use */ -+/* support subtreecheck option */ -+static struct dentry *aufs_fh_to_parent(struct super_block *sb, struct fid *fid, -+ int fh_len, int fh_type) -+{ -+ struct dentry *parent; -+ __u32 *fh = fid->raw; -+ ino_t dir_ino; -+ -+ dir_ino = decode_ino(fh + Fh_dir_ino); -+ parent = decode_by_ino(sb, dir_ino, 0); -+ if (IS_ERR(parent)) -+ goto out; -+ if (!parent) -+ parent = decode_by_path(sb, au_br_index(sb, fh[Fh_br_id]), -+ dir_ino, fh, fh_len); -+ -+out: -+ AuTraceErrPtr(parent); -+ return parent; -+} -+#endif -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int aufs_encode_fh(struct inode *inode, __u32 *fh, int *max_len, -+ struct inode *dir) -+{ -+ int err; -+ aufs_bindex_t bindex; -+ struct super_block *sb, *h_sb; -+ struct dentry *dentry, *parent, *h_parent; -+ struct inode *h_dir; -+ struct au_branch *br; -+ -+ err = -ENOSPC; -+ if (unlikely(*max_len <= Fh_tail)) { -+ AuWarn1("NFSv2 client (max_len %d)?\n", *max_len); -+ goto out; -+ } -+ -+ err = FILEID_ROOT; -+ if (inode->i_ino == AUFS_ROOT_INO) { -+ AuDebugOn(inode->i_ino != AUFS_ROOT_INO); -+ goto out; -+ } -+ -+ h_parent = NULL; -+ sb = inode->i_sb; -+ err = si_read_lock(sb, AuLock_FLUSH); -+ if (unlikely(err)) -+ goto out; -+ -+#ifdef CONFIG_AUFS_DEBUG -+ if (unlikely(!au_opt_test(au_mntflags(sb), XINO))) -+ AuWarn1("NFS-exporting requires xino\n"); -+#endif -+ err = -EIO; -+ parent = NULL; -+ ii_read_lock_child(inode); -+ bindex = au_ibtop(inode); -+ if (!dir) { -+ dentry = d_find_any_alias(inode); -+ if (unlikely(!dentry)) -+ goto out_unlock; -+ AuDebugOn(au_test_anon(dentry)); -+ parent = dget_parent(dentry); -+ dput(dentry); -+ if (unlikely(!parent)) -+ goto out_unlock; -+ if (d_really_is_positive(parent)) -+ dir = d_inode(parent); -+ } -+ -+ ii_read_lock_parent(dir); -+ h_dir = au_h_iptr(dir, bindex); -+ ii_read_unlock(dir); -+ if (unlikely(!h_dir)) -+ goto out_parent; -+ h_parent = d_find_any_alias(h_dir); -+ if (unlikely(!h_parent)) -+ goto out_hparent; -+ -+ err = -EPERM; -+ br = au_sbr(sb, bindex); -+ h_sb = au_br_sb(br); -+ if (unlikely(!h_sb->s_export_op)) { -+ AuErr1("%s branch is not exportable\n", au_sbtype(h_sb)); -+ goto out_hparent; -+ } -+ -+ fh[Fh_br_id] = br->br_id; -+ fh[Fh_sigen] = au_sigen(sb); -+ encode_ino(fh + Fh_ino, inode->i_ino); -+ encode_ino(fh + Fh_dir_ino, dir->i_ino); -+ fh[Fh_igen] = inode->i_generation; -+ -+ *max_len -= Fh_tail; -+ fh[Fh_h_type] = exportfs_encode_fh(h_parent, (void *)(fh + Fh_tail), -+ max_len, -+ /*connectable or subtreecheck*/0); -+ err = fh[Fh_h_type]; -+ *max_len += Fh_tail; -+ /* todo: macros? */ -+ if (err != FILEID_INVALID) -+ err = 99; -+ else -+ AuWarn1("%s encode_fh failed\n", au_sbtype(h_sb)); -+ -+out_hparent: -+ dput(h_parent); -+out_parent: -+ dput(parent); -+out_unlock: -+ ii_read_unlock(inode); -+ si_read_unlock(sb); -+out: -+ if (unlikely(err < 0)) -+ err = FILEID_INVALID; -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int aufs_commit_metadata(struct inode *inode) -+{ -+ int err; -+ aufs_bindex_t bindex; -+ struct super_block *sb; -+ struct inode *h_inode; -+ int (*f)(struct inode *inode); -+ -+ sb = inode->i_sb; -+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW); -+ ii_write_lock_child(inode); -+ bindex = au_ibtop(inode); -+ AuDebugOn(bindex < 0); -+ h_inode = au_h_iptr(inode, bindex); -+ -+ f = h_inode->i_sb->s_export_op->commit_metadata; -+ if (f) -+ err = f(h_inode); -+ else { -+ struct writeback_control wbc = { -+ .sync_mode = WB_SYNC_ALL, -+ .nr_to_write = 0 /* metadata only */ -+ }; -+ -+ err = sync_inode(h_inode, &wbc); -+ } -+ -+ au_cpup_attr_timesizes(inode); -+ ii_write_unlock(inode); -+ si_read_unlock(sb); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static struct export_operations aufs_export_op = { -+ .fh_to_dentry = aufs_fh_to_dentry, -+ /* .fh_to_parent = aufs_fh_to_parent, */ -+ .encode_fh = aufs_encode_fh, -+ .commit_metadata = aufs_commit_metadata -+}; -+ -+void au_export_init(struct super_block *sb) -+{ -+ struct au_sbinfo *sbinfo; -+ __u32 u; -+ -+ BUILD_BUG_ON_MSG(IS_BUILTIN(CONFIG_AUFS_FS) -+ && IS_MODULE(CONFIG_EXPORTFS), -+ AUFS_NAME ": unsupported configuration " -+ "CONFIG_EXPORTFS=m and CONFIG_AUFS_FS=y"); -+ -+ sb->s_export_op = &aufs_export_op; -+ sbinfo = au_sbi(sb); -+ sbinfo->si_xigen = NULL; -+ get_random_bytes(&u, sizeof(u)); -+ BUILD_BUG_ON(sizeof(u) != sizeof(int)); -+ atomic_set(&sbinfo->si_xigen_next, u); -+} -diff -Nurp linux-5.10-rc6/fs/aufs/fhsm.c linux-5.10-rc6.aufs/fs/aufs/fhsm.c ---- linux-5.10-rc6/fs/aufs/fhsm.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/fhsm.c 2020-12-02 21:19:51.881036743 +0200 -@@ -0,0 +1,413 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2011-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * File-based Hierarchy Storage Management -+ */ -+ -+#include -+#include -+#include -+#include -+#include "aufs.h" -+ -+static aufs_bindex_t au_fhsm_bottom(struct super_block *sb) -+{ -+ struct au_sbinfo *sbinfo; -+ struct au_fhsm *fhsm; -+ -+ SiMustAnyLock(sb); -+ -+ sbinfo = au_sbi(sb); -+ fhsm = &sbinfo->si_fhsm; -+ AuDebugOn(!fhsm); -+ return fhsm->fhsm_bottom; -+} -+ -+void au_fhsm_set_bottom(struct super_block *sb, aufs_bindex_t bindex) -+{ -+ struct au_sbinfo *sbinfo; -+ struct au_fhsm *fhsm; -+ -+ SiMustWriteLock(sb); -+ -+ sbinfo = au_sbi(sb); -+ fhsm = &sbinfo->si_fhsm; -+ AuDebugOn(!fhsm); -+ fhsm->fhsm_bottom = bindex; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int au_fhsm_test_jiffy(struct au_sbinfo *sbinfo, struct au_branch *br) -+{ -+ struct au_br_fhsm *bf; -+ -+ bf = br->br_fhsm; -+ MtxMustLock(&bf->bf_lock); -+ -+ return !bf->bf_readable -+ || time_after(jiffies, -+ bf->bf_jiffy + sbinfo->si_fhsm.fhsm_expire); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static void au_fhsm_notify(struct super_block *sb, int val) -+{ -+ struct au_sbinfo *sbinfo; -+ struct au_fhsm *fhsm; -+ -+ SiMustAnyLock(sb); -+ -+ sbinfo = au_sbi(sb); -+ fhsm = &sbinfo->si_fhsm; -+ if (au_fhsm_pid(fhsm) -+ && atomic_read(&fhsm->fhsm_readable) != -1) { -+ atomic_set(&fhsm->fhsm_readable, val); -+ if (val) -+ wake_up(&fhsm->fhsm_wqh); -+ } -+} -+ -+static int au_fhsm_stfs(struct super_block *sb, aufs_bindex_t bindex, -+ struct aufs_stfs *rstfs, int do_lock, int do_notify) -+{ -+ int err; -+ struct au_branch *br; -+ struct au_br_fhsm *bf; -+ -+ br = au_sbr(sb, bindex); -+ AuDebugOn(au_br_rdonly(br)); -+ bf = br->br_fhsm; -+ AuDebugOn(!bf); -+ -+ if (do_lock) -+ mutex_lock(&bf->bf_lock); -+ else -+ MtxMustLock(&bf->bf_lock); -+ -+ /* sb->s_root for NFS is unreliable */ -+ err = au_br_stfs(br, &bf->bf_stfs); -+ if (unlikely(err)) { -+ AuErr1("FHSM failed (%d), b%d, ignored.\n", bindex, err); -+ goto out; -+ } -+ -+ bf->bf_jiffy = jiffies; -+ bf->bf_readable = 1; -+ if (do_notify) -+ au_fhsm_notify(sb, /*val*/1); -+ if (rstfs) -+ *rstfs = bf->bf_stfs; -+ -+out: -+ if (do_lock) -+ mutex_unlock(&bf->bf_lock); -+ au_fhsm_notify(sb, /*val*/1); -+ -+ return err; -+} -+ -+void au_fhsm_wrote(struct super_block *sb, aufs_bindex_t bindex, int force) -+{ -+ int err; -+ struct au_sbinfo *sbinfo; -+ struct au_fhsm *fhsm; -+ struct au_branch *br; -+ struct au_br_fhsm *bf; -+ -+ AuDbg("b%d, force %d\n", bindex, force); -+ SiMustAnyLock(sb); -+ -+ sbinfo = au_sbi(sb); -+ fhsm = &sbinfo->si_fhsm; -+ if (!au_ftest_si(sbinfo, FHSM) -+ || fhsm->fhsm_bottom == bindex) -+ return; -+ -+ br = au_sbr(sb, bindex); -+ bf = br->br_fhsm; -+ AuDebugOn(!bf); -+ mutex_lock(&bf->bf_lock); -+ if (force -+ || au_fhsm_pid(fhsm) -+ || au_fhsm_test_jiffy(sbinfo, br)) -+ err = au_fhsm_stfs(sb, bindex, /*rstfs*/NULL, /*do_lock*/0, -+ /*do_notify*/1); -+ mutex_unlock(&bf->bf_lock); -+} -+ -+void au_fhsm_wrote_all(struct super_block *sb, int force) -+{ -+ aufs_bindex_t bindex, bbot; -+ struct au_branch *br; -+ -+ /* exclude the bottom */ -+ bbot = au_fhsm_bottom(sb); -+ for (bindex = 0; bindex < bbot; bindex++) { -+ br = au_sbr(sb, bindex); -+ if (au_br_fhsm(br->br_perm)) -+ au_fhsm_wrote(sb, bindex, force); -+ } -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static __poll_t au_fhsm_poll(struct file *file, struct poll_table_struct *wait) -+{ -+ __poll_t mask; -+ struct au_sbinfo *sbinfo; -+ struct au_fhsm *fhsm; -+ -+ mask = 0; -+ sbinfo = file->private_data; -+ fhsm = &sbinfo->si_fhsm; -+ poll_wait(file, &fhsm->fhsm_wqh, wait); -+ if (atomic_read(&fhsm->fhsm_readable)) -+ mask = EPOLLIN /* | EPOLLRDNORM */; -+ -+ if (!mask) -+ AuDbg("mask 0x%x\n", mask); -+ return mask; -+} -+ -+static int au_fhsm_do_read_one(struct aufs_stbr __user *stbr, -+ struct aufs_stfs *stfs, __s16 brid) -+{ -+ int err; -+ -+ err = copy_to_user(&stbr->stfs, stfs, sizeof(*stfs)); -+ if (!err) -+ err = __put_user(brid, &stbr->brid); -+ if (unlikely(err)) -+ err = -EFAULT; -+ -+ return err; -+} -+ -+static ssize_t au_fhsm_do_read(struct super_block *sb, -+ struct aufs_stbr __user *stbr, size_t count) -+{ -+ ssize_t err; -+ int nstbr; -+ aufs_bindex_t bindex, bbot; -+ struct au_branch *br; -+ struct au_br_fhsm *bf; -+ -+ /* except the bottom branch */ -+ err = 0; -+ nstbr = 0; -+ bbot = au_fhsm_bottom(sb); -+ for (bindex = 0; !err && bindex < bbot; bindex++) { -+ br = au_sbr(sb, bindex); -+ if (!au_br_fhsm(br->br_perm)) -+ continue; -+ -+ bf = br->br_fhsm; -+ mutex_lock(&bf->bf_lock); -+ if (bf->bf_readable) { -+ err = -EFAULT; -+ if (count >= sizeof(*stbr)) -+ err = au_fhsm_do_read_one(stbr++, &bf->bf_stfs, -+ br->br_id); -+ if (!err) { -+ bf->bf_readable = 0; -+ count -= sizeof(*stbr); -+ nstbr++; -+ } -+ } -+ mutex_unlock(&bf->bf_lock); -+ } -+ if (!err) -+ err = sizeof(*stbr) * nstbr; -+ -+ return err; -+} -+ -+static ssize_t au_fhsm_read(struct file *file, char __user *buf, size_t count, -+ loff_t *pos) -+{ -+ ssize_t err; -+ int readable; -+ aufs_bindex_t nfhsm, bindex, bbot; -+ struct au_sbinfo *sbinfo; -+ struct au_fhsm *fhsm; -+ struct au_branch *br; -+ struct super_block *sb; -+ -+ err = 0; -+ sbinfo = file->private_data; -+ fhsm = &sbinfo->si_fhsm; -+need_data: -+ spin_lock_irq(&fhsm->fhsm_wqh.lock); -+ if (!atomic_read(&fhsm->fhsm_readable)) { -+ if (vfsub_file_flags(file) & O_NONBLOCK) -+ err = -EAGAIN; -+ else -+ err = wait_event_interruptible_locked_irq -+ (fhsm->fhsm_wqh, -+ atomic_read(&fhsm->fhsm_readable)); -+ } -+ spin_unlock_irq(&fhsm->fhsm_wqh.lock); -+ if (unlikely(err)) -+ goto out; -+ -+ /* sb may already be dead */ -+ au_rw_read_lock(&sbinfo->si_rwsem); -+ readable = atomic_read(&fhsm->fhsm_readable); -+ if (readable > 0) { -+ sb = sbinfo->si_sb; -+ AuDebugOn(!sb); -+ /* exclude the bottom branch */ -+ nfhsm = 0; -+ bbot = au_fhsm_bottom(sb); -+ for (bindex = 0; bindex < bbot; bindex++) { -+ br = au_sbr(sb, bindex); -+ if (au_br_fhsm(br->br_perm)) -+ nfhsm++; -+ } -+ err = -EMSGSIZE; -+ if (nfhsm * sizeof(struct aufs_stbr) <= count) { -+ atomic_set(&fhsm->fhsm_readable, 0); -+ err = au_fhsm_do_read(sbinfo->si_sb, (void __user *)buf, -+ count); -+ } -+ } -+ au_rw_read_unlock(&sbinfo->si_rwsem); -+ if (!readable) -+ goto need_data; -+ -+out: -+ return err; -+} -+ -+static int au_fhsm_release(struct inode *inode, struct file *file) -+{ -+ struct au_sbinfo *sbinfo; -+ struct au_fhsm *fhsm; -+ -+ /* sb may already be dead */ -+ sbinfo = file->private_data; -+ fhsm = &sbinfo->si_fhsm; -+ spin_lock(&fhsm->fhsm_spin); -+ fhsm->fhsm_pid = 0; -+ spin_unlock(&fhsm->fhsm_spin); -+ kobject_put(&sbinfo->si_kobj); -+ -+ return 0; -+} -+ -+static const struct file_operations au_fhsm_fops = { -+ .owner = THIS_MODULE, -+ .llseek = noop_llseek, -+ .read = au_fhsm_read, -+ .poll = au_fhsm_poll, -+ .release = au_fhsm_release -+}; -+ -+int au_fhsm_fd(struct super_block *sb, int oflags) -+{ -+ int err, fd; -+ struct au_sbinfo *sbinfo; -+ struct au_fhsm *fhsm; -+ -+ err = -EPERM; -+ if (unlikely(!capable(CAP_SYS_ADMIN))) -+ goto out; -+ -+ err = -EINVAL; -+ if (unlikely(oflags & ~(O_CLOEXEC | O_NONBLOCK))) -+ goto out; -+ -+ err = 0; -+ sbinfo = au_sbi(sb); -+ fhsm = &sbinfo->si_fhsm; -+ spin_lock(&fhsm->fhsm_spin); -+ if (!fhsm->fhsm_pid) -+ fhsm->fhsm_pid = current->pid; -+ else -+ err = -EBUSY; -+ spin_unlock(&fhsm->fhsm_spin); -+ if (unlikely(err)) -+ goto out; -+ -+ oflags |= O_RDONLY; -+ /* oflags |= FMODE_NONOTIFY; */ -+ fd = anon_inode_getfd("[aufs_fhsm]", &au_fhsm_fops, sbinfo, oflags); -+ err = fd; -+ if (unlikely(fd < 0)) -+ goto out_pid; -+ -+ /* succeed regardless 'fhsm' status */ -+ kobject_get(&sbinfo->si_kobj); -+ si_noflush_read_lock(sb); -+ if (au_ftest_si(sbinfo, FHSM)) -+ au_fhsm_wrote_all(sb, /*force*/0); -+ si_read_unlock(sb); -+ goto out; /* success */ -+ -+out_pid: -+ spin_lock(&fhsm->fhsm_spin); -+ fhsm->fhsm_pid = 0; -+ spin_unlock(&fhsm->fhsm_spin); -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+int au_fhsm_br_alloc(struct au_branch *br) -+{ -+ int err; -+ -+ err = 0; -+ br->br_fhsm = kmalloc(sizeof(*br->br_fhsm), GFP_NOFS); -+ if (br->br_fhsm) -+ au_br_fhsm_init(br->br_fhsm); -+ else -+ err = -ENOMEM; -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+void au_fhsm_fin(struct super_block *sb) -+{ -+ au_fhsm_notify(sb, /*val*/-1); -+} -+ -+void au_fhsm_init(struct au_sbinfo *sbinfo) -+{ -+ struct au_fhsm *fhsm; -+ -+ fhsm = &sbinfo->si_fhsm; -+ spin_lock_init(&fhsm->fhsm_spin); -+ init_waitqueue_head(&fhsm->fhsm_wqh); -+ atomic_set(&fhsm->fhsm_readable, 0); -+ fhsm->fhsm_expire -+ = msecs_to_jiffies(AUFS_FHSM_CACHE_DEF_SEC * MSEC_PER_SEC); -+ fhsm->fhsm_bottom = -1; -+} -+ -+void au_fhsm_set(struct au_sbinfo *sbinfo, unsigned int sec) -+{ -+ sbinfo->si_fhsm.fhsm_expire -+ = msecs_to_jiffies(sec * MSEC_PER_SEC); -+} -+ -+void au_fhsm_show(struct seq_file *seq, struct au_sbinfo *sbinfo) -+{ -+ unsigned int u; -+ -+ if (!au_ftest_si(sbinfo, FHSM)) -+ return; -+ -+ u = jiffies_to_msecs(sbinfo->si_fhsm.fhsm_expire) / MSEC_PER_SEC; -+ if (u != AUFS_FHSM_CACHE_DEF_SEC) -+ seq_printf(seq, ",fhsm_sec=%u", u); -+} -diff -Nurp linux-5.10-rc6/fs/aufs/file.c linux-5.10-rc6.aufs/fs/aufs/file.c ---- linux-5.10-rc6/fs/aufs/file.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/file.c 2020-12-02 21:19:51.881036743 +0200 -@@ -0,0 +1,850 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * handling file/dir, and address_space operation -+ */ -+ -+#ifdef CONFIG_AUFS_DEBUG -+#include -+#endif -+#include -+#include "aufs.h" -+ -+/* drop flags for writing */ -+unsigned int au_file_roflags(unsigned int flags) -+{ -+ flags &= ~(O_WRONLY | O_RDWR | O_APPEND | O_CREAT | O_TRUNC); -+ flags |= O_RDONLY | O_NOATIME; -+ return flags; -+} -+ -+/* common functions to regular file and dir */ -+struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags, -+ struct file *file, int force_wr) -+{ -+ struct file *h_file; -+ struct dentry *h_dentry; -+ struct inode *h_inode; -+ struct super_block *sb; -+ struct au_branch *br; -+ struct path h_path; -+ int err; -+ -+ /* a race condition can happen between open and unlink/rmdir */ -+ h_file = ERR_PTR(-ENOENT); -+ h_dentry = au_h_dptr(dentry, bindex); -+ if (au_test_nfsd() && (!h_dentry || d_is_negative(h_dentry))) -+ goto out; -+ h_inode = d_inode(h_dentry); -+ spin_lock(&h_dentry->d_lock); -+ err = (!d_unhashed(dentry) && d_unlinked(h_dentry)) -+ /* || !d_inode(dentry)->i_nlink */ -+ ; -+ spin_unlock(&h_dentry->d_lock); -+ if (unlikely(err)) -+ goto out; -+ -+ sb = dentry->d_sb; -+ br = au_sbr(sb, bindex); -+ err = au_br_test_oflag(flags, br); -+ h_file = ERR_PTR(err); -+ if (unlikely(err)) -+ goto out; -+ -+ /* drop flags for writing */ -+ if (au_test_ro(sb, bindex, d_inode(dentry))) { -+ if (force_wr && !(flags & O_WRONLY)) -+ force_wr = 0; -+ flags = au_file_roflags(flags); -+ if (force_wr) { -+ h_file = ERR_PTR(-EROFS); -+ flags = au_file_roflags(flags); -+ if (unlikely(vfsub_native_ro(h_inode) -+ || IS_APPEND(h_inode))) -+ goto out; -+ flags &= ~O_ACCMODE; -+ flags |= O_WRONLY; -+ } -+ } -+ flags &= ~O_CREAT; -+ au_lcnt_inc(&br->br_nfiles); -+ h_path.dentry = h_dentry; -+ h_path.mnt = au_br_mnt(br); -+ h_file = vfsub_dentry_open(&h_path, flags); -+ if (IS_ERR(h_file)) -+ goto out_br; -+ -+ if (flags & __FMODE_EXEC) { -+ err = deny_write_access(h_file); -+ if (unlikely(err)) { -+ fput(h_file); -+ h_file = ERR_PTR(err); -+ goto out_br; -+ } -+ } -+ fsnotify_open(h_file); -+ goto out; /* success */ -+ -+out_br: -+ au_lcnt_dec(&br->br_nfiles); -+out: -+ return h_file; -+} -+ -+static int au_cmoo(struct dentry *dentry) -+{ -+ int err, cmoo, matched; -+ unsigned int udba; -+ struct path h_path; -+ struct au_pin pin; -+ struct au_cp_generic cpg = { -+ .dentry = dentry, -+ .bdst = -1, -+ .bsrc = -1, -+ .len = -1, -+ .pin = &pin, -+ .flags = AuCpup_DTIME | AuCpup_HOPEN -+ }; -+ struct inode *delegated; -+ struct super_block *sb; -+ struct au_sbinfo *sbinfo; -+ struct au_fhsm *fhsm; -+ pid_t pid; -+ struct au_branch *br; -+ struct dentry *parent; -+ struct au_hinode *hdir; -+ -+ DiMustWriteLock(dentry); -+ IiMustWriteLock(d_inode(dentry)); -+ -+ err = 0; -+ if (IS_ROOT(dentry)) -+ goto out; -+ cpg.bsrc = au_dbtop(dentry); -+ if (!cpg.bsrc) -+ goto out; -+ -+ sb = dentry->d_sb; -+ sbinfo = au_sbi(sb); -+ fhsm = &sbinfo->si_fhsm; -+ pid = au_fhsm_pid(fhsm); -+ rcu_read_lock(); -+ matched = (pid -+ && (current->pid == pid -+ || rcu_dereference(current->real_parent)->pid == pid)); -+ rcu_read_unlock(); -+ if (matched) -+ goto out; -+ -+ br = au_sbr(sb, cpg.bsrc); -+ cmoo = au_br_cmoo(br->br_perm); -+ if (!cmoo) -+ goto out; -+ if (!d_is_reg(dentry)) -+ cmoo &= AuBrAttr_COO_ALL; -+ if (!cmoo) -+ goto out; -+ -+ parent = dget_parent(dentry); -+ di_write_lock_parent(parent); -+ err = au_wbr_do_copyup_bu(dentry, cpg.bsrc - 1); -+ cpg.bdst = err; -+ if (unlikely(err < 0)) { -+ err = 0; /* there is no upper writable branch */ -+ goto out_dgrade; -+ } -+ AuDbg("bsrc %d, bdst %d\n", cpg.bsrc, cpg.bdst); -+ -+ /* do not respect the coo attrib for the target branch */ -+ err = au_cpup_dirs(dentry, cpg.bdst); -+ if (unlikely(err)) -+ goto out_dgrade; -+ -+ di_downgrade_lock(parent, AuLock_IR); -+ udba = au_opt_udba(sb); -+ err = au_pin(&pin, dentry, cpg.bdst, udba, -+ AuPin_DI_LOCKED | AuPin_MNT_WRITE); -+ if (unlikely(err)) -+ goto out_parent; -+ -+ err = au_sio_cpup_simple(&cpg); -+ au_unpin(&pin); -+ if (unlikely(err)) -+ goto out_parent; -+ if (!(cmoo & AuBrWAttr_MOO)) -+ goto out_parent; /* success */ -+ -+ err = au_pin(&pin, dentry, cpg.bsrc, udba, -+ AuPin_DI_LOCKED | AuPin_MNT_WRITE); -+ if (unlikely(err)) -+ goto out_parent; -+ -+ h_path.mnt = au_br_mnt(br); -+ h_path.dentry = au_h_dptr(dentry, cpg.bsrc); -+ hdir = au_hi(d_inode(parent), cpg.bsrc); -+ delegated = NULL; -+ err = vfsub_unlink(hdir->hi_inode, &h_path, &delegated, /*force*/1); -+ au_unpin(&pin); -+ /* todo: keep h_dentry or not? */ -+ if (unlikely(err == -EWOULDBLOCK)) { -+ pr_warn("cannot retry for NFSv4 delegation" -+ " for an internal unlink\n"); -+ iput(delegated); -+ } -+ if (unlikely(err)) { -+ pr_err("unlink %pd after coo failed (%d), ignored\n", -+ dentry, err); -+ err = 0; -+ } -+ goto out_parent; /* success */ -+ -+out_dgrade: -+ di_downgrade_lock(parent, AuLock_IR); -+out_parent: -+ di_read_unlock(parent, AuLock_IR); -+ dput(parent); -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+int au_do_open(struct file *file, struct au_do_open_args *args) -+{ -+ int err, aopen = args->aopen; -+ struct dentry *dentry; -+ struct au_finfo *finfo; -+ -+ if (!aopen) -+ err = au_finfo_init(file, args->fidir); -+ else { -+ lockdep_off(); -+ err = au_finfo_init(file, args->fidir); -+ lockdep_on(); -+ } -+ if (unlikely(err)) -+ goto out; -+ -+ dentry = file->f_path.dentry; -+ AuDebugOn(IS_ERR_OR_NULL(dentry)); -+ di_write_lock_child(dentry); -+ err = au_cmoo(dentry); -+ di_downgrade_lock(dentry, AuLock_IR); -+ if (!err) { -+ if (!aopen) -+ err = args->open(file, vfsub_file_flags(file), NULL); -+ else { -+ lockdep_off(); -+ err = args->open(file, vfsub_file_flags(file), -+ args->h_file); -+ lockdep_on(); -+ } -+ } -+ di_read_unlock(dentry, AuLock_IR); -+ -+ finfo = au_fi(file); -+ if (!err) { -+ finfo->fi_file = file; -+ au_hbl_add(&finfo->fi_hlist, -+ &au_sbi(file->f_path.dentry->d_sb)->si_files); -+ } -+ if (!aopen) -+ fi_write_unlock(file); -+ else { -+ lockdep_off(); -+ fi_write_unlock(file); -+ lockdep_on(); -+ } -+ if (unlikely(err)) { -+ finfo->fi_hdir = NULL; -+ au_finfo_fin(file); -+ } -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+int au_reopen_nondir(struct file *file) -+{ -+ int err; -+ aufs_bindex_t btop; -+ struct dentry *dentry; -+ struct au_branch *br; -+ struct file *h_file, *h_file_tmp; -+ -+ dentry = file->f_path.dentry; -+ btop = au_dbtop(dentry); -+ br = au_sbr(dentry->d_sb, btop); -+ h_file_tmp = NULL; -+ if (au_fbtop(file) == btop) { -+ h_file = au_hf_top(file); -+ if (file->f_mode == h_file->f_mode) -+ return 0; /* success */ -+ h_file_tmp = h_file; -+ get_file(h_file_tmp); -+ au_lcnt_inc(&br->br_nfiles); -+ au_set_h_fptr(file, btop, NULL); -+ } -+ AuDebugOn(au_fi(file)->fi_hdir); -+ /* -+ * it can happen -+ * file exists on both of rw and ro -+ * open --> dbtop and fbtop are both 0 -+ * prepend a branch as rw, "rw" become ro -+ * remove rw/file -+ * delete the top branch, "rw" becomes rw again -+ * --> dbtop is 1, fbtop is still 0 -+ * write --> fbtop is 0 but dbtop is 1 -+ */ -+ /* AuDebugOn(au_fbtop(file) < btop); */ -+ -+ h_file = au_h_open(dentry, btop, vfsub_file_flags(file) & ~O_TRUNC, -+ file, /*force_wr*/0); -+ err = PTR_ERR(h_file); -+ if (IS_ERR(h_file)) { -+ if (h_file_tmp) { -+ /* revert */ -+ au_set_h_fptr(file, btop, h_file_tmp); -+ h_file_tmp = NULL; -+ } -+ goto out; /* todo: close all? */ -+ } -+ -+ err = 0; -+ au_set_fbtop(file, btop); -+ au_set_h_fptr(file, btop, h_file); -+ au_update_figen(file); -+ /* todo: necessary? */ -+ /* file->f_ra = h_file->f_ra; */ -+ -+out: -+ if (h_file_tmp) { -+ fput(h_file_tmp); -+ au_lcnt_dec(&br->br_nfiles); -+ } -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int au_reopen_wh(struct file *file, aufs_bindex_t btgt, -+ struct dentry *hi_wh) -+{ -+ int err; -+ aufs_bindex_t btop; -+ struct au_dinfo *dinfo; -+ struct dentry *h_dentry; -+ struct au_hdentry *hdp; -+ -+ dinfo = au_di(file->f_path.dentry); -+ AuRwMustWriteLock(&dinfo->di_rwsem); -+ -+ btop = dinfo->di_btop; -+ dinfo->di_btop = btgt; -+ hdp = au_hdentry(dinfo, btgt); -+ h_dentry = hdp->hd_dentry; -+ hdp->hd_dentry = hi_wh; -+ err = au_reopen_nondir(file); -+ hdp->hd_dentry = h_dentry; -+ dinfo->di_btop = btop; -+ -+ return err; -+} -+ -+static int au_ready_to_write_wh(struct file *file, loff_t len, -+ aufs_bindex_t bcpup, struct au_pin *pin) -+{ -+ int err; -+ struct inode *inode, *h_inode; -+ struct dentry *h_dentry, *hi_wh; -+ struct au_cp_generic cpg = { -+ .dentry = file->f_path.dentry, -+ .bdst = bcpup, -+ .bsrc = -1, -+ .len = len, -+ .pin = pin -+ }; -+ -+ au_update_dbtop(cpg.dentry); -+ inode = d_inode(cpg.dentry); -+ h_inode = NULL; -+ if (au_dbtop(cpg.dentry) <= bcpup -+ && au_dbbot(cpg.dentry) >= bcpup) { -+ h_dentry = au_h_dptr(cpg.dentry, bcpup); -+ if (h_dentry && d_is_positive(h_dentry)) -+ h_inode = d_inode(h_dentry); -+ } -+ hi_wh = au_hi_wh(inode, bcpup); -+ if (!hi_wh && !h_inode) -+ err = au_sio_cpup_wh(&cpg, file); -+ else -+ /* already copied-up after unlink */ -+ err = au_reopen_wh(file, bcpup, hi_wh); -+ -+ if (!err -+ && (inode->i_nlink > 1 -+ || (inode->i_state & I_LINKABLE)) -+ && au_opt_test(au_mntflags(cpg.dentry->d_sb), PLINK)) -+ au_plink_append(inode, bcpup, au_h_dptr(cpg.dentry, bcpup)); -+ -+ return err; -+} -+ -+/* -+ * prepare the @file for writing. -+ */ -+int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin) -+{ -+ int err; -+ aufs_bindex_t dbtop; -+ struct dentry *parent; -+ struct inode *inode; -+ struct super_block *sb; -+ struct file *h_file; -+ struct au_cp_generic cpg = { -+ .dentry = file->f_path.dentry, -+ .bdst = -1, -+ .bsrc = -1, -+ .len = len, -+ .pin = pin, -+ .flags = AuCpup_DTIME -+ }; -+ -+ sb = cpg.dentry->d_sb; -+ inode = d_inode(cpg.dentry); -+ cpg.bsrc = au_fbtop(file); -+ err = au_test_ro(sb, cpg.bsrc, inode); -+ if (!err && (au_hf_top(file)->f_mode & FMODE_WRITE)) { -+ err = au_pin(pin, cpg.dentry, cpg.bsrc, AuOpt_UDBA_NONE, -+ /*flags*/0); -+ goto out; -+ } -+ -+ /* need to cpup or reopen */ -+ parent = dget_parent(cpg.dentry); -+ di_write_lock_parent(parent); -+ err = AuWbrCopyup(au_sbi(sb), cpg.dentry); -+ cpg.bdst = err; -+ if (unlikely(err < 0)) -+ goto out_dgrade; -+ err = 0; -+ -+ if (!d_unhashed(cpg.dentry) && !au_h_dptr(parent, cpg.bdst)) { -+ err = au_cpup_dirs(cpg.dentry, cpg.bdst); -+ if (unlikely(err)) -+ goto out_dgrade; -+ } -+ -+ err = au_pin(pin, cpg.dentry, cpg.bdst, AuOpt_UDBA_NONE, -+ AuPin_DI_LOCKED | AuPin_MNT_WRITE); -+ if (unlikely(err)) -+ goto out_dgrade; -+ -+ dbtop = au_dbtop(cpg.dentry); -+ if (dbtop <= cpg.bdst) -+ cpg.bsrc = cpg.bdst; -+ -+ if (dbtop <= cpg.bdst /* just reopen */ -+ || !d_unhashed(cpg.dentry) /* copyup and reopen */ -+ ) { -+ h_file = au_h_open_pre(cpg.dentry, cpg.bsrc, /*force_wr*/0); -+ if (IS_ERR(h_file)) -+ err = PTR_ERR(h_file); -+ else { -+ di_downgrade_lock(parent, AuLock_IR); -+ if (dbtop > cpg.bdst) -+ err = au_sio_cpup_simple(&cpg); -+ if (!err) -+ err = au_reopen_nondir(file); -+ au_h_open_post(cpg.dentry, cpg.bsrc, h_file); -+ } -+ } else { /* copyup as wh and reopen */ -+ /* -+ * since writable hfsplus branch is not supported, -+ * h_open_pre/post() are unnecessary. -+ */ -+ err = au_ready_to_write_wh(file, len, cpg.bdst, pin); -+ di_downgrade_lock(parent, AuLock_IR); -+ } -+ -+ if (!err) { -+ au_pin_set_parent_lflag(pin, /*lflag*/0); -+ goto out_dput; /* success */ -+ } -+ au_unpin(pin); -+ goto out_unlock; -+ -+out_dgrade: -+ di_downgrade_lock(parent, AuLock_IR); -+out_unlock: -+ di_read_unlock(parent, AuLock_IR); -+out_dput: -+ dput(parent); -+out: -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+int au_do_flush(struct file *file, fl_owner_t id, -+ int (*flush)(struct file *file, fl_owner_t id)) -+{ -+ int err; -+ struct super_block *sb; -+ struct inode *inode; -+ -+ inode = file_inode(file); -+ sb = inode->i_sb; -+ si_noflush_read_lock(sb); -+ fi_read_lock(file); -+ ii_read_lock_child(inode); -+ -+ err = flush(file, id); -+ au_cpup_attr_timesizes(inode); -+ -+ ii_read_unlock(inode); -+ fi_read_unlock(file); -+ si_read_unlock(sb); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int au_file_refresh_by_inode(struct file *file, int *need_reopen) -+{ -+ int err; -+ struct au_pin pin; -+ struct au_finfo *finfo; -+ struct dentry *parent, *hi_wh; -+ struct inode *inode; -+ struct super_block *sb; -+ struct au_cp_generic cpg = { -+ .dentry = file->f_path.dentry, -+ .bdst = -1, -+ .bsrc = -1, -+ .len = -1, -+ .pin = &pin, -+ .flags = AuCpup_DTIME -+ }; -+ -+ FiMustWriteLock(file); -+ -+ err = 0; -+ finfo = au_fi(file); -+ sb = cpg.dentry->d_sb; -+ inode = d_inode(cpg.dentry); -+ cpg.bdst = au_ibtop(inode); -+ if (cpg.bdst == finfo->fi_btop || IS_ROOT(cpg.dentry)) -+ goto out; -+ -+ parent = dget_parent(cpg.dentry); -+ if (au_test_ro(sb, cpg.bdst, inode)) { -+ di_read_lock_parent(parent, !AuLock_IR); -+ err = AuWbrCopyup(au_sbi(sb), cpg.dentry); -+ cpg.bdst = err; -+ di_read_unlock(parent, !AuLock_IR); -+ if (unlikely(err < 0)) -+ goto out_parent; -+ err = 0; -+ } -+ -+ di_read_lock_parent(parent, AuLock_IR); -+ hi_wh = au_hi_wh(inode, cpg.bdst); -+ if (!S_ISDIR(inode->i_mode) -+ && au_opt_test(au_mntflags(sb), PLINK) -+ && au_plink_test(inode) -+ && !d_unhashed(cpg.dentry) -+ && cpg.bdst < au_dbtop(cpg.dentry)) { -+ err = au_test_and_cpup_dirs(cpg.dentry, cpg.bdst); -+ if (unlikely(err)) -+ goto out_unlock; -+ -+ /* always superio. */ -+ err = au_pin(&pin, cpg.dentry, cpg.bdst, AuOpt_UDBA_NONE, -+ AuPin_DI_LOCKED | AuPin_MNT_WRITE); -+ if (!err) { -+ err = au_sio_cpup_simple(&cpg); -+ au_unpin(&pin); -+ } -+ } else if (hi_wh) { -+ /* already copied-up after unlink */ -+ err = au_reopen_wh(file, cpg.bdst, hi_wh); -+ *need_reopen = 0; -+ } -+ -+out_unlock: -+ di_read_unlock(parent, AuLock_IR); -+out_parent: -+ dput(parent); -+out: -+ return err; -+} -+ -+static void au_do_refresh_dir(struct file *file) -+{ -+ aufs_bindex_t bindex, bbot, new_bindex, brid; -+ struct au_hfile *p, tmp, *q; -+ struct au_finfo *finfo; -+ struct super_block *sb; -+ struct au_fidir *fidir; -+ -+ FiMustWriteLock(file); -+ -+ sb = file->f_path.dentry->d_sb; -+ finfo = au_fi(file); -+ fidir = finfo->fi_hdir; -+ AuDebugOn(!fidir); -+ p = fidir->fd_hfile + finfo->fi_btop; -+ brid = p->hf_br->br_id; -+ bbot = fidir->fd_bbot; -+ for (bindex = finfo->fi_btop; bindex <= bbot; bindex++, p++) { -+ if (!p->hf_file) -+ continue; -+ -+ new_bindex = au_br_index(sb, p->hf_br->br_id); -+ if (new_bindex == bindex) -+ continue; -+ if (new_bindex < 0) { -+ au_set_h_fptr(file, bindex, NULL); -+ continue; -+ } -+ -+ /* swap two lower inode, and loop again */ -+ q = fidir->fd_hfile + new_bindex; -+ tmp = *q; -+ *q = *p; -+ *p = tmp; -+ if (tmp.hf_file) { -+ bindex--; -+ p--; -+ } -+ } -+ -+ p = fidir->fd_hfile; -+ if (!au_test_mmapped(file) && !d_unlinked(file->f_path.dentry)) { -+ bbot = au_sbbot(sb); -+ for (finfo->fi_btop = 0; finfo->fi_btop <= bbot; -+ finfo->fi_btop++, p++) -+ if (p->hf_file) { -+ if (file_inode(p->hf_file)) -+ break; -+ au_hfput(p, /*execed*/0); -+ } -+ } else { -+ bbot = au_br_index(sb, brid); -+ for (finfo->fi_btop = 0; finfo->fi_btop < bbot; -+ finfo->fi_btop++, p++) -+ if (p->hf_file) -+ au_hfput(p, /*execed*/0); -+ bbot = au_sbbot(sb); -+ } -+ -+ p = fidir->fd_hfile + bbot; -+ for (fidir->fd_bbot = bbot; fidir->fd_bbot >= finfo->fi_btop; -+ fidir->fd_bbot--, p--) -+ if (p->hf_file) { -+ if (file_inode(p->hf_file)) -+ break; -+ au_hfput(p, /*execed*/0); -+ } -+ AuDebugOn(fidir->fd_bbot < finfo->fi_btop); -+} -+ -+/* -+ * after branch manipulating, refresh the file. -+ */ -+static int refresh_file(struct file *file, int (*reopen)(struct file *file)) -+{ -+ int err, need_reopen, nbr; -+ aufs_bindex_t bbot, bindex; -+ struct dentry *dentry; -+ struct super_block *sb; -+ struct au_finfo *finfo; -+ struct au_hfile *hfile; -+ -+ dentry = file->f_path.dentry; -+ sb = dentry->d_sb; -+ nbr = au_sbbot(sb) + 1; -+ finfo = au_fi(file); -+ if (!finfo->fi_hdir) { -+ hfile = &finfo->fi_htop; -+ AuDebugOn(!hfile->hf_file); -+ bindex = au_br_index(sb, hfile->hf_br->br_id); -+ AuDebugOn(bindex < 0); -+ if (bindex != finfo->fi_btop) -+ au_set_fbtop(file, bindex); -+ } else { -+ err = au_fidir_realloc(finfo, nbr, /*may_shrink*/0); -+ if (unlikely(err)) -+ goto out; -+ au_do_refresh_dir(file); -+ } -+ -+ err = 0; -+ need_reopen = 1; -+ if (!au_test_mmapped(file)) -+ err = au_file_refresh_by_inode(file, &need_reopen); -+ if (finfo->fi_hdir) -+ /* harmless if err */ -+ au_fidir_realloc(finfo, nbr, /*may_shrink*/1); -+ if (!err && need_reopen && !d_unlinked(dentry)) -+ err = reopen(file); -+ if (!err) { -+ au_update_figen(file); -+ goto out; /* success */ -+ } -+ -+ /* error, close all lower files */ -+ if (finfo->fi_hdir) { -+ bbot = au_fbbot_dir(file); -+ for (bindex = au_fbtop(file); bindex <= bbot; bindex++) -+ au_set_h_fptr(file, bindex, NULL); -+ } -+ -+out: -+ return err; -+} -+ -+/* common function to regular file and dir */ -+int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file), -+ int wlock, unsigned int fi_lsc) -+{ -+ int err; -+ unsigned int sigen, figen; -+ aufs_bindex_t btop; -+ unsigned char pseudo_link; -+ struct dentry *dentry; -+ struct inode *inode; -+ -+ err = 0; -+ dentry = file->f_path.dentry; -+ inode = d_inode(dentry); -+ sigen = au_sigen(dentry->d_sb); -+ fi_write_lock_nested(file, fi_lsc); -+ figen = au_figen(file); -+ if (!fi_lsc) -+ di_write_lock_child(dentry); -+ else -+ di_write_lock_child2(dentry); -+ btop = au_dbtop(dentry); -+ pseudo_link = (btop != au_ibtop(inode)); -+ if (sigen == figen && !pseudo_link && au_fbtop(file) == btop) { -+ if (!wlock) { -+ di_downgrade_lock(dentry, AuLock_IR); -+ fi_downgrade_lock(file); -+ } -+ goto out; /* success */ -+ } -+ -+ AuDbg("sigen %d, figen %d\n", sigen, figen); -+ if (au_digen_test(dentry, sigen)) { -+ err = au_reval_dpath(dentry, sigen); -+ AuDebugOn(!err && au_digen_test(dentry, sigen)); -+ } -+ -+ if (!err) -+ err = refresh_file(file, reopen); -+ if (!err) { -+ if (!wlock) { -+ di_downgrade_lock(dentry, AuLock_IR); -+ fi_downgrade_lock(file); -+ } -+ } else { -+ di_write_unlock(dentry); -+ fi_write_unlock(file); -+ } -+ -+out: -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* cf. aufs_nopage() */ -+/* for madvise(2) */ -+static int aufs_readpage(struct file *file __maybe_unused, struct page *page) -+{ -+ unlock_page(page); -+ return 0; -+} -+ -+/* it will never be called, but necessary to support O_DIRECT */ -+static ssize_t aufs_direct_IO(struct kiocb *iocb, struct iov_iter *iter) -+{ BUG(); return 0; } -+ -+/* they will never be called. */ -+#ifdef CONFIG_AUFS_DEBUG -+static int aufs_write_begin(struct file *file, struct address_space *mapping, -+ loff_t pos, unsigned len, unsigned flags, -+ struct page **pagep, void **fsdata) -+{ AuUnsupport(); return 0; } -+static int aufs_write_end(struct file *file, struct address_space *mapping, -+ loff_t pos, unsigned len, unsigned copied, -+ struct page *page, void *fsdata) -+{ AuUnsupport(); return 0; } -+static int aufs_writepage(struct page *page, struct writeback_control *wbc) -+{ AuUnsupport(); return 0; } -+ -+static int aufs_set_page_dirty(struct page *page) -+{ AuUnsupport(); return 0; } -+static void aufs_invalidatepage(struct page *page, unsigned int offset, -+ unsigned int length) -+{ AuUnsupport(); } -+static int aufs_releasepage(struct page *page, gfp_t gfp) -+{ AuUnsupport(); return 0; } -+#if 0 /* called by memory compaction regardless file */ -+static int aufs_migratepage(struct address_space *mapping, struct page *newpage, -+ struct page *page, enum migrate_mode mode) -+{ AuUnsupport(); return 0; } -+#endif -+static bool aufs_isolate_page(struct page *page, isolate_mode_t mode) -+{ AuUnsupport(); return true; } -+static void aufs_putback_page(struct page *page) -+{ AuUnsupport(); } -+static int aufs_launder_page(struct page *page) -+{ AuUnsupport(); return 0; } -+static int aufs_is_partially_uptodate(struct page *page, -+ unsigned long from, -+ unsigned long count) -+{ AuUnsupport(); return 0; } -+static void aufs_is_dirty_writeback(struct page *page, bool *dirty, -+ bool *writeback) -+{ AuUnsupport(); } -+static int aufs_error_remove_page(struct address_space *mapping, -+ struct page *page) -+{ AuUnsupport(); return 0; } -+static int aufs_swap_activate(struct swap_info_struct *sis, struct file *file, -+ sector_t *span) -+{ AuUnsupport(); return 0; } -+static void aufs_swap_deactivate(struct file *file) -+{ AuUnsupport(); } -+#endif /* CONFIG_AUFS_DEBUG */ -+ -+const struct address_space_operations aufs_aop = { -+ .readpage = aufs_readpage, -+ .direct_IO = aufs_direct_IO, -+#ifdef CONFIG_AUFS_DEBUG -+ .writepage = aufs_writepage, -+ /* no writepages, because of writepage */ -+ .set_page_dirty = aufs_set_page_dirty, -+ /* no readpages, because of readpage */ -+ .write_begin = aufs_write_begin, -+ .write_end = aufs_write_end, -+ /* no bmap, no block device */ -+ .invalidatepage = aufs_invalidatepage, -+ .releasepage = aufs_releasepage, -+ /* is fallback_migrate_page ok? */ -+ /* .migratepage = aufs_migratepage, */ -+ .isolate_page = aufs_isolate_page, -+ .putback_page = aufs_putback_page, -+ .launder_page = aufs_launder_page, -+ .is_partially_uptodate = aufs_is_partially_uptodate, -+ .is_dirty_writeback = aufs_is_dirty_writeback, -+ .error_remove_page = aufs_error_remove_page, -+ .swap_activate = aufs_swap_activate, -+ .swap_deactivate = aufs_swap_deactivate -+#endif /* CONFIG_AUFS_DEBUG */ -+}; -diff -Nurp linux-5.10-rc6/fs/aufs/file.h linux-5.10-rc6.aufs/fs/aufs/file.h ---- linux-5.10-rc6/fs/aufs/file.h 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/file.h 2020-12-02 21:19:51.881036743 +0200 -@@ -0,0 +1,329 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * file operations -+ */ -+ -+#ifndef __AUFS_FILE_H__ -+#define __AUFS_FILE_H__ -+ -+#ifdef __KERNEL__ -+ -+#include -+#include -+#include -+#include -+#include "rwsem.h" -+ -+struct au_branch; -+struct au_hfile { -+ struct file *hf_file; -+ struct au_branch *hf_br; -+}; -+ -+struct au_vdir; -+struct au_fidir { -+ aufs_bindex_t fd_bbot; -+ aufs_bindex_t fd_nent; -+ struct au_vdir *fd_vdir_cache; -+ struct au_hfile fd_hfile[]; -+}; -+ -+static inline int au_fidir_sz(int nent) -+{ -+ AuDebugOn(nent < 0); -+ return sizeof(struct au_fidir) + sizeof(struct au_hfile) * nent; -+} -+ -+struct au_finfo { -+ atomic_t fi_generation; -+ -+ struct au_rwsem fi_rwsem; -+ aufs_bindex_t fi_btop; -+ -+ /* do not union them */ -+ struct { /* for non-dir */ -+ struct au_hfile fi_htop; -+ atomic_t fi_mmapped; -+ }; -+ struct au_fidir *fi_hdir; /* for dir only */ -+ -+ struct hlist_bl_node fi_hlist; -+ struct file *fi_file; /* very ugly */ -+ struct rcu_head rcu; -+} ____cacheline_aligned_in_smp; -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* file.c */ -+extern const struct address_space_operations aufs_aop; -+unsigned int au_file_roflags(unsigned int flags); -+struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags, -+ struct file *file, int force_wr); -+struct au_do_open_args { -+ int aopen; -+ int (*open)(struct file *file, int flags, -+ struct file *h_file); -+ struct au_fidir *fidir; -+ struct file *h_file; -+}; -+int au_do_open(struct file *file, struct au_do_open_args *args); -+int au_reopen_nondir(struct file *file); -+struct au_pin; -+int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin); -+int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file), -+ int wlock, unsigned int fi_lsc); -+int au_do_flush(struct file *file, fl_owner_t id, -+ int (*flush)(struct file *file, fl_owner_t id)); -+ -+/* poll.c */ -+#ifdef CONFIG_AUFS_POLL -+__poll_t aufs_poll(struct file *file, struct poll_table_struct *pt); -+#endif -+ -+#ifdef CONFIG_AUFS_BR_HFSPLUS -+/* hfsplus.c */ -+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex, -+ int force_wr); -+void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex, -+ struct file *h_file); -+#else -+AuStub(struct file *, au_h_open_pre, return NULL, struct dentry *dentry, -+ aufs_bindex_t bindex, int force_wr) -+AuStubVoid(au_h_open_post, struct dentry *dentry, aufs_bindex_t bindex, -+ struct file *h_file); -+#endif -+ -+/* f_op.c */ -+extern const struct file_operations aufs_file_fop; -+int au_do_open_nondir(struct file *file, int flags, struct file *h_file); -+int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file); -+struct file *au_read_pre(struct file *file, int keep_fi, unsigned int lsc); -+ -+/* finfo.c */ -+void au_hfput(struct au_hfile *hf, int execed); -+void au_set_h_fptr(struct file *file, aufs_bindex_t bindex, -+ struct file *h_file); -+ -+void au_update_figen(struct file *file); -+struct au_fidir *au_fidir_alloc(struct super_block *sb); -+int au_fidir_realloc(struct au_finfo *finfo, int nbr, int may_shrink); -+ -+void au_fi_init_once(void *_fi); -+void au_finfo_fin(struct file *file); -+int au_finfo_init(struct file *file, struct au_fidir *fidir); -+ -+/* ioctl.c */ -+long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg); -+#ifdef CONFIG_COMPAT -+long aufs_compat_ioctl_dir(struct file *file, unsigned int cmd, -+ unsigned long arg); -+long aufs_compat_ioctl_nondir(struct file *file, unsigned int cmd, -+ unsigned long arg); -+#endif -+ -+/* ---------------------------------------------------------------------- */ -+ -+static inline struct au_finfo *au_fi(struct file *file) -+{ -+ return file->private_data; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+#define fi_read_lock(f) au_rw_read_lock(&au_fi(f)->fi_rwsem) -+#define fi_write_lock(f) au_rw_write_lock(&au_fi(f)->fi_rwsem) -+#define fi_read_trylock(f) au_rw_read_trylock(&au_fi(f)->fi_rwsem) -+#define fi_write_trylock(f) au_rw_write_trylock(&au_fi(f)->fi_rwsem) -+/* -+#define fi_read_trylock_nested(f) \ -+ au_rw_read_trylock_nested(&au_fi(f)->fi_rwsem) -+#define fi_write_trylock_nested(f) \ -+ au_rw_write_trylock_nested(&au_fi(f)->fi_rwsem) -+*/ -+ -+#define fi_read_unlock(f) au_rw_read_unlock(&au_fi(f)->fi_rwsem) -+#define fi_write_unlock(f) au_rw_write_unlock(&au_fi(f)->fi_rwsem) -+#define fi_downgrade_lock(f) au_rw_dgrade_lock(&au_fi(f)->fi_rwsem) -+ -+/* lock subclass for finfo */ -+enum { -+ AuLsc_FI_1, -+ AuLsc_FI_2 -+}; -+ -+static inline void fi_read_lock_nested(struct file *f, unsigned int lsc) -+{ -+ au_rw_read_lock_nested(&au_fi(f)->fi_rwsem, lsc); -+} -+ -+static inline void fi_write_lock_nested(struct file *f, unsigned int lsc) -+{ -+ au_rw_write_lock_nested(&au_fi(f)->fi_rwsem, lsc); -+} -+ -+/* -+ * fi_read_lock_1, fi_write_lock_1, -+ * fi_read_lock_2, fi_write_lock_2 -+ */ -+#define AuReadLockFunc(name) \ -+static inline void fi_read_lock_##name(struct file *f) \ -+{ fi_read_lock_nested(f, AuLsc_FI_##name); } -+ -+#define AuWriteLockFunc(name) \ -+static inline void fi_write_lock_##name(struct file *f) \ -+{ fi_write_lock_nested(f, AuLsc_FI_##name); } -+ -+#define AuRWLockFuncs(name) \ -+ AuReadLockFunc(name) \ -+ AuWriteLockFunc(name) -+ -+AuRWLockFuncs(1); -+AuRWLockFuncs(2); -+ -+#undef AuReadLockFunc -+#undef AuWriteLockFunc -+#undef AuRWLockFuncs -+ -+#define FiMustNoWaiters(f) AuRwMustNoWaiters(&au_fi(f)->fi_rwsem) -+#define FiMustAnyLock(f) AuRwMustAnyLock(&au_fi(f)->fi_rwsem) -+#define FiMustWriteLock(f) AuRwMustWriteLock(&au_fi(f)->fi_rwsem) -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* todo: hard/soft set? */ -+static inline aufs_bindex_t au_fbtop(struct file *file) -+{ -+ FiMustAnyLock(file); -+ return au_fi(file)->fi_btop; -+} -+ -+static inline aufs_bindex_t au_fbbot_dir(struct file *file) -+{ -+ FiMustAnyLock(file); -+ AuDebugOn(!au_fi(file)->fi_hdir); -+ return au_fi(file)->fi_hdir->fd_bbot; -+} -+ -+static inline struct au_vdir *au_fvdir_cache(struct file *file) -+{ -+ FiMustAnyLock(file); -+ AuDebugOn(!au_fi(file)->fi_hdir); -+ return au_fi(file)->fi_hdir->fd_vdir_cache; -+} -+ -+static inline void au_set_fbtop(struct file *file, aufs_bindex_t bindex) -+{ -+ FiMustWriteLock(file); -+ au_fi(file)->fi_btop = bindex; -+} -+ -+static inline void au_set_fbbot_dir(struct file *file, aufs_bindex_t bindex) -+{ -+ FiMustWriteLock(file); -+ AuDebugOn(!au_fi(file)->fi_hdir); -+ au_fi(file)->fi_hdir->fd_bbot = bindex; -+} -+ -+static inline void au_set_fvdir_cache(struct file *file, -+ struct au_vdir *vdir_cache) -+{ -+ FiMustWriteLock(file); -+ AuDebugOn(!au_fi(file)->fi_hdir); -+ au_fi(file)->fi_hdir->fd_vdir_cache = vdir_cache; -+} -+ -+static inline struct file *au_hf_top(struct file *file) -+{ -+ FiMustAnyLock(file); -+ AuDebugOn(au_fi(file)->fi_hdir); -+ return au_fi(file)->fi_htop.hf_file; -+} -+ -+static inline struct file *au_hf_dir(struct file *file, aufs_bindex_t bindex) -+{ -+ FiMustAnyLock(file); -+ AuDebugOn(!au_fi(file)->fi_hdir); -+ return au_fi(file)->fi_hdir->fd_hfile[0 + bindex].hf_file; -+} -+ -+/* todo: memory barrier? */ -+static inline unsigned int au_figen(struct file *f) -+{ -+ return atomic_read(&au_fi(f)->fi_generation); -+} -+ -+static inline void au_set_mmapped(struct file *f) -+{ -+ if (atomic_inc_return(&au_fi(f)->fi_mmapped)) -+ return; -+ pr_warn("fi_mmapped wrapped around\n"); -+ while (!atomic_inc_return(&au_fi(f)->fi_mmapped)) -+ ; -+} -+ -+static inline void au_unset_mmapped(struct file *f) -+{ -+ atomic_dec(&au_fi(f)->fi_mmapped); -+} -+ -+static inline int au_test_mmapped(struct file *f) -+{ -+ return atomic_read(&au_fi(f)->fi_mmapped); -+} -+ -+/* customize vma->vm_file */ -+ -+static inline void au_do_vm_file_reset(struct vm_area_struct *vma, -+ struct file *file) -+{ -+ struct file *f; -+ -+ f = vma->vm_file; -+ get_file(file); -+ vma->vm_file = file; -+ fput(f); -+} -+ -+#ifdef CONFIG_MMU -+#define AuDbgVmRegion(file, vma) do {} while (0) -+ -+static inline void au_vm_file_reset(struct vm_area_struct *vma, -+ struct file *file) -+{ -+ au_do_vm_file_reset(vma, file); -+} -+#else -+#define AuDbgVmRegion(file, vma) \ -+ AuDebugOn((vma)->vm_region && (vma)->vm_region->vm_file != (file)) -+ -+static inline void au_vm_file_reset(struct vm_area_struct *vma, -+ struct file *file) -+{ -+ struct file *f; -+ -+ au_do_vm_file_reset(vma, file); -+ f = vma->vm_region->vm_file; -+ get_file(file); -+ vma->vm_region->vm_file = file; -+ fput(f); -+} -+#endif /* CONFIG_MMU */ -+ -+/* handle vma->vm_prfile */ -+static inline void au_vm_prfile_set(struct vm_area_struct *vma, -+ struct file *file) -+{ -+ get_file(file); -+ vma->vm_prfile = file; -+#ifndef CONFIG_MMU -+ get_file(file); -+ vma->vm_region->vm_prfile = file; -+#endif -+} -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_FILE_H__ */ -diff -Nurp linux-5.10-rc6/fs/aufs/finfo.c linux-5.10-rc6.aufs/fs/aufs/finfo.c ---- linux-5.10-rc6/fs/aufs/finfo.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/finfo.c 2020-12-02 21:19:51.881036743 +0200 -@@ -0,0 +1,136 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * file private data -+ */ -+ -+#include "aufs.h" -+ -+void au_hfput(struct au_hfile *hf, int execed) -+{ -+ if (execed) -+ allow_write_access(hf->hf_file); -+ fput(hf->hf_file); -+ hf->hf_file = NULL; -+ au_lcnt_dec(&hf->hf_br->br_nfiles); -+ hf->hf_br = NULL; -+} -+ -+void au_set_h_fptr(struct file *file, aufs_bindex_t bindex, struct file *val) -+{ -+ struct au_finfo *finfo = au_fi(file); -+ struct au_hfile *hf; -+ struct au_fidir *fidir; -+ -+ fidir = finfo->fi_hdir; -+ if (!fidir) { -+ AuDebugOn(finfo->fi_btop != bindex); -+ hf = &finfo->fi_htop; -+ } else -+ hf = fidir->fd_hfile + bindex; -+ -+ if (hf && hf->hf_file) -+ au_hfput(hf, vfsub_file_execed(file)); -+ if (val) { -+ FiMustWriteLock(file); -+ AuDebugOn(IS_ERR_OR_NULL(file->f_path.dentry)); -+ hf->hf_file = val; -+ hf->hf_br = au_sbr(file->f_path.dentry->d_sb, bindex); -+ } -+} -+ -+void au_update_figen(struct file *file) -+{ -+ atomic_set(&au_fi(file)->fi_generation, au_digen(file->f_path.dentry)); -+ /* smp_mb(); */ /* atomic_set */ -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct au_fidir *au_fidir_alloc(struct super_block *sb) -+{ -+ struct au_fidir *fidir; -+ int nbr; -+ -+ nbr = au_sbbot(sb) + 1; -+ if (nbr < 2) -+ nbr = 2; /* initial allocate for 2 branches */ -+ fidir = kzalloc(au_fidir_sz(nbr), GFP_NOFS); -+ if (fidir) { -+ fidir->fd_bbot = -1; -+ fidir->fd_nent = nbr; -+ } -+ -+ return fidir; -+} -+ -+int au_fidir_realloc(struct au_finfo *finfo, int nbr, int may_shrink) -+{ -+ int err; -+ struct au_fidir *fidir, *p; -+ -+ AuRwMustWriteLock(&finfo->fi_rwsem); -+ fidir = finfo->fi_hdir; -+ AuDebugOn(!fidir); -+ -+ err = -ENOMEM; -+ p = au_kzrealloc(fidir, au_fidir_sz(fidir->fd_nent), au_fidir_sz(nbr), -+ GFP_NOFS, may_shrink); -+ if (p) { -+ p->fd_nent = nbr; -+ finfo->fi_hdir = p; -+ err = 0; -+ } -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+void au_finfo_fin(struct file *file) -+{ -+ struct au_finfo *finfo; -+ -+ au_lcnt_dec(&au_sbi(file->f_path.dentry->d_sb)->si_nfiles); -+ -+ finfo = au_fi(file); -+ AuDebugOn(finfo->fi_hdir); -+ AuRwDestroy(&finfo->fi_rwsem); -+ au_cache_free_finfo(finfo); -+} -+ -+void au_fi_init_once(void *_finfo) -+{ -+ struct au_finfo *finfo = _finfo; -+ -+ au_rw_init(&finfo->fi_rwsem); -+} -+ -+int au_finfo_init(struct file *file, struct au_fidir *fidir) -+{ -+ int err; -+ struct au_finfo *finfo; -+ struct dentry *dentry; -+ -+ err = -ENOMEM; -+ dentry = file->f_path.dentry; -+ finfo = au_cache_alloc_finfo(); -+ if (unlikely(!finfo)) -+ goto out; -+ -+ err = 0; -+ au_lcnt_inc(&au_sbi(dentry->d_sb)->si_nfiles); -+ au_rw_write_lock(&finfo->fi_rwsem); -+ finfo->fi_btop = -1; -+ finfo->fi_hdir = fidir; -+ atomic_set(&finfo->fi_generation, au_digen(dentry)); -+ /* smp_mb(); */ /* atomic_set */ -+ -+ file->private_data = finfo; -+ -+out: -+ return err; -+} -diff -Nurp linux-5.10-rc6/fs/aufs/f_op.c linux-5.10-rc6.aufs/fs/aufs/f_op.c ---- linux-5.10-rc6/fs/aufs/f_op.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/f_op.c 2020-12-02 21:19:51.881036743 +0200 -@@ -0,0 +1,806 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * file and vm operations -+ */ -+ -+#include -+#include -+#include -+#include -+#include "aufs.h" -+ -+int au_do_open_nondir(struct file *file, int flags, struct file *h_file) -+{ -+ int err; -+ aufs_bindex_t bindex; -+ struct dentry *dentry, *h_dentry; -+ struct au_finfo *finfo; -+ struct inode *h_inode; -+ -+ FiMustWriteLock(file); -+ -+ err = 0; -+ dentry = file->f_path.dentry; -+ AuDebugOn(IS_ERR_OR_NULL(dentry)); -+ finfo = au_fi(file); -+ memset(&finfo->fi_htop, 0, sizeof(finfo->fi_htop)); -+ atomic_set(&finfo->fi_mmapped, 0); -+ bindex = au_dbtop(dentry); -+ if (!h_file) { -+ h_dentry = au_h_dptr(dentry, bindex); -+ err = vfsub_test_mntns(file->f_path.mnt, h_dentry->d_sb); -+ if (unlikely(err)) -+ goto out; -+ h_file = au_h_open(dentry, bindex, flags, file, /*force_wr*/0); -+ if (IS_ERR(h_file)) { -+ err = PTR_ERR(h_file); -+ goto out; -+ } -+ } else { -+ h_dentry = h_file->f_path.dentry; -+ err = vfsub_test_mntns(file->f_path.mnt, h_dentry->d_sb); -+ if (unlikely(err)) -+ goto out; -+ /* br ref is already inc-ed */ -+ } -+ -+ if ((flags & __O_TMPFILE) -+ && !(flags & O_EXCL)) { -+ h_inode = file_inode(h_file); -+ spin_lock(&h_inode->i_lock); -+ h_inode->i_state |= I_LINKABLE; -+ spin_unlock(&h_inode->i_lock); -+ } -+ au_set_fbtop(file, bindex); -+ au_set_h_fptr(file, bindex, h_file); -+ au_update_figen(file); -+ /* todo: necessary? */ -+ /* file->f_ra = h_file->f_ra; */ -+ -+out: -+ return err; -+} -+ -+static int aufs_open_nondir(struct inode *inode __maybe_unused, -+ struct file *file) -+{ -+ int err; -+ struct super_block *sb; -+ struct au_do_open_args args = { -+ .open = au_do_open_nondir -+ }; -+ -+ AuDbg("%pD, f_flags 0x%x, f_mode 0x%x\n", -+ file, vfsub_file_flags(file), file->f_mode); -+ -+ sb = file->f_path.dentry->d_sb; -+ si_read_lock(sb, AuLock_FLUSH); -+ err = au_do_open(file, &args); -+ si_read_unlock(sb); -+ return err; -+} -+ -+int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file) -+{ -+ struct au_finfo *finfo; -+ aufs_bindex_t bindex; -+ -+ finfo = au_fi(file); -+ au_hbl_del(&finfo->fi_hlist, -+ &au_sbi(file->f_path.dentry->d_sb)->si_files); -+ bindex = finfo->fi_btop; -+ if (bindex >= 0) -+ au_set_h_fptr(file, bindex, NULL); -+ -+ au_finfo_fin(file); -+ return 0; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int au_do_flush_nondir(struct file *file, fl_owner_t id) -+{ -+ int err; -+ struct file *h_file; -+ -+ err = 0; -+ h_file = au_hf_top(file); -+ if (h_file) -+ err = vfsub_flush(h_file, id); -+ return err; -+} -+ -+static int aufs_flush_nondir(struct file *file, fl_owner_t id) -+{ -+ return au_do_flush(file, id, au_do_flush_nondir); -+} -+ -+/* ---------------------------------------------------------------------- */ -+/* -+ * read and write functions acquire [fdi]_rwsem once, but release before -+ * mmap_sem. This is because to stop a race condition between mmap(2). -+ * Releasing these aufs-rwsem should be safe, no branch-management (by keeping -+ * si_rwsem), no harmful copy-up should happen. Actually copy-up may happen in -+ * read functions after [fdi]_rwsem are released, but it should be harmless. -+ */ -+ -+/* Callers should call au_read_post() or fput() in the end */ -+struct file *au_read_pre(struct file *file, int keep_fi, unsigned int lsc) -+{ -+ struct file *h_file; -+ int err; -+ -+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0, lsc); -+ if (!err) { -+ di_read_unlock(file->f_path.dentry, AuLock_IR); -+ h_file = au_hf_top(file); -+ get_file(h_file); -+ if (!keep_fi) -+ fi_read_unlock(file); -+ } else -+ h_file = ERR_PTR(err); -+ -+ return h_file; -+} -+ -+static void au_read_post(struct inode *inode, struct file *h_file) -+{ -+ /* update without lock, I don't think it a problem */ -+ fsstack_copy_attr_atime(inode, file_inode(h_file)); -+ fput(h_file); -+} -+ -+struct au_write_pre { -+ /* input */ -+ unsigned int lsc; -+ -+ /* output */ -+ blkcnt_t blks; -+ aufs_bindex_t btop; -+}; -+ -+/* -+ * return with iinfo is write-locked -+ * callers should call au_write_post() or iinfo_write_unlock() + fput() in the -+ * end -+ */ -+static struct file *au_write_pre(struct file *file, int do_ready, -+ struct au_write_pre *wpre) -+{ -+ struct file *h_file; -+ struct dentry *dentry; -+ int err; -+ unsigned int lsc; -+ struct au_pin pin; -+ -+ lsc = 0; -+ if (wpre) -+ lsc = wpre->lsc; -+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1, lsc); -+ h_file = ERR_PTR(err); -+ if (unlikely(err)) -+ goto out; -+ -+ dentry = file->f_path.dentry; -+ if (do_ready) { -+ err = au_ready_to_write(file, -1, &pin); -+ if (unlikely(err)) { -+ h_file = ERR_PTR(err); -+ di_write_unlock(dentry); -+ goto out_fi; -+ } -+ } -+ -+ di_downgrade_lock(dentry, /*flags*/0); -+ if (wpre) -+ wpre->btop = au_fbtop(file); -+ h_file = au_hf_top(file); -+ get_file(h_file); -+ if (wpre) -+ wpre->blks = file_inode(h_file)->i_blocks; -+ if (do_ready) -+ au_unpin(&pin); -+ di_read_unlock(dentry, /*flags*/0); -+ -+out_fi: -+ fi_write_unlock(file); -+out: -+ return h_file; -+} -+ -+static void au_write_post(struct inode *inode, struct file *h_file, -+ struct au_write_pre *wpre, ssize_t written) -+{ -+ struct inode *h_inode; -+ -+ au_cpup_attr_timesizes(inode); -+ AuDebugOn(au_ibtop(inode) != wpre->btop); -+ h_inode = file_inode(h_file); -+ inode->i_mode = h_inode->i_mode; -+ ii_write_unlock(inode); -+ /* AuDbg("blks %llu, %llu\n", (u64)blks, (u64)h_inode->i_blocks); */ -+ if (written > 0) -+ au_fhsm_wrote(inode->i_sb, wpre->btop, -+ /*force*/h_inode->i_blocks > wpre->blks); -+ fput(h_file); -+} -+ -+static ssize_t aufs_read(struct file *file, char __user *buf, size_t count, -+ loff_t *ppos) -+{ -+ ssize_t err; -+ struct inode *inode; -+ struct file *h_file; -+ struct super_block *sb; -+ -+ inode = file_inode(file); -+ sb = inode->i_sb; -+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW); -+ -+ h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0); -+ err = PTR_ERR(h_file); -+ if (IS_ERR(h_file)) -+ goto out; -+ -+ /* filedata may be obsoleted by concurrent copyup, but no problem */ -+ err = vfsub_read_u(h_file, buf, count, ppos); -+ /* todo: necessary? */ -+ /* file->f_ra = h_file->f_ra; */ -+ au_read_post(inode, h_file); -+ -+out: -+ si_read_unlock(sb); -+ return err; -+} -+ -+/* -+ * todo: very ugly -+ * it locks both of i_mutex and si_rwsem for read in safe. -+ * if the plink maintenance mode continues forever (that is the problem), -+ * may loop forever. -+ */ -+static void au_mtx_and_read_lock(struct inode *inode) -+{ -+ int err; -+ struct super_block *sb = inode->i_sb; -+ -+ while (1) { -+ inode_lock(inode); -+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM); -+ if (!err) -+ break; -+ inode_unlock(inode); -+ si_read_lock(sb, AuLock_NOPLMW); -+ si_read_unlock(sb); -+ } -+} -+ -+static ssize_t aufs_write(struct file *file, const char __user *ubuf, -+ size_t count, loff_t *ppos) -+{ -+ ssize_t err; -+ struct au_write_pre wpre; -+ struct inode *inode; -+ struct file *h_file; -+ char __user *buf = (char __user *)ubuf; -+ -+ inode = file_inode(file); -+ au_mtx_and_read_lock(inode); -+ -+ wpre.lsc = 0; -+ h_file = au_write_pre(file, /*do_ready*/1, &wpre); -+ err = PTR_ERR(h_file); -+ if (IS_ERR(h_file)) -+ goto out; -+ -+ err = vfsub_write_u(h_file, buf, count, ppos); -+ au_write_post(inode, h_file, &wpre, err); -+ -+out: -+ si_read_unlock(inode->i_sb); -+ inode_unlock(inode); -+ return err; -+} -+ -+static ssize_t au_do_iter(struct file *h_file, int rw, struct kiocb *kio, -+ struct iov_iter *iov_iter) -+{ -+ ssize_t err; -+ struct file *file; -+ ssize_t (*iter)(struct kiocb *, struct iov_iter *); -+ -+ err = security_file_permission(h_file, rw); -+ if (unlikely(err)) -+ goto out; -+ -+ err = -ENOSYS; /* the branch doesn't have its ->(read|write)_iter() */ -+ iter = NULL; -+ if (rw == MAY_READ) -+ iter = h_file->f_op->read_iter; -+ else if (rw == MAY_WRITE) -+ iter = h_file->f_op->write_iter; -+ -+ file = kio->ki_filp; -+ kio->ki_filp = h_file; -+ if (iter) { -+ lockdep_off(); -+ err = iter(kio, iov_iter); -+ lockdep_on(); -+ } else -+ /* currently there is no such fs */ -+ WARN_ON_ONCE(1); -+ kio->ki_filp = file; -+ -+out: -+ return err; -+} -+ -+static ssize_t aufs_read_iter(struct kiocb *kio, struct iov_iter *iov_iter) -+{ -+ ssize_t err; -+ struct file *file, *h_file; -+ struct inode *inode; -+ struct super_block *sb; -+ -+ file = kio->ki_filp; -+ inode = file_inode(file); -+ sb = inode->i_sb; -+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW); -+ -+ h_file = au_read_pre(file, /*keep_fi*/1, /*lsc*/0); -+ err = PTR_ERR(h_file); -+ if (IS_ERR(h_file)) -+ goto out; -+ -+ if (au_test_loopback_kthread()) { -+ au_warn_loopback(h_file->f_path.dentry->d_sb); -+ if (file->f_mapping != h_file->f_mapping) { -+ file->f_mapping = h_file->f_mapping; -+ smp_mb(); /* unnecessary? */ -+ } -+ } -+ fi_read_unlock(file); -+ -+ err = au_do_iter(h_file, MAY_READ, kio, iov_iter); -+ /* todo: necessary? */ -+ /* file->f_ra = h_file->f_ra; */ -+ au_read_post(inode, h_file); -+ -+out: -+ si_read_unlock(sb); -+ return err; -+} -+ -+static ssize_t aufs_write_iter(struct kiocb *kio, struct iov_iter *iov_iter) -+{ -+ ssize_t err; -+ struct au_write_pre wpre; -+ struct inode *inode; -+ struct file *file, *h_file; -+ -+ file = kio->ki_filp; -+ inode = file_inode(file); -+ au_mtx_and_read_lock(inode); -+ -+ wpre.lsc = 0; -+ h_file = au_write_pre(file, /*do_ready*/1, &wpre); -+ err = PTR_ERR(h_file); -+ if (IS_ERR(h_file)) -+ goto out; -+ -+ err = au_do_iter(h_file, MAY_WRITE, kio, iov_iter); -+ au_write_post(inode, h_file, &wpre, err); -+ -+out: -+ si_read_unlock(inode->i_sb); -+ inode_unlock(inode); -+ return err; -+} -+ -+static ssize_t aufs_splice_read(struct file *file, loff_t *ppos, -+ struct pipe_inode_info *pipe, size_t len, -+ unsigned int flags) -+{ -+ ssize_t err; -+ struct file *h_file; -+ struct inode *inode; -+ struct super_block *sb; -+ -+ inode = file_inode(file); -+ sb = inode->i_sb; -+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW); -+ -+ h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0); -+ err = PTR_ERR(h_file); -+ if (IS_ERR(h_file)) -+ goto out; -+ -+ err = vfsub_splice_to(h_file, ppos, pipe, len, flags); -+ /* todo: necessary? */ -+ /* file->f_ra = h_file->f_ra; */ -+ au_read_post(inode, h_file); -+ -+out: -+ si_read_unlock(sb); -+ return err; -+} -+ -+static ssize_t -+aufs_splice_write(struct pipe_inode_info *pipe, struct file *file, loff_t *ppos, -+ size_t len, unsigned int flags) -+{ -+ ssize_t err; -+ struct au_write_pre wpre; -+ struct inode *inode; -+ struct file *h_file; -+ -+ inode = file_inode(file); -+ au_mtx_and_read_lock(inode); -+ -+ wpre.lsc = 0; -+ h_file = au_write_pre(file, /*do_ready*/1, &wpre); -+ err = PTR_ERR(h_file); -+ if (IS_ERR(h_file)) -+ goto out; -+ -+ err = vfsub_splice_from(pipe, h_file, ppos, len, flags); -+ au_write_post(inode, h_file, &wpre, err); -+ -+out: -+ si_read_unlock(inode->i_sb); -+ inode_unlock(inode); -+ return err; -+} -+ -+static long aufs_fallocate(struct file *file, int mode, loff_t offset, -+ loff_t len) -+{ -+ long err; -+ struct au_write_pre wpre; -+ struct inode *inode; -+ struct file *h_file; -+ -+ inode = file_inode(file); -+ au_mtx_and_read_lock(inode); -+ -+ wpre.lsc = 0; -+ h_file = au_write_pre(file, /*do_ready*/1, &wpre); -+ err = PTR_ERR(h_file); -+ if (IS_ERR(h_file)) -+ goto out; -+ -+ lockdep_off(); -+ err = vfs_fallocate(h_file, mode, offset, len); -+ lockdep_on(); -+ au_write_post(inode, h_file, &wpre, /*written*/1); -+ -+out: -+ si_read_unlock(inode->i_sb); -+ inode_unlock(inode); -+ return err; -+} -+ -+static ssize_t aufs_copy_file_range(struct file *src, loff_t src_pos, -+ struct file *dst, loff_t dst_pos, -+ size_t len, unsigned int flags) -+{ -+ ssize_t err; -+ struct au_write_pre wpre; -+ enum { SRC, DST }; -+ struct { -+ struct inode *inode; -+ struct file *h_file; -+ struct super_block *h_sb; -+ } a[2]; -+#define a_src a[SRC] -+#define a_dst a[DST] -+ -+ err = -EINVAL; -+ a_src.inode = file_inode(src); -+ if (unlikely(!S_ISREG(a_src.inode->i_mode))) -+ goto out; -+ a_dst.inode = file_inode(dst); -+ if (unlikely(!S_ISREG(a_dst.inode->i_mode))) -+ goto out; -+ -+ au_mtx_and_read_lock(a_dst.inode); -+ /* -+ * in order to match the order in di_write_lock2_{child,parent}(), -+ * use f_path.dentry for this comparison. -+ */ -+ if (src->f_path.dentry < dst->f_path.dentry) { -+ a_src.h_file = au_read_pre(src, /*keep_fi*/1, AuLsc_FI_1); -+ err = PTR_ERR(a_src.h_file); -+ if (IS_ERR(a_src.h_file)) -+ goto out_si; -+ -+ wpre.lsc = AuLsc_FI_2; -+ a_dst.h_file = au_write_pre(dst, /*do_ready*/1, &wpre); -+ err = PTR_ERR(a_dst.h_file); -+ if (IS_ERR(a_dst.h_file)) { -+ au_read_post(a_src.inode, a_src.h_file); -+ goto out_si; -+ } -+ } else { -+ wpre.lsc = AuLsc_FI_1; -+ a_dst.h_file = au_write_pre(dst, /*do_ready*/1, &wpre); -+ err = PTR_ERR(a_dst.h_file); -+ if (IS_ERR(a_dst.h_file)) -+ goto out_si; -+ -+ a_src.h_file = au_read_pre(src, /*keep_fi*/1, AuLsc_FI_2); -+ err = PTR_ERR(a_src.h_file); -+ if (IS_ERR(a_src.h_file)) { -+ au_write_post(a_dst.inode, a_dst.h_file, &wpre, -+ /*written*/0); -+ goto out_si; -+ } -+ } -+ -+ err = -EXDEV; -+ a_src.h_sb = file_inode(a_src.h_file)->i_sb; -+ a_dst.h_sb = file_inode(a_dst.h_file)->i_sb; -+ if (unlikely(a_src.h_sb != a_dst.h_sb)) { -+ AuDbgFile(src); -+ AuDbgFile(dst); -+ goto out_file; -+ } -+ -+ err = vfsub_copy_file_range(a_src.h_file, src_pos, a_dst.h_file, -+ dst_pos, len, flags); -+ -+out_file: -+ au_write_post(a_dst.inode, a_dst.h_file, &wpre, err); -+ fi_read_unlock(src); -+ au_read_post(a_src.inode, a_src.h_file); -+out_si: -+ si_read_unlock(a_dst.inode->i_sb); -+ inode_unlock(a_dst.inode); -+out: -+ return err; -+#undef a_src -+#undef a_dst -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * The locking order around current->mmap_sem. -+ * - in most and regular cases -+ * file I/O syscall -- aufs_read() or something -+ * -- si_rwsem for read -- mmap_sem -+ * (Note that [fdi]i_rwsem are released before mmap_sem). -+ * - in mmap case -+ * mmap(2) -- mmap_sem -- aufs_mmap() -- si_rwsem for read -- [fdi]i_rwsem -+ * This AB-BA order is definitely bad, but is not a problem since "si_rwsem for -+ * read" allows multiple processes to acquire it and [fdi]i_rwsem are not held -+ * in file I/O. Aufs needs to stop lockdep in aufs_mmap() though. -+ * It means that when aufs acquires si_rwsem for write, the process should never -+ * acquire mmap_sem. -+ * -+ * Actually aufs_iterate() holds [fdi]i_rwsem before mmap_sem, but this is not a -+ * problem either since any directory is not able to be mmap-ed. -+ * The similar scenario is applied to aufs_readlink() too. -+ */ -+ -+#if 0 /* stop calling security_file_mmap() */ -+/* cf. linux/include/linux/mman.h: calc_vm_prot_bits() */ -+#define AuConv_VM_PROT(f, b) _calc_vm_trans(f, VM_##b, PROT_##b) -+ -+static unsigned long au_arch_prot_conv(unsigned long flags) -+{ -+ /* currently ppc64 only */ -+#ifdef CONFIG_PPC64 -+ /* cf. linux/arch/powerpc/include/asm/mman.h */ -+ AuDebugOn(arch_calc_vm_prot_bits(-1) != VM_SAO); -+ return AuConv_VM_PROT(flags, SAO); -+#else -+ AuDebugOn(arch_calc_vm_prot_bits(-1)); -+ return 0; -+#endif -+} -+ -+static unsigned long au_prot_conv(unsigned long flags) -+{ -+ return AuConv_VM_PROT(flags, READ) -+ | AuConv_VM_PROT(flags, WRITE) -+ | AuConv_VM_PROT(flags, EXEC) -+ | au_arch_prot_conv(flags); -+} -+ -+/* cf. linux/include/linux/mman.h: calc_vm_flag_bits() */ -+#define AuConv_VM_MAP(f, b) _calc_vm_trans(f, VM_##b, MAP_##b) -+ -+static unsigned long au_flag_conv(unsigned long flags) -+{ -+ return AuConv_VM_MAP(flags, GROWSDOWN) -+ | AuConv_VM_MAP(flags, DENYWRITE) -+ | AuConv_VM_MAP(flags, LOCKED); -+} -+#endif -+ -+static int aufs_mmap(struct file *file, struct vm_area_struct *vma) -+{ -+ int err; -+ const unsigned char wlock -+ = (file->f_mode & FMODE_WRITE) && (vma->vm_flags & VM_SHARED); -+ struct super_block *sb; -+ struct file *h_file; -+ struct inode *inode; -+ -+ AuDbgVmRegion(file, vma); -+ -+ inode = file_inode(file); -+ sb = inode->i_sb; -+ lockdep_off(); -+ si_read_lock(sb, AuLock_NOPLMW); -+ -+ h_file = au_write_pre(file, wlock, /*wpre*/NULL); -+ lockdep_on(); -+ err = PTR_ERR(h_file); -+ if (IS_ERR(h_file)) -+ goto out; -+ -+ err = 0; -+ au_set_mmapped(file); -+ au_vm_file_reset(vma, h_file); -+ /* -+ * we cannot call security_mmap_file() here since it may acquire -+ * mmap_sem or i_mutex. -+ * -+ * err = security_mmap_file(h_file, au_prot_conv(vma->vm_flags), -+ * au_flag_conv(vma->vm_flags)); -+ */ -+ if (!err) -+ err = call_mmap(h_file, vma); -+ if (!err) { -+ au_vm_prfile_set(vma, file); -+ fsstack_copy_attr_atime(inode, file_inode(h_file)); -+ goto out_fput; /* success */ -+ } -+ au_unset_mmapped(file); -+ au_vm_file_reset(vma, file); -+ -+out_fput: -+ lockdep_off(); -+ ii_write_unlock(inode); -+ lockdep_on(); -+ fput(h_file); -+out: -+ lockdep_off(); -+ si_read_unlock(sb); -+ lockdep_on(); -+ AuTraceErr(err); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int aufs_fsync_nondir(struct file *file, loff_t start, loff_t end, -+ int datasync) -+{ -+ int err; -+ struct au_write_pre wpre; -+ struct inode *inode; -+ struct file *h_file; -+ -+ err = 0; /* -EBADF; */ /* posix? */ -+ if (unlikely(!(file->f_mode & FMODE_WRITE))) -+ goto out; -+ -+ inode = file_inode(file); -+ au_mtx_and_read_lock(inode); -+ -+ wpre.lsc = 0; -+ h_file = au_write_pre(file, /*do_ready*/1, &wpre); -+ err = PTR_ERR(h_file); -+ if (IS_ERR(h_file)) -+ goto out_unlock; -+ -+ err = vfsub_fsync(h_file, &h_file->f_path, datasync); -+ au_write_post(inode, h_file, &wpre, /*written*/0); -+ -+out_unlock: -+ si_read_unlock(inode->i_sb); -+ inode_unlock(inode); -+out: -+ return err; -+} -+ -+static int aufs_fasync(int fd, struct file *file, int flag) -+{ -+ int err; -+ struct file *h_file; -+ struct super_block *sb; -+ -+ sb = file->f_path.dentry->d_sb; -+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW); -+ -+ h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0); -+ err = PTR_ERR(h_file); -+ if (IS_ERR(h_file)) -+ goto out; -+ -+ if (h_file->f_op->fasync) -+ err = h_file->f_op->fasync(fd, h_file, flag); -+ fput(h_file); /* instead of au_read_post() */ -+ -+out: -+ si_read_unlock(sb); -+ return err; -+} -+ -+static int aufs_setfl(struct file *file, unsigned long arg) -+{ -+ int err; -+ struct file *h_file; -+ struct super_block *sb; -+ -+ sb = file->f_path.dentry->d_sb; -+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW); -+ -+ h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0); -+ err = PTR_ERR(h_file); -+ if (IS_ERR(h_file)) -+ goto out; -+ -+ /* stop calling h_file->fasync */ -+ arg |= vfsub_file_flags(file) & FASYNC; -+ err = setfl(/*unused fd*/-1, h_file, arg); -+ fput(h_file); /* instead of au_read_post() */ -+ -+out: -+ si_read_unlock(sb); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* no one supports this operation, currently */ -+#if 0 /* reserved for future use */ -+static ssize_t aufs_sendpage(struct file *file, struct page *page, int offset, -+ size_t len, loff_t *pos, int more) -+{ -+} -+#endif -+ -+/* ---------------------------------------------------------------------- */ -+ -+const struct file_operations aufs_file_fop = { -+ .owner = THIS_MODULE, -+ -+ .llseek = default_llseek, -+ -+ .read = aufs_read, -+ .write = aufs_write, -+ .read_iter = aufs_read_iter, -+ .write_iter = aufs_write_iter, -+ -+#ifdef CONFIG_AUFS_POLL -+ .poll = aufs_poll, -+#endif -+ .unlocked_ioctl = aufs_ioctl_nondir, -+#ifdef CONFIG_COMPAT -+ .compat_ioctl = aufs_compat_ioctl_nondir, -+#endif -+ .mmap = aufs_mmap, -+ .open = aufs_open_nondir, -+ .flush = aufs_flush_nondir, -+ .release = aufs_release_nondir, -+ .fsync = aufs_fsync_nondir, -+ .fasync = aufs_fasync, -+ /* .sendpage = aufs_sendpage, */ -+ .setfl = aufs_setfl, -+ .splice_write = aufs_splice_write, -+ .splice_read = aufs_splice_read, -+#if 0 /* reserved for future use */ -+ .aio_splice_write = aufs_aio_splice_write, -+ .aio_splice_read = aufs_aio_splice_read, -+#endif -+ .fallocate = aufs_fallocate, -+ .copy_file_range = aufs_copy_file_range -+}; -diff -Nurp linux-5.10-rc6/fs/aufs/fstype.h linux-5.10-rc6.aufs/fs/aufs/fstype.h ---- linux-5.10-rc6/fs/aufs/fstype.h 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/fstype.h 2020-12-02 21:19:51.881036743 +0200 -@@ -0,0 +1,388 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * judging filesystem type -+ */ -+ -+#ifndef __AUFS_FSTYPE_H__ -+#define __AUFS_FSTYPE_H__ -+ -+#ifdef __KERNEL__ -+ -+#include -+#include -+#include -+#include -+ -+static inline int au_test_aufs(struct super_block *sb) -+{ -+ return sb->s_magic == AUFS_SUPER_MAGIC; -+} -+ -+static inline const char *au_sbtype(struct super_block *sb) -+{ -+ return sb->s_type->name; -+} -+ -+static inline int au_test_iso9660(struct super_block *sb __maybe_unused) -+{ -+#if IS_ENABLED(CONFIG_ISO9660_FS) -+ return sb->s_magic == ISOFS_SUPER_MAGIC; -+#else -+ return 0; -+#endif -+} -+ -+static inline int au_test_romfs(struct super_block *sb __maybe_unused) -+{ -+#if IS_ENABLED(CONFIG_ROMFS_FS) -+ return sb->s_magic == ROMFS_MAGIC; -+#else -+ return 0; -+#endif -+} -+ -+static inline int au_test_cramfs(struct super_block *sb __maybe_unused) -+{ -+#if IS_ENABLED(CONFIG_CRAMFS) -+ return sb->s_magic == CRAMFS_MAGIC; -+#endif -+ return 0; -+} -+ -+static inline int au_test_nfs(struct super_block *sb __maybe_unused) -+{ -+#if IS_ENABLED(CONFIG_NFS_FS) -+ return sb->s_magic == NFS_SUPER_MAGIC; -+#else -+ return 0; -+#endif -+} -+ -+static inline int au_test_fuse(struct super_block *sb __maybe_unused) -+{ -+#if IS_ENABLED(CONFIG_FUSE_FS) -+ return sb->s_magic == FUSE_SUPER_MAGIC; -+#else -+ return 0; -+#endif -+} -+ -+static inline int au_test_xfs(struct super_block *sb __maybe_unused) -+{ -+#if IS_ENABLED(CONFIG_XFS_FS) -+ return sb->s_magic == XFS_SB_MAGIC; -+#else -+ return 0; -+#endif -+} -+ -+static inline int au_test_tmpfs(struct super_block *sb __maybe_unused) -+{ -+#ifdef CONFIG_TMPFS -+ return sb->s_magic == TMPFS_MAGIC; -+#else -+ return 0; -+#endif -+} -+ -+static inline int au_test_ecryptfs(struct super_block *sb __maybe_unused) -+{ -+#if IS_ENABLED(CONFIG_ECRYPT_FS) -+ return !strcmp(au_sbtype(sb), "ecryptfs"); -+#else -+ return 0; -+#endif -+} -+ -+static inline int au_test_ramfs(struct super_block *sb) -+{ -+ return sb->s_magic == RAMFS_MAGIC; -+} -+ -+static inline int au_test_ubifs(struct super_block *sb __maybe_unused) -+{ -+#if IS_ENABLED(CONFIG_UBIFS_FS) -+ return sb->s_magic == UBIFS_SUPER_MAGIC; -+#else -+ return 0; -+#endif -+} -+ -+static inline int au_test_procfs(struct super_block *sb __maybe_unused) -+{ -+#ifdef CONFIG_PROC_FS -+ return sb->s_magic == PROC_SUPER_MAGIC; -+#else -+ return 0; -+#endif -+} -+ -+static inline int au_test_sysfs(struct super_block *sb __maybe_unused) -+{ -+#ifdef CONFIG_SYSFS -+ return sb->s_magic == SYSFS_MAGIC; -+#else -+ return 0; -+#endif -+} -+ -+static inline int au_test_configfs(struct super_block *sb __maybe_unused) -+{ -+#if IS_ENABLED(CONFIG_CONFIGFS_FS) -+ return sb->s_magic == CONFIGFS_MAGIC; -+#else -+ return 0; -+#endif -+} -+ -+static inline int au_test_minix(struct super_block *sb __maybe_unused) -+{ -+#if IS_ENABLED(CONFIG_MINIX_FS) -+ return sb->s_magic == MINIX3_SUPER_MAGIC -+ || sb->s_magic == MINIX2_SUPER_MAGIC -+ || sb->s_magic == MINIX2_SUPER_MAGIC2 -+ || sb->s_magic == MINIX_SUPER_MAGIC -+ || sb->s_magic == MINIX_SUPER_MAGIC2; -+#else -+ return 0; -+#endif -+} -+ -+static inline int au_test_fat(struct super_block *sb __maybe_unused) -+{ -+#if IS_ENABLED(CONFIG_FAT_FS) -+ return sb->s_magic == MSDOS_SUPER_MAGIC; -+#else -+ return 0; -+#endif -+} -+ -+static inline int au_test_msdos(struct super_block *sb) -+{ -+ return au_test_fat(sb); -+} -+ -+static inline int au_test_vfat(struct super_block *sb) -+{ -+ return au_test_fat(sb); -+} -+ -+static inline int au_test_securityfs(struct super_block *sb __maybe_unused) -+{ -+#ifdef CONFIG_SECURITYFS -+ return sb->s_magic == SECURITYFS_MAGIC; -+#else -+ return 0; -+#endif -+} -+ -+static inline int au_test_squashfs(struct super_block *sb __maybe_unused) -+{ -+#if IS_ENABLED(CONFIG_SQUASHFS) -+ return sb->s_magic == SQUASHFS_MAGIC; -+#else -+ return 0; -+#endif -+} -+ -+static inline int au_test_btrfs(struct super_block *sb __maybe_unused) -+{ -+#if IS_ENABLED(CONFIG_BTRFS_FS) -+ return sb->s_magic == BTRFS_SUPER_MAGIC; -+#else -+ return 0; -+#endif -+} -+ -+static inline int au_test_xenfs(struct super_block *sb __maybe_unused) -+{ -+#if IS_ENABLED(CONFIG_XENFS) -+ return sb->s_magic == XENFS_SUPER_MAGIC; -+#else -+ return 0; -+#endif -+} -+ -+static inline int au_test_debugfs(struct super_block *sb __maybe_unused) -+{ -+#ifdef CONFIG_DEBUG_FS -+ return sb->s_magic == DEBUGFS_MAGIC; -+#else -+ return 0; -+#endif -+} -+ -+static inline int au_test_nilfs(struct super_block *sb __maybe_unused) -+{ -+#if IS_ENABLED(CONFIG_NILFS) -+ return sb->s_magic == NILFS_SUPER_MAGIC; -+#else -+ return 0; -+#endif -+} -+ -+static inline int au_test_hfsplus(struct super_block *sb __maybe_unused) -+{ -+#if IS_ENABLED(CONFIG_HFSPLUS_FS) -+ return sb->s_magic == HFSPLUS_SUPER_MAGIC; -+#else -+ return 0; -+#endif -+} -+ -+/* ---------------------------------------------------------------------- */ -+/* -+ * they can't be an aufs branch. -+ */ -+static inline int au_test_fs_unsuppoted(struct super_block *sb) -+{ -+ return -+#ifndef CONFIG_AUFS_BR_RAMFS -+ au_test_ramfs(sb) || -+#endif -+ au_test_procfs(sb) -+ || au_test_sysfs(sb) -+ || au_test_configfs(sb) -+ || au_test_debugfs(sb) -+ || au_test_securityfs(sb) -+ || au_test_xenfs(sb) -+ || au_test_ecryptfs(sb) -+ /* || !strcmp(au_sbtype(sb), "unionfs") */ -+ || au_test_aufs(sb); /* will be supported in next version */ -+} -+ -+static inline int au_test_fs_remote(struct super_block *sb) -+{ -+ return !au_test_tmpfs(sb) -+#ifdef CONFIG_AUFS_BR_RAMFS -+ && !au_test_ramfs(sb) -+#endif -+ && !(sb->s_type->fs_flags & FS_REQUIRES_DEV); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * Note: these functions (below) are created after reading ->getattr() in all -+ * filesystems under linux/fs. it means we have to do so in every update... -+ */ -+ -+/* -+ * some filesystems require getattr to refresh the inode attributes before -+ * referencing. -+ * in most cases, we can rely on the inode attribute in NFS (or every remote fs) -+ * and leave the work for d_revalidate() -+ */ -+static inline int au_test_fs_refresh_iattr(struct super_block *sb) -+{ -+ return au_test_nfs(sb) -+ || au_test_fuse(sb) -+ /* || au_test_btrfs(sb) */ /* untested */ -+ ; -+} -+ -+/* -+ * filesystems which don't maintain i_size or i_blocks. -+ */ -+static inline int au_test_fs_bad_iattr_size(struct super_block *sb) -+{ -+ return au_test_xfs(sb) -+ || au_test_btrfs(sb) -+ || au_test_ubifs(sb) -+ || au_test_hfsplus(sb) /* maintained, but incorrect */ -+ /* || au_test_minix(sb) */ /* untested */ -+ ; -+} -+ -+/* -+ * filesystems which don't store the correct value in some of their inode -+ * attributes. -+ */ -+static inline int au_test_fs_bad_iattr(struct super_block *sb) -+{ -+ return au_test_fs_bad_iattr_size(sb) -+ || au_test_fat(sb) -+ || au_test_msdos(sb) -+ || au_test_vfat(sb); -+} -+ -+/* they don't check i_nlink in link(2) */ -+static inline int au_test_fs_no_limit_nlink(struct super_block *sb) -+{ -+ return au_test_tmpfs(sb) -+#ifdef CONFIG_AUFS_BR_RAMFS -+ || au_test_ramfs(sb) -+#endif -+ || au_test_ubifs(sb) -+ || au_test_hfsplus(sb); -+} -+ -+/* -+ * filesystems which sets S_NOATIME and S_NOCMTIME. -+ */ -+static inline int au_test_fs_notime(struct super_block *sb) -+{ -+ return au_test_nfs(sb) -+ || au_test_fuse(sb) -+ || au_test_ubifs(sb) -+ ; -+} -+ -+/* temporary support for i#1 in cramfs */ -+static inline int au_test_fs_unique_ino(struct inode *inode) -+{ -+ if (au_test_cramfs(inode->i_sb)) -+ return inode->i_ino != 1; -+ return 1; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * the filesystem where the xino files placed must support i/o after unlink and -+ * maintain i_size and i_blocks. -+ */ -+static inline int au_test_fs_bad_xino(struct super_block *sb) -+{ -+ return au_test_fs_remote(sb) -+ || au_test_fs_bad_iattr_size(sb) -+ /* don't want unnecessary work for xino */ -+ || au_test_aufs(sb) -+ || au_test_ecryptfs(sb) -+ || au_test_nilfs(sb); -+} -+ -+static inline int au_test_fs_trunc_xino(struct super_block *sb) -+{ -+ return au_test_tmpfs(sb) -+ || au_test_ramfs(sb); -+} -+ -+/* -+ * test if the @sb is real-readonly. -+ */ -+static inline int au_test_fs_rr(struct super_block *sb) -+{ -+ return au_test_squashfs(sb) -+ || au_test_iso9660(sb) -+ || au_test_cramfs(sb) -+ || au_test_romfs(sb); -+} -+ -+/* -+ * test if the @inode is nfs with 'noacl' option -+ * NFS always sets SB_POSIXACL regardless its mount option 'noacl.' -+ */ -+static inline int au_test_nfs_noacl(struct inode *inode) -+{ -+ return au_test_nfs(inode->i_sb) -+ /* && IS_POSIXACL(inode) */ -+ && !nfs_server_capable(inode, NFS_CAP_ACLS); -+} -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_FSTYPE_H__ */ -diff -Nurp linux-5.10-rc6/fs/aufs/hbl.h linux-5.10-rc6.aufs/fs/aufs/hbl.h ---- linux-5.10-rc6/fs/aufs/hbl.h 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/hbl.h 2020-12-02 21:19:51.881036743 +0200 -@@ -0,0 +1,52 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2017-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * helpers for hlist_bl.h -+ */ -+ -+#ifndef __AUFS_HBL_H__ -+#define __AUFS_HBL_H__ -+ -+#ifdef __KERNEL__ -+ -+#include -+ -+static inline void au_hbl_add(struct hlist_bl_node *node, -+ struct hlist_bl_head *hbl) -+{ -+ hlist_bl_lock(hbl); -+ hlist_bl_add_head(node, hbl); -+ hlist_bl_unlock(hbl); -+} -+ -+static inline void au_hbl_del(struct hlist_bl_node *node, -+ struct hlist_bl_head *hbl) -+{ -+ hlist_bl_lock(hbl); -+ hlist_bl_del(node); -+ hlist_bl_unlock(hbl); -+} -+ -+#define au_hbl_for_each(pos, head) \ -+ for (pos = hlist_bl_first(head); \ -+ pos; \ -+ pos = pos->next) -+ -+static inline unsigned long au_hbl_count(struct hlist_bl_head *hbl) -+{ -+ unsigned long cnt; -+ struct hlist_bl_node *pos; -+ -+ cnt = 0; -+ hlist_bl_lock(hbl); -+ au_hbl_for_each(pos, hbl) -+ cnt++; -+ hlist_bl_unlock(hbl); -+ return cnt; -+} -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_HBL_H__ */ -diff -Nurp linux-5.10-rc6/fs/aufs/hfsnotify.c linux-5.10-rc6.aufs/fs/aufs/hfsnotify.c ---- linux-5.10-rc6/fs/aufs/hfsnotify.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/hfsnotify.c 2020-12-02 21:19:51.881036743 +0200 -@@ -0,0 +1,275 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * fsnotify for the lower directories -+ */ -+ -+#include "aufs.h" -+ -+/* FS_IN_IGNORED is unnecessary */ -+static const __u32 AuHfsnMask = (FS_MOVED_TO | FS_MOVED_FROM | FS_DELETE -+ | FS_CREATE | FS_EVENT_ON_CHILD); -+static DECLARE_WAIT_QUEUE_HEAD(au_hfsn_wq); -+static __cacheline_aligned_in_smp atomic64_t au_hfsn_ifree = ATOMIC64_INIT(0); -+ -+static void au_hfsn_free_mark(struct fsnotify_mark *mark) -+{ -+ struct au_hnotify *hn = container_of(mark, struct au_hnotify, -+ hn_mark); -+ /* AuDbg("here\n"); */ -+ au_cache_free_hnotify(hn); -+ smp_mb__before_atomic(); /* for atomic64_dec */ -+ if (atomic64_dec_and_test(&au_hfsn_ifree)) -+ wake_up(&au_hfsn_wq); -+} -+ -+static int au_hfsn_alloc(struct au_hinode *hinode) -+{ -+ int err; -+ struct au_hnotify *hn; -+ struct super_block *sb; -+ struct au_branch *br; -+ struct fsnotify_mark *mark; -+ aufs_bindex_t bindex; -+ -+ hn = hinode->hi_notify; -+ sb = hn->hn_aufs_inode->i_sb; -+ bindex = au_br_index(sb, hinode->hi_id); -+ br = au_sbr(sb, bindex); -+ AuDebugOn(!br->br_hfsn); -+ -+ mark = &hn->hn_mark; -+ fsnotify_init_mark(mark, br->br_hfsn->hfsn_group); -+ mark->mask = AuHfsnMask; -+ /* -+ * by udba rename or rmdir, aufs assign a new inode to the known -+ * h_inode, so specify 1 to allow dups. -+ */ -+ lockdep_off(); -+ err = fsnotify_add_inode_mark(mark, hinode->hi_inode, /*allow_dups*/1); -+ lockdep_on(); -+ -+ return err; -+} -+ -+static int au_hfsn_free(struct au_hinode *hinode, struct au_hnotify *hn) -+{ -+ struct fsnotify_mark *mark; -+ unsigned long long ull; -+ struct fsnotify_group *group; -+ -+ ull = atomic64_inc_return(&au_hfsn_ifree); -+ BUG_ON(!ull); -+ -+ mark = &hn->hn_mark; -+ spin_lock(&mark->lock); -+ group = mark->group; -+ fsnotify_get_group(group); -+ spin_unlock(&mark->lock); -+ lockdep_off(); -+ fsnotify_destroy_mark(mark, group); -+ fsnotify_put_mark(mark); -+ fsnotify_put_group(group); -+ lockdep_on(); -+ -+ /* free hn by myself */ -+ return 0; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static void au_hfsn_ctl(struct au_hinode *hinode, int do_set) -+{ -+ struct fsnotify_mark *mark; -+ -+ mark = &hinode->hi_notify->hn_mark; -+ spin_lock(&mark->lock); -+ if (do_set) { -+ AuDebugOn(mark->mask & AuHfsnMask); -+ mark->mask |= AuHfsnMask; -+ } else { -+ AuDebugOn(!(mark->mask & AuHfsnMask)); -+ mark->mask &= ~AuHfsnMask; -+ } -+ spin_unlock(&mark->lock); -+ /* fsnotify_recalc_inode_mask(hinode->hi_inode); */ -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* #define AuDbgHnotify */ -+#ifdef AuDbgHnotify -+static char *au_hfsn_name(u32 mask) -+{ -+#ifdef CONFIG_AUFS_DEBUG -+#define test_ret(flag) \ -+ do { \ -+ if (mask & flag) \ -+ return #flag; \ -+ } while (0) -+ test_ret(FS_ACCESS); -+ test_ret(FS_MODIFY); -+ test_ret(FS_ATTRIB); -+ test_ret(FS_CLOSE_WRITE); -+ test_ret(FS_CLOSE_NOWRITE); -+ test_ret(FS_OPEN); -+ test_ret(FS_MOVED_FROM); -+ test_ret(FS_MOVED_TO); -+ test_ret(FS_CREATE); -+ test_ret(FS_DELETE); -+ test_ret(FS_DELETE_SELF); -+ test_ret(FS_MOVE_SELF); -+ test_ret(FS_UNMOUNT); -+ test_ret(FS_Q_OVERFLOW); -+ test_ret(FS_IN_IGNORED); -+ test_ret(FS_ISDIR); -+ test_ret(FS_IN_ONESHOT); -+ test_ret(FS_EVENT_ON_CHILD); -+ return ""; -+#undef test_ret -+#else -+ return "??"; -+#endif -+} -+#endif -+ -+/* ---------------------------------------------------------------------- */ -+ -+static void au_hfsn_free_group(struct fsnotify_group *group) -+{ -+ struct au_br_hfsnotify *hfsn = group->private; -+ -+ /* AuDbg("here\n"); */ -+ au_kfree_try_rcu(hfsn); -+} -+ -+static int au_hfsn_handle_event(struct fsnotify_group *group, -+ struct inode *inode, -+ u32 mask, const void *data, int data_type, -+ const struct qstr *file_name, u32 cookie, -+ struct fsnotify_iter_info *iter_info) -+{ -+ int err; -+ struct au_hnotify *hnotify; -+ struct inode *h_dir, *h_inode; -+ struct fsnotify_mark *inode_mark; -+ -+ AuDebugOn(data_type != FSNOTIFY_EVENT_INODE); -+ -+ err = 0; -+ /* if FS_UNMOUNT happens, there must be another bug */ -+ AuDebugOn(mask & FS_UNMOUNT); -+ if (mask & (FS_IN_IGNORED | FS_UNMOUNT)) -+ goto out; -+ -+ h_dir = inode; -+ h_inode = NULL; -+#ifdef AuDbgHnotify -+ au_debug_on(); -+ if (1 || h_child_qstr.len != sizeof(AUFS_XINO_FNAME) - 1 -+ || strncmp(h_child_qstr.name, AUFS_XINO_FNAME, h_child_qstr.len)) { -+ AuDbg("i%lu, mask 0x%x %s, hcname %.*s, hi%lu\n", -+ h_dir->i_ino, mask, au_hfsn_name(mask), -+ AuLNPair(&h_child_qstr), h_inode ? h_inode->i_ino : 0); -+ /* WARN_ON(1); */ -+ } -+ au_debug_off(); -+#endif -+ -+ inode_mark = fsnotify_iter_inode_mark(iter_info); -+ AuDebugOn(!inode_mark); -+ hnotify = container_of(inode_mark, struct au_hnotify, hn_mark); -+ err = au_hnotify(h_dir, hnotify, mask, file_name, h_inode); -+ -+out: -+ return err; -+} -+ -+static struct fsnotify_ops au_hfsn_ops = { -+ .handle_event = au_hfsn_handle_event, -+ .free_group_priv = au_hfsn_free_group, -+ .free_mark = au_hfsn_free_mark -+}; -+ -+/* ---------------------------------------------------------------------- */ -+ -+static void au_hfsn_fin_br(struct au_branch *br) -+{ -+ struct au_br_hfsnotify *hfsn; -+ -+ hfsn = br->br_hfsn; -+ if (hfsn) { -+ lockdep_off(); -+ fsnotify_put_group(hfsn->hfsn_group); -+ lockdep_on(); -+ } -+} -+ -+static int au_hfsn_init_br(struct au_branch *br, int perm) -+{ -+ int err; -+ struct fsnotify_group *group; -+ struct au_br_hfsnotify *hfsn; -+ -+ err = 0; -+ br->br_hfsn = NULL; -+ if (!au_br_hnotifyable(perm)) -+ goto out; -+ -+ err = -ENOMEM; -+ hfsn = kmalloc(sizeof(*hfsn), GFP_NOFS); -+ if (unlikely(!hfsn)) -+ goto out; -+ -+ err = 0; -+ group = fsnotify_alloc_group(&au_hfsn_ops); -+ if (IS_ERR(group)) { -+ err = PTR_ERR(group); -+ pr_err("fsnotify_alloc_group() failed, %d\n", err); -+ goto out_hfsn; -+ } -+ -+ group->private = hfsn; -+ hfsn->hfsn_group = group; -+ br->br_hfsn = hfsn; -+ goto out; /* success */ -+ -+out_hfsn: -+ au_kfree_try_rcu(hfsn); -+out: -+ return err; -+} -+ -+static int au_hfsn_reset_br(unsigned int udba, struct au_branch *br, int perm) -+{ -+ int err; -+ -+ err = 0; -+ if (!br->br_hfsn) -+ err = au_hfsn_init_br(br, perm); -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static void au_hfsn_fin(void) -+{ -+ AuDbg("au_hfsn_ifree %lld\n", (long long)atomic64_read(&au_hfsn_ifree)); -+ wait_event(au_hfsn_wq, !atomic64_read(&au_hfsn_ifree)); -+} -+ -+const struct au_hnotify_op au_hnotify_op = { -+ .ctl = au_hfsn_ctl, -+ .alloc = au_hfsn_alloc, -+ .free = au_hfsn_free, -+ -+ .fin = au_hfsn_fin, -+ -+ .reset_br = au_hfsn_reset_br, -+ .fin_br = au_hfsn_fin_br, -+ .init_br = au_hfsn_init_br -+}; -diff -Nurp linux-5.10-rc6/fs/aufs/hfsplus.c linux-5.10-rc6.aufs/fs/aufs/hfsplus.c ---- linux-5.10-rc6/fs/aufs/hfsplus.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/hfsplus.c 2020-12-02 21:19:51.881036743 +0200 -@@ -0,0 +1,47 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2010-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * special support for filesystems which acquires an inode mutex -+ * at final closing a file, eg, hfsplus. -+ * -+ * This trick is very simple and stupid, just to open the file before really -+ * necessary open to tell hfsplus that this is not the final closing. -+ * The caller should call au_h_open_pre() after acquiring the inode mutex, -+ * and au_h_open_post() after releasing it. -+ */ -+ -+#include "aufs.h" -+ -+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex, -+ int force_wr) -+{ -+ struct file *h_file; -+ struct dentry *h_dentry; -+ -+ h_dentry = au_h_dptr(dentry, bindex); -+ AuDebugOn(!h_dentry); -+ AuDebugOn(d_is_negative(h_dentry)); -+ -+ h_file = NULL; -+ if (au_test_hfsplus(h_dentry->d_sb) -+ && d_is_reg(h_dentry)) -+ h_file = au_h_open(dentry, bindex, -+ O_RDONLY | O_NOATIME | O_LARGEFILE, -+ /*file*/NULL, force_wr); -+ return h_file; -+} -+ -+void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex, -+ struct file *h_file) -+{ -+ struct au_branch *br; -+ -+ if (h_file) { -+ fput(h_file); -+ br = au_sbr(dentry->d_sb, bindex); -+ au_lcnt_dec(&br->br_nfiles); -+ } -+} -diff -Nurp linux-5.10-rc6/fs/aufs/hnotify.c linux-5.10-rc6.aufs/fs/aufs/hnotify.c ---- linux-5.10-rc6/fs/aufs/hnotify.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/hnotify.c 2020-12-02 21:19:51.882036788 +0200 -@@ -0,0 +1,702 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * abstraction to notify the direct changes on lower directories -+ */ -+ -+/* #include */ -+#include "aufs.h" -+ -+int au_hn_alloc(struct au_hinode *hinode, struct inode *inode) -+{ -+ int err; -+ struct au_hnotify *hn; -+ -+ err = -ENOMEM; -+ hn = au_cache_alloc_hnotify(); -+ if (hn) { -+ hn->hn_aufs_inode = inode; -+ hinode->hi_notify = hn; -+ err = au_hnotify_op.alloc(hinode); -+ AuTraceErr(err); -+ if (unlikely(err)) { -+ hinode->hi_notify = NULL; -+ au_cache_free_hnotify(hn); -+ /* -+ * The upper dir was removed by udba, but the same named -+ * dir left. In this case, aufs assigns a new inode -+ * number and set the monitor again. -+ * For the lower dir, the old monitor is still left. -+ */ -+ if (err == -EEXIST) -+ err = 0; -+ } -+ } -+ -+ AuTraceErr(err); -+ return err; -+} -+ -+void au_hn_free(struct au_hinode *hinode) -+{ -+ struct au_hnotify *hn; -+ -+ hn = hinode->hi_notify; -+ if (hn) { -+ hinode->hi_notify = NULL; -+ if (au_hnotify_op.free(hinode, hn)) -+ au_cache_free_hnotify(hn); -+ } -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+void au_hn_ctl(struct au_hinode *hinode, int do_set) -+{ -+ if (hinode->hi_notify) -+ au_hnotify_op.ctl(hinode, do_set); -+} -+ -+void au_hn_reset(struct inode *inode, unsigned int flags) -+{ -+ aufs_bindex_t bindex, bbot; -+ struct inode *hi; -+ struct dentry *iwhdentry; -+ -+ bbot = au_ibbot(inode); -+ for (bindex = au_ibtop(inode); bindex <= bbot; bindex++) { -+ hi = au_h_iptr(inode, bindex); -+ if (!hi) -+ continue; -+ -+ /* inode_lock_nested(hi, AuLsc_I_CHILD); */ -+ iwhdentry = au_hi_wh(inode, bindex); -+ if (iwhdentry) -+ dget(iwhdentry); -+ au_igrab(hi); -+ au_set_h_iptr(inode, bindex, NULL, 0); -+ au_set_h_iptr(inode, bindex, au_igrab(hi), -+ flags & ~AuHi_XINO); -+ iput(hi); -+ dput(iwhdentry); -+ /* inode_unlock(hi); */ -+ } -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int hn_xino(struct inode *inode, struct inode *h_inode) -+{ -+ int err; -+ aufs_bindex_t bindex, bbot, bfound, btop; -+ struct inode *h_i; -+ -+ err = 0; -+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) { -+ pr_warn("branch root dir was changed\n"); -+ goto out; -+ } -+ -+ bfound = -1; -+ bbot = au_ibbot(inode); -+ btop = au_ibtop(inode); -+#if 0 /* reserved for future use */ -+ if (bindex == bbot) { -+ /* keep this ino in rename case */ -+ goto out; -+ } -+#endif -+ for (bindex = btop; bindex <= bbot; bindex++) -+ if (au_h_iptr(inode, bindex) == h_inode) { -+ bfound = bindex; -+ break; -+ } -+ if (bfound < 0) -+ goto out; -+ -+ for (bindex = btop; bindex <= bbot; bindex++) { -+ h_i = au_h_iptr(inode, bindex); -+ if (!h_i) -+ continue; -+ -+ err = au_xino_write(inode->i_sb, bindex, h_i->i_ino, /*ino*/0); -+ /* ignore this error */ -+ /* bad action? */ -+ } -+ -+ /* children inode number will be broken */ -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+static int hn_gen_tree(struct dentry *dentry) -+{ -+ int err, i, j, ndentry; -+ struct au_dcsub_pages dpages; -+ struct au_dpage *dpage; -+ struct dentry **dentries; -+ -+ err = au_dpages_init(&dpages, GFP_NOFS); -+ if (unlikely(err)) -+ goto out; -+ err = au_dcsub_pages(&dpages, dentry, NULL, NULL); -+ if (unlikely(err)) -+ goto out_dpages; -+ -+ for (i = 0; i < dpages.ndpage; i++) { -+ dpage = dpages.dpages + i; -+ dentries = dpage->dentries; -+ ndentry = dpage->ndentry; -+ for (j = 0; j < ndentry; j++) { -+ struct dentry *d; -+ -+ d = dentries[j]; -+ if (IS_ROOT(d)) -+ continue; -+ -+ au_digen_dec(d); -+ if (d_really_is_positive(d)) -+ /* todo: reset children xino? -+ cached children only? */ -+ au_iigen_dec(d_inode(d)); -+ } -+ } -+ -+out_dpages: -+ au_dpages_free(&dpages); -+out: -+ return err; -+} -+ -+/* -+ * return 0 if processed. -+ */ -+static int hn_gen_by_inode(char *name, unsigned int nlen, struct inode *inode, -+ const unsigned int isdir) -+{ -+ int err; -+ struct dentry *d; -+ struct qstr *dname; -+ -+ err = 1; -+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) { -+ pr_warn("branch root dir was changed\n"); -+ err = 0; -+ goto out; -+ } -+ -+ if (!isdir) { -+ AuDebugOn(!name); -+ au_iigen_dec(inode); -+ spin_lock(&inode->i_lock); -+ hlist_for_each_entry(d, &inode->i_dentry, d_u.d_alias) { -+ spin_lock(&d->d_lock); -+ dname = &d->d_name; -+ if (dname->len != nlen -+ && memcmp(dname->name, name, nlen)) { -+ spin_unlock(&d->d_lock); -+ continue; -+ } -+ err = 0; -+ au_digen_dec(d); -+ spin_unlock(&d->d_lock); -+ break; -+ } -+ spin_unlock(&inode->i_lock); -+ } else { -+ au_fset_si(au_sbi(inode->i_sb), FAILED_REFRESH_DIR); -+ d = d_find_any_alias(inode); -+ if (!d) { -+ au_iigen_dec(inode); -+ goto out; -+ } -+ -+ spin_lock(&d->d_lock); -+ dname = &d->d_name; -+ if (dname->len == nlen && !memcmp(dname->name, name, nlen)) { -+ spin_unlock(&d->d_lock); -+ err = hn_gen_tree(d); -+ spin_lock(&d->d_lock); -+ } -+ spin_unlock(&d->d_lock); -+ dput(d); -+ } -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+static int hn_gen_by_name(struct dentry *dentry, const unsigned int isdir) -+{ -+ int err; -+ -+ if (IS_ROOT(dentry)) { -+ pr_warn("branch root dir was changed\n"); -+ return 0; -+ } -+ -+ err = 0; -+ if (!isdir) { -+ au_digen_dec(dentry); -+ if (d_really_is_positive(dentry)) -+ au_iigen_dec(d_inode(dentry)); -+ } else { -+ au_fset_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIR); -+ if (d_really_is_positive(dentry)) -+ err = hn_gen_tree(dentry); -+ } -+ -+ AuTraceErr(err); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* hnotify job flags */ -+#define AuHnJob_XINO0 1 -+#define AuHnJob_GEN (1 << 1) -+#define AuHnJob_DIRENT (1 << 2) -+#define AuHnJob_ISDIR (1 << 3) -+#define AuHnJob_TRYXINO0 (1 << 4) -+#define AuHnJob_MNTPNT (1 << 5) -+#define au_ftest_hnjob(flags, name) ((flags) & AuHnJob_##name) -+#define au_fset_hnjob(flags, name) \ -+ do { (flags) |= AuHnJob_##name; } while (0) -+#define au_fclr_hnjob(flags, name) \ -+ do { (flags) &= ~AuHnJob_##name; } while (0) -+ -+enum { -+ AuHn_CHILD, -+ AuHn_PARENT, -+ AuHnLast -+}; -+ -+struct au_hnotify_args { -+ struct inode *h_dir, *dir, *h_child_inode; -+ u32 mask; -+ unsigned int flags[AuHnLast]; -+ unsigned int h_child_nlen; -+ char h_child_name[]; -+}; -+ -+struct hn_job_args { -+ unsigned int flags; -+ struct inode *inode, *h_inode, *dir, *h_dir; -+ struct dentry *dentry; -+ char *h_name; -+ int h_nlen; -+}; -+ -+static int hn_job(struct hn_job_args *a) -+{ -+ const unsigned int isdir = au_ftest_hnjob(a->flags, ISDIR); -+ int e; -+ -+ /* reset xino */ -+ if (au_ftest_hnjob(a->flags, XINO0) && a->inode) -+ hn_xino(a->inode, a->h_inode); /* ignore this error */ -+ -+ if (au_ftest_hnjob(a->flags, TRYXINO0) -+ && a->inode -+ && a->h_inode) { -+ inode_lock_shared_nested(a->h_inode, AuLsc_I_CHILD); -+ if (!a->h_inode->i_nlink -+ && !(a->h_inode->i_state & I_LINKABLE)) -+ hn_xino(a->inode, a->h_inode); /* ignore this error */ -+ inode_unlock_shared(a->h_inode); -+ } -+ -+ /* make the generation obsolete */ -+ if (au_ftest_hnjob(a->flags, GEN)) { -+ e = -1; -+ if (a->inode) -+ e = hn_gen_by_inode(a->h_name, a->h_nlen, a->inode, -+ isdir); -+ if (e && a->dentry) -+ hn_gen_by_name(a->dentry, isdir); -+ /* ignore this error */ -+ } -+ -+ /* make dir entries obsolete */ -+ if (au_ftest_hnjob(a->flags, DIRENT) && a->inode) { -+ struct au_vdir *vdir; -+ -+ vdir = au_ivdir(a->inode); -+ if (vdir) -+ vdir->vd_jiffy = 0; -+ /* IMustLock(a->inode); */ -+ /* inode_inc_iversion(a->inode); */ -+ } -+ -+ /* can do nothing but warn */ -+ if (au_ftest_hnjob(a->flags, MNTPNT) -+ && a->dentry -+ && d_mountpoint(a->dentry)) -+ pr_warn("mount-point %pd is removed or renamed\n", a->dentry); -+ -+ return 0; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static struct dentry *lookup_wlock_by_name(char *name, unsigned int nlen, -+ struct inode *dir) -+{ -+ struct dentry *dentry, *d, *parent; -+ struct qstr *dname; -+ -+ parent = d_find_any_alias(dir); -+ if (!parent) -+ return NULL; -+ -+ dentry = NULL; -+ spin_lock(&parent->d_lock); -+ list_for_each_entry(d, &parent->d_subdirs, d_child) { -+ /* AuDbg("%pd\n", d); */ -+ spin_lock_nested(&d->d_lock, DENTRY_D_LOCK_NESTED); -+ dname = &d->d_name; -+ if (dname->len != nlen || memcmp(dname->name, name, nlen)) -+ goto cont_unlock; -+ if (au_di(d)) -+ au_digen_dec(d); -+ else -+ goto cont_unlock; -+ if (au_dcount(d) > 0) { -+ dentry = dget_dlock(d); -+ spin_unlock(&d->d_lock); -+ break; -+ } -+ -+cont_unlock: -+ spin_unlock(&d->d_lock); -+ } -+ spin_unlock(&parent->d_lock); -+ dput(parent); -+ -+ if (dentry) -+ di_write_lock_child(dentry); -+ -+ return dentry; -+} -+ -+static struct inode *lookup_wlock_by_ino(struct super_block *sb, -+ aufs_bindex_t bindex, ino_t h_ino) -+{ -+ struct inode *inode; -+ ino_t ino; -+ int err; -+ -+ inode = NULL; -+ err = au_xino_read(sb, bindex, h_ino, &ino); -+ if (!err && ino) -+ inode = ilookup(sb, ino); -+ if (!inode) -+ goto out; -+ -+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) { -+ pr_warn("wrong root branch\n"); -+ iput(inode); -+ inode = NULL; -+ goto out; -+ } -+ -+ ii_write_lock_child(inode); -+ -+out: -+ return inode; -+} -+ -+static void au_hn_bh(void *_args) -+{ -+ struct au_hnotify_args *a = _args; -+ struct super_block *sb; -+ aufs_bindex_t bindex, bbot, bfound; -+ unsigned char xino, try_iput; -+ int err; -+ struct inode *inode; -+ ino_t h_ino; -+ struct hn_job_args args; -+ struct dentry *dentry; -+ struct au_sbinfo *sbinfo; -+ -+ AuDebugOn(!_args); -+ AuDebugOn(!a->h_dir); -+ AuDebugOn(!a->dir); -+ AuDebugOn(!a->mask); -+ AuDbg("mask 0x%x, i%lu, hi%lu, hci%lu\n", -+ a->mask, a->dir->i_ino, a->h_dir->i_ino, -+ a->h_child_inode ? a->h_child_inode->i_ino : 0); -+ -+ inode = NULL; -+ dentry = NULL; -+ /* -+ * do not lock a->dir->i_mutex here -+ * because of d_revalidate() may cause a deadlock. -+ */ -+ sb = a->dir->i_sb; -+ AuDebugOn(!sb); -+ sbinfo = au_sbi(sb); -+ AuDebugOn(!sbinfo); -+ si_write_lock(sb, AuLock_NOPLMW); -+ -+ if (au_opt_test(sbinfo->si_mntflags, DIRREN)) -+ switch (a->mask & FS_EVENTS_POSS_ON_CHILD) { -+ case FS_MOVED_FROM: -+ case FS_MOVED_TO: -+ AuWarn1("DIRREN with UDBA may not work correctly " -+ "for the direct rename(2)\n"); -+ } -+ -+ ii_read_lock_parent(a->dir); -+ bfound = -1; -+ bbot = au_ibbot(a->dir); -+ for (bindex = au_ibtop(a->dir); bindex <= bbot; bindex++) -+ if (au_h_iptr(a->dir, bindex) == a->h_dir) { -+ bfound = bindex; -+ break; -+ } -+ ii_read_unlock(a->dir); -+ if (unlikely(bfound < 0)) -+ goto out; -+ -+ xino = !!au_opt_test(au_mntflags(sb), XINO); -+ h_ino = 0; -+ if (a->h_child_inode) -+ h_ino = a->h_child_inode->i_ino; -+ -+ if (a->h_child_nlen -+ && (au_ftest_hnjob(a->flags[AuHn_CHILD], GEN) -+ || au_ftest_hnjob(a->flags[AuHn_CHILD], MNTPNT))) -+ dentry = lookup_wlock_by_name(a->h_child_name, a->h_child_nlen, -+ a->dir); -+ try_iput = 0; -+ if (dentry && d_really_is_positive(dentry)) -+ inode = d_inode(dentry); -+ if (xino && !inode && h_ino -+ && (au_ftest_hnjob(a->flags[AuHn_CHILD], XINO0) -+ || au_ftest_hnjob(a->flags[AuHn_CHILD], TRYXINO0) -+ || au_ftest_hnjob(a->flags[AuHn_CHILD], GEN))) { -+ inode = lookup_wlock_by_ino(sb, bfound, h_ino); -+ try_iput = 1; -+ } -+ -+ args.flags = a->flags[AuHn_CHILD]; -+ args.dentry = dentry; -+ args.inode = inode; -+ args.h_inode = a->h_child_inode; -+ args.dir = a->dir; -+ args.h_dir = a->h_dir; -+ args.h_name = a->h_child_name; -+ args.h_nlen = a->h_child_nlen; -+ err = hn_job(&args); -+ if (dentry) { -+ if (au_di(dentry)) -+ di_write_unlock(dentry); -+ dput(dentry); -+ } -+ if (inode && try_iput) { -+ ii_write_unlock(inode); -+ iput(inode); -+ } -+ -+ ii_write_lock_parent(a->dir); -+ args.flags = a->flags[AuHn_PARENT]; -+ args.dentry = NULL; -+ args.inode = a->dir; -+ args.h_inode = a->h_dir; -+ args.dir = NULL; -+ args.h_dir = NULL; -+ args.h_name = NULL; -+ args.h_nlen = 0; -+ err = hn_job(&args); -+ ii_write_unlock(a->dir); -+ -+out: -+ iput(a->h_child_inode); -+ iput(a->h_dir); -+ iput(a->dir); -+ si_write_unlock(sb); -+ au_nwt_done(&sbinfo->si_nowait); -+ au_kfree_rcu(a); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+int au_hnotify(struct inode *h_dir, struct au_hnotify *hnotify, u32 mask, -+ const struct qstr *h_child_qstr, struct inode *h_child_inode) -+{ -+ int err, len; -+ unsigned int flags[AuHnLast], f; -+ unsigned char isdir, isroot, wh; -+ struct inode *dir; -+ struct au_hnotify_args *args; -+ char *p, *h_child_name; -+ -+ err = 0; -+ AuDebugOn(!hnotify || !hnotify->hn_aufs_inode); -+ dir = igrab(hnotify->hn_aufs_inode); -+ if (!dir) -+ goto out; -+ -+ isroot = (dir->i_ino == AUFS_ROOT_INO); -+ wh = 0; -+ h_child_name = (void *)h_child_qstr->name; -+ len = h_child_qstr->len; -+ if (h_child_name) { -+ if (len > AUFS_WH_PFX_LEN -+ && !memcmp(h_child_name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) { -+ h_child_name += AUFS_WH_PFX_LEN; -+ len -= AUFS_WH_PFX_LEN; -+ wh = 1; -+ } -+ } -+ -+ isdir = 0; -+ if (h_child_inode) -+ isdir = !!S_ISDIR(h_child_inode->i_mode); -+ flags[AuHn_PARENT] = AuHnJob_ISDIR; -+ flags[AuHn_CHILD] = 0; -+ if (isdir) -+ flags[AuHn_CHILD] = AuHnJob_ISDIR; -+ au_fset_hnjob(flags[AuHn_PARENT], DIRENT); -+ au_fset_hnjob(flags[AuHn_CHILD], GEN); -+ switch (mask & ALL_FSNOTIFY_DIRENT_EVENTS) { -+ case FS_MOVED_FROM: -+ case FS_MOVED_TO: -+ au_fset_hnjob(flags[AuHn_CHILD], XINO0); -+ au_fset_hnjob(flags[AuHn_CHILD], MNTPNT); -+ /*FALLTHROUGH*/ -+ case FS_CREATE: -+ AuDebugOn(!h_child_name); -+ break; -+ -+ case FS_DELETE: -+ /* -+ * aufs never be able to get this child inode. -+ * revalidation should be in d_revalidate() -+ * by checking i_nlink, i_generation or d_unhashed(). -+ */ -+ AuDebugOn(!h_child_name); -+ au_fset_hnjob(flags[AuHn_CHILD], TRYXINO0); -+ au_fset_hnjob(flags[AuHn_CHILD], MNTPNT); -+ break; -+ -+ default: -+ AuDebugOn(1); -+ } -+ -+ if (wh) -+ h_child_inode = NULL; -+ -+ err = -ENOMEM; -+ /* iput() and kfree() will be called in au_hnotify() */ -+ args = kmalloc(sizeof(*args) + len + 1, GFP_NOFS); -+ if (unlikely(!args)) { -+ AuErr1("no memory\n"); -+ iput(dir); -+ goto out; -+ } -+ args->flags[AuHn_PARENT] = flags[AuHn_PARENT]; -+ args->flags[AuHn_CHILD] = flags[AuHn_CHILD]; -+ args->mask = mask; -+ args->dir = dir; -+ args->h_dir = igrab(h_dir); -+ if (h_child_inode) -+ h_child_inode = igrab(h_child_inode); /* can be NULL */ -+ args->h_child_inode = h_child_inode; -+ args->h_child_nlen = len; -+ if (len) { -+ p = (void *)args; -+ p += sizeof(*args); -+ memcpy(p, h_child_name, len); -+ p[len] = 0; -+ } -+ -+ /* NFS fires the event for silly-renamed one from kworker */ -+ f = 0; -+ if (!dir->i_nlink -+ || (au_test_nfs(h_dir->i_sb) && (mask & FS_DELETE))) -+ f = AuWkq_NEST; -+ err = au_wkq_nowait(au_hn_bh, args, dir->i_sb, f); -+ if (unlikely(err)) { -+ pr_err("wkq %d\n", err); -+ iput(args->h_child_inode); -+ iput(args->h_dir); -+ iput(args->dir); -+ au_kfree_rcu(args); -+ } -+ -+out: -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+int au_hnotify_reset_br(unsigned int udba, struct au_branch *br, int perm) -+{ -+ int err; -+ -+ AuDebugOn(!(udba & AuOptMask_UDBA)); -+ -+ err = 0; -+ if (au_hnotify_op.reset_br) -+ err = au_hnotify_op.reset_br(udba, br, perm); -+ -+ return err; -+} -+ -+int au_hnotify_init_br(struct au_branch *br, int perm) -+{ -+ int err; -+ -+ err = 0; -+ if (au_hnotify_op.init_br) -+ err = au_hnotify_op.init_br(br, perm); -+ -+ return err; -+} -+ -+void au_hnotify_fin_br(struct au_branch *br) -+{ -+ if (au_hnotify_op.fin_br) -+ au_hnotify_op.fin_br(br); -+} -+ -+static void au_hn_destroy_cache(void) -+{ -+ kmem_cache_destroy(au_cache[AuCache_HNOTIFY]); -+ au_cache[AuCache_HNOTIFY] = NULL; -+} -+ -+int __init au_hnotify_init(void) -+{ -+ int err; -+ -+ err = -ENOMEM; -+ au_cache[AuCache_HNOTIFY] = AuCache(au_hnotify); -+ if (au_cache[AuCache_HNOTIFY]) { -+ err = 0; -+ if (au_hnotify_op.init) -+ err = au_hnotify_op.init(); -+ if (unlikely(err)) -+ au_hn_destroy_cache(); -+ } -+ AuTraceErr(err); -+ return err; -+} -+ -+void au_hnotify_fin(void) -+{ -+ if (au_hnotify_op.fin) -+ au_hnotify_op.fin(); -+ -+ /* cf. au_cache_fin() */ -+ if (au_cache[AuCache_HNOTIFY]) -+ au_hn_destroy_cache(); -+} -diff -Nurp linux-5.10-rc6/fs/aufs/iinfo.c linux-5.10-rc6.aufs/fs/aufs/iinfo.c ---- linux-5.10-rc6/fs/aufs/iinfo.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/iinfo.c 2020-12-02 21:19:51.882036788 +0200 -@@ -0,0 +1,273 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * inode private data -+ */ -+ -+#include "aufs.h" -+ -+struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex) -+{ -+ struct inode *h_inode; -+ struct au_hinode *hinode; -+ -+ IiMustAnyLock(inode); -+ -+ hinode = au_hinode(au_ii(inode), bindex); -+ h_inode = hinode->hi_inode; -+ AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0); -+ return h_inode; -+} -+ -+/* todo: hard/soft set? */ -+void au_hiput(struct au_hinode *hinode) -+{ -+ au_hn_free(hinode); -+ dput(hinode->hi_whdentry); -+ iput(hinode->hi_inode); -+} -+ -+unsigned int au_hi_flags(struct inode *inode, int isdir) -+{ -+ unsigned int flags; -+ const unsigned int mnt_flags = au_mntflags(inode->i_sb); -+ -+ flags = 0; -+ if (au_opt_test(mnt_flags, XINO)) -+ au_fset_hi(flags, XINO); -+ if (isdir && au_opt_test(mnt_flags, UDBA_HNOTIFY)) -+ au_fset_hi(flags, HNOTIFY); -+ return flags; -+} -+ -+void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex, -+ struct inode *h_inode, unsigned int flags) -+{ -+ struct au_hinode *hinode; -+ struct inode *hi; -+ struct au_iinfo *iinfo = au_ii(inode); -+ -+ IiMustWriteLock(inode); -+ -+ hinode = au_hinode(iinfo, bindex); -+ hi = hinode->hi_inode; -+ AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0); -+ -+ if (hi) -+ au_hiput(hinode); -+ hinode->hi_inode = h_inode; -+ if (h_inode) { -+ int err; -+ struct super_block *sb = inode->i_sb; -+ struct au_branch *br; -+ -+ AuDebugOn(inode->i_mode -+ && (h_inode->i_mode & S_IFMT) -+ != (inode->i_mode & S_IFMT)); -+ if (bindex == iinfo->ii_btop) -+ au_cpup_igen(inode, h_inode); -+ br = au_sbr(sb, bindex); -+ hinode->hi_id = br->br_id; -+ if (au_ftest_hi(flags, XINO)) { -+ err = au_xino_write(sb, bindex, h_inode->i_ino, -+ inode->i_ino); -+ if (unlikely(err)) -+ AuIOErr1("failed au_xino_write() %d\n", err); -+ } -+ -+ if (au_ftest_hi(flags, HNOTIFY) -+ && au_br_hnotifyable(br->br_perm)) { -+ err = au_hn_alloc(hinode, inode); -+ if (unlikely(err)) -+ AuIOErr1("au_hn_alloc() %d\n", err); -+ } -+ } -+} -+ -+void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex, -+ struct dentry *h_wh) -+{ -+ struct au_hinode *hinode; -+ -+ IiMustWriteLock(inode); -+ -+ hinode = au_hinode(au_ii(inode), bindex); -+ AuDebugOn(hinode->hi_whdentry); -+ hinode->hi_whdentry = h_wh; -+} -+ -+void au_update_iigen(struct inode *inode, int half) -+{ -+ struct au_iinfo *iinfo; -+ struct au_iigen *iigen; -+ unsigned int sigen; -+ -+ sigen = au_sigen(inode->i_sb); -+ iinfo = au_ii(inode); -+ iigen = &iinfo->ii_generation; -+ spin_lock(&iigen->ig_spin); -+ iigen->ig_generation = sigen; -+ if (half) -+ au_ig_fset(iigen->ig_flags, HALF_REFRESHED); -+ else -+ au_ig_fclr(iigen->ig_flags, HALF_REFRESHED); -+ spin_unlock(&iigen->ig_spin); -+} -+ -+/* it may be called at remount time, too */ -+void au_update_ibrange(struct inode *inode, int do_put_zero) -+{ -+ struct au_iinfo *iinfo; -+ aufs_bindex_t bindex, bbot; -+ -+ AuDebugOn(au_is_bad_inode(inode)); -+ IiMustWriteLock(inode); -+ -+ iinfo = au_ii(inode); -+ if (do_put_zero && iinfo->ii_btop >= 0) { -+ for (bindex = iinfo->ii_btop; bindex <= iinfo->ii_bbot; -+ bindex++) { -+ struct inode *h_i; -+ -+ h_i = au_hinode(iinfo, bindex)->hi_inode; -+ if (h_i -+ && !h_i->i_nlink -+ && !(h_i->i_state & I_LINKABLE)) -+ au_set_h_iptr(inode, bindex, NULL, 0); -+ } -+ } -+ -+ iinfo->ii_btop = -1; -+ iinfo->ii_bbot = -1; -+ bbot = au_sbbot(inode->i_sb); -+ for (bindex = 0; bindex <= bbot; bindex++) -+ if (au_hinode(iinfo, bindex)->hi_inode) { -+ iinfo->ii_btop = bindex; -+ break; -+ } -+ if (iinfo->ii_btop >= 0) -+ for (bindex = bbot; bindex >= iinfo->ii_btop; bindex--) -+ if (au_hinode(iinfo, bindex)->hi_inode) { -+ iinfo->ii_bbot = bindex; -+ break; -+ } -+ AuDebugOn(iinfo->ii_btop > iinfo->ii_bbot); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+void au_icntnr_init_once(void *_c) -+{ -+ struct au_icntnr *c = _c; -+ struct au_iinfo *iinfo = &c->iinfo; -+ -+ spin_lock_init(&iinfo->ii_generation.ig_spin); -+ au_rw_init(&iinfo->ii_rwsem); -+ inode_init_once(&c->vfs_inode); -+} -+ -+void au_hinode_init(struct au_hinode *hinode) -+{ -+ hinode->hi_inode = NULL; -+ hinode->hi_id = -1; -+ au_hn_init(hinode); -+ hinode->hi_whdentry = NULL; -+} -+ -+int au_iinfo_init(struct inode *inode) -+{ -+ struct au_iinfo *iinfo; -+ struct super_block *sb; -+ struct au_hinode *hi; -+ int nbr, i; -+ -+ sb = inode->i_sb; -+ iinfo = &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo); -+ nbr = au_sbbot(sb) + 1; -+ if (unlikely(nbr <= 0)) -+ nbr = 1; -+ hi = kmalloc_array(nbr, sizeof(*iinfo->ii_hinode), GFP_NOFS); -+ if (hi) { -+ au_lcnt_inc(&au_sbi(sb)->si_ninodes); -+ -+ iinfo->ii_hinode = hi; -+ for (i = 0; i < nbr; i++, hi++) -+ au_hinode_init(hi); -+ -+ iinfo->ii_generation.ig_generation = au_sigen(sb); -+ iinfo->ii_btop = -1; -+ iinfo->ii_bbot = -1; -+ iinfo->ii_vdir = NULL; -+ return 0; -+ } -+ return -ENOMEM; -+} -+ -+int au_hinode_realloc(struct au_iinfo *iinfo, int nbr, int may_shrink) -+{ -+ int err, i; -+ struct au_hinode *hip; -+ -+ AuRwMustWriteLock(&iinfo->ii_rwsem); -+ -+ err = -ENOMEM; -+ hip = au_krealloc(iinfo->ii_hinode, sizeof(*hip) * nbr, GFP_NOFS, -+ may_shrink); -+ if (hip) { -+ iinfo->ii_hinode = hip; -+ i = iinfo->ii_bbot + 1; -+ hip += i; -+ for (; i < nbr; i++, hip++) -+ au_hinode_init(hip); -+ err = 0; -+ } -+ -+ return err; -+} -+ -+void au_iinfo_fin(struct inode *inode) -+{ -+ struct au_iinfo *iinfo; -+ struct au_hinode *hi; -+ struct super_block *sb; -+ aufs_bindex_t bindex, bbot; -+ const unsigned char unlinked = !inode->i_nlink; -+ -+ AuDebugOn(au_is_bad_inode(inode)); -+ -+ sb = inode->i_sb; -+ au_lcnt_dec(&au_sbi(sb)->si_ninodes); -+ if (si_pid_test(sb)) -+ au_xino_delete_inode(inode, unlinked); -+ else { -+ /* -+ * it is safe to hide the dependency between sbinfo and -+ * sb->s_umount. -+ */ -+ lockdep_off(); -+ si_noflush_read_lock(sb); -+ au_xino_delete_inode(inode, unlinked); -+ si_read_unlock(sb); -+ lockdep_on(); -+ } -+ -+ iinfo = au_ii(inode); -+ if (iinfo->ii_vdir) -+ au_vdir_free(iinfo->ii_vdir); -+ -+ bindex = iinfo->ii_btop; -+ if (bindex >= 0) { -+ hi = au_hinode(iinfo, bindex); -+ bbot = iinfo->ii_bbot; -+ while (bindex++ <= bbot) { -+ if (hi->hi_inode) -+ au_hiput(hi); -+ hi++; -+ } -+ } -+ au_kfree_rcu(iinfo->ii_hinode); -+ AuRwDestroy(&iinfo->ii_rwsem); -+} -diff -Nurp linux-5.10-rc6/fs/aufs/inode.c linux-5.10-rc6.aufs/fs/aufs/inode.c ---- linux-5.10-rc6/fs/aufs/inode.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/inode.c 2020-12-02 21:19:51.882036788 +0200 -@@ -0,0 +1,516 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * inode functions -+ */ -+ -+#include -+#include "aufs.h" -+ -+struct inode *au_igrab(struct inode *inode) -+{ -+ if (inode) { -+ AuDebugOn(!atomic_read(&inode->i_count)); -+ ihold(inode); -+ } -+ return inode; -+} -+ -+static void au_refresh_hinode_attr(struct inode *inode, int do_version) -+{ -+ au_cpup_attr_all(inode, /*force*/0); -+ au_update_iigen(inode, /*half*/1); -+ if (do_version) -+ inode_inc_iversion(inode); -+} -+ -+static int au_ii_refresh(struct inode *inode, int *update) -+{ -+ int err, e, nbr; -+ umode_t type; -+ aufs_bindex_t bindex, new_bindex; -+ struct super_block *sb; -+ struct au_iinfo *iinfo; -+ struct au_hinode *p, *q, tmp; -+ -+ AuDebugOn(au_is_bad_inode(inode)); -+ IiMustWriteLock(inode); -+ -+ *update = 0; -+ sb = inode->i_sb; -+ nbr = au_sbbot(sb) + 1; -+ type = inode->i_mode & S_IFMT; -+ iinfo = au_ii(inode); -+ err = au_hinode_realloc(iinfo, nbr, /*may_shrink*/0); -+ if (unlikely(err)) -+ goto out; -+ -+ AuDebugOn(iinfo->ii_btop < 0); -+ p = au_hinode(iinfo, iinfo->ii_btop); -+ for (bindex = iinfo->ii_btop; bindex <= iinfo->ii_bbot; -+ bindex++, p++) { -+ if (!p->hi_inode) -+ continue; -+ -+ AuDebugOn(type != (p->hi_inode->i_mode & S_IFMT)); -+ new_bindex = au_br_index(sb, p->hi_id); -+ if (new_bindex == bindex) -+ continue; -+ -+ if (new_bindex < 0) { -+ *update = 1; -+ au_hiput(p); -+ p->hi_inode = NULL; -+ continue; -+ } -+ -+ if (new_bindex < iinfo->ii_btop) -+ iinfo->ii_btop = new_bindex; -+ if (iinfo->ii_bbot < new_bindex) -+ iinfo->ii_bbot = new_bindex; -+ /* swap two lower inode, and loop again */ -+ q = au_hinode(iinfo, new_bindex); -+ tmp = *q; -+ *q = *p; -+ *p = tmp; -+ if (tmp.hi_inode) { -+ bindex--; -+ p--; -+ } -+ } -+ au_update_ibrange(inode, /*do_put_zero*/0); -+ au_hinode_realloc(iinfo, nbr, /*may_shrink*/1); /* harmless if err */ -+ e = au_dy_irefresh(inode); -+ if (unlikely(e && !err)) -+ err = e; -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+void au_refresh_iop(struct inode *inode, int force_getattr) -+{ -+ int type; -+ struct au_sbinfo *sbi = au_sbi(inode->i_sb); -+ const struct inode_operations *iop -+ = force_getattr ? aufs_iop : sbi->si_iop_array; -+ -+ if (inode->i_op == iop) -+ return; -+ -+ switch (inode->i_mode & S_IFMT) { -+ case S_IFDIR: -+ type = AuIop_DIR; -+ break; -+ case S_IFLNK: -+ type = AuIop_SYMLINK; -+ break; -+ default: -+ type = AuIop_OTHER; -+ break; -+ } -+ -+ inode->i_op = iop + type; -+ /* unnecessary smp_wmb() */ -+} -+ -+int au_refresh_hinode_self(struct inode *inode) -+{ -+ int err, update; -+ -+ err = au_ii_refresh(inode, &update); -+ if (!err) -+ au_refresh_hinode_attr(inode, update && S_ISDIR(inode->i_mode)); -+ -+ AuTraceErr(err); -+ return err; -+} -+ -+int au_refresh_hinode(struct inode *inode, struct dentry *dentry) -+{ -+ int err, e, update; -+ unsigned int flags; -+ umode_t mode; -+ aufs_bindex_t bindex, bbot; -+ unsigned char isdir; -+ struct au_hinode *p; -+ struct au_iinfo *iinfo; -+ -+ err = au_ii_refresh(inode, &update); -+ if (unlikely(err)) -+ goto out; -+ -+ update = 0; -+ iinfo = au_ii(inode); -+ p = au_hinode(iinfo, iinfo->ii_btop); -+ mode = (inode->i_mode & S_IFMT); -+ isdir = S_ISDIR(mode); -+ flags = au_hi_flags(inode, isdir); -+ bbot = au_dbbot(dentry); -+ for (bindex = au_dbtop(dentry); bindex <= bbot; bindex++) { -+ struct inode *h_i, *h_inode; -+ struct dentry *h_d; -+ -+ h_d = au_h_dptr(dentry, bindex); -+ if (!h_d || d_is_negative(h_d)) -+ continue; -+ -+ h_inode = d_inode(h_d); -+ AuDebugOn(mode != (h_inode->i_mode & S_IFMT)); -+ if (iinfo->ii_btop <= bindex && bindex <= iinfo->ii_bbot) { -+ h_i = au_h_iptr(inode, bindex); -+ if (h_i) { -+ if (h_i == h_inode) -+ continue; -+ err = -EIO; -+ break; -+ } -+ } -+ if (bindex < iinfo->ii_btop) -+ iinfo->ii_btop = bindex; -+ if (iinfo->ii_bbot < bindex) -+ iinfo->ii_bbot = bindex; -+ au_set_h_iptr(inode, bindex, au_igrab(h_inode), flags); -+ update = 1; -+ } -+ au_update_ibrange(inode, /*do_put_zero*/0); -+ e = au_dy_irefresh(inode); -+ if (unlikely(e && !err)) -+ err = e; -+ if (!err) -+ au_refresh_hinode_attr(inode, update && isdir); -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+static int set_inode(struct inode *inode, struct dentry *dentry) -+{ -+ int err; -+ unsigned int flags; -+ umode_t mode; -+ aufs_bindex_t bindex, btop, btail; -+ unsigned char isdir; -+ struct dentry *h_dentry; -+ struct inode *h_inode; -+ struct au_iinfo *iinfo; -+ const struct inode_operations *iop; -+ -+ IiMustWriteLock(inode); -+ -+ err = 0; -+ isdir = 0; -+ iop = au_sbi(inode->i_sb)->si_iop_array; -+ btop = au_dbtop(dentry); -+ h_dentry = au_h_dptr(dentry, btop); -+ h_inode = d_inode(h_dentry); -+ mode = h_inode->i_mode; -+ switch (mode & S_IFMT) { -+ case S_IFREG: -+ btail = au_dbtail(dentry); -+ inode->i_op = iop + AuIop_OTHER; -+ inode->i_fop = &aufs_file_fop; -+ err = au_dy_iaop(inode, btop, h_inode); -+ if (unlikely(err)) -+ goto out; -+ break; -+ case S_IFDIR: -+ isdir = 1; -+ btail = au_dbtaildir(dentry); -+ inode->i_op = iop + AuIop_DIR; -+ inode->i_fop = &aufs_dir_fop; -+ break; -+ case S_IFLNK: -+ btail = au_dbtail(dentry); -+ inode->i_op = iop + AuIop_SYMLINK; -+ break; -+ case S_IFBLK: -+ case S_IFCHR: -+ case S_IFIFO: -+ case S_IFSOCK: -+ btail = au_dbtail(dentry); -+ inode->i_op = iop + AuIop_OTHER; -+ init_special_inode(inode, mode, h_inode->i_rdev); -+ break; -+ default: -+ AuIOErr("Unknown file type 0%o\n", mode); -+ err = -EIO; -+ goto out; -+ } -+ -+ /* do not set hnotify for whiteouted dirs (SHWH mode) */ -+ flags = au_hi_flags(inode, isdir); -+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH) -+ && au_ftest_hi(flags, HNOTIFY) -+ && dentry->d_name.len > AUFS_WH_PFX_LEN -+ && !memcmp(dentry->d_name.name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) -+ au_fclr_hi(flags, HNOTIFY); -+ iinfo = au_ii(inode); -+ iinfo->ii_btop = btop; -+ iinfo->ii_bbot = btail; -+ for (bindex = btop; bindex <= btail; bindex++) { -+ h_dentry = au_h_dptr(dentry, bindex); -+ if (h_dentry) -+ au_set_h_iptr(inode, bindex, -+ au_igrab(d_inode(h_dentry)), flags); -+ } -+ au_cpup_attr_all(inode, /*force*/1); -+ /* -+ * to force calling aufs_get_acl() every time, -+ * do not call cache_no_acl() for aufs inode. -+ */ -+ -+out: -+ return err; -+} -+ -+/* -+ * successful returns with iinfo write_locked -+ * minus: errno -+ * zero: success, matched -+ * plus: no error, but unmatched -+ */ -+static int reval_inode(struct inode *inode, struct dentry *dentry) -+{ -+ int err; -+ unsigned int gen, igflags; -+ aufs_bindex_t bindex, bbot; -+ struct inode *h_inode, *h_dinode; -+ struct dentry *h_dentry; -+ -+ /* -+ * before this function, if aufs got any iinfo lock, it must be only -+ * one, the parent dir. -+ * it can happen by UDBA and the obsoleted inode number. -+ */ -+ err = -EIO; -+ if (unlikely(inode->i_ino == parent_ino(dentry))) -+ goto out; -+ -+ err = 1; -+ ii_write_lock_new_child(inode); -+ h_dentry = au_h_dptr(dentry, au_dbtop(dentry)); -+ h_dinode = d_inode(h_dentry); -+ bbot = au_ibbot(inode); -+ for (bindex = au_ibtop(inode); bindex <= bbot; bindex++) { -+ h_inode = au_h_iptr(inode, bindex); -+ if (!h_inode || h_inode != h_dinode) -+ continue; -+ -+ err = 0; -+ gen = au_iigen(inode, &igflags); -+ if (gen == au_digen(dentry) -+ && !au_ig_ftest(igflags, HALF_REFRESHED)) -+ break; -+ -+ /* fully refresh inode using dentry */ -+ err = au_refresh_hinode(inode, dentry); -+ if (!err) -+ au_update_iigen(inode, /*half*/0); -+ break; -+ } -+ -+ if (unlikely(err)) -+ ii_write_unlock(inode); -+out: -+ return err; -+} -+ -+int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, -+ unsigned int d_type, ino_t *ino) -+{ -+ int err, idx; -+ const int isnondir = d_type != DT_DIR; -+ -+ /* prevent hardlinked inode number from race condition */ -+ if (isnondir) { -+ err = au_xinondir_enter(sb, bindex, h_ino, &idx); -+ if (unlikely(err)) -+ goto out; -+ } -+ -+ err = au_xino_read(sb, bindex, h_ino, ino); -+ if (unlikely(err)) -+ goto out_xinondir; -+ -+ if (!*ino) { -+ err = -EIO; -+ *ino = au_xino_new_ino(sb); -+ if (unlikely(!*ino)) -+ goto out_xinondir; -+ err = au_xino_write(sb, bindex, h_ino, *ino); -+ if (unlikely(err)) -+ goto out_xinondir; -+ } -+ -+out_xinondir: -+ if (isnondir && idx >= 0) -+ au_xinondir_leave(sb, bindex, h_ino, idx); -+out: -+ return err; -+} -+ -+/* successful returns with iinfo write_locked */ -+/* todo: return with unlocked? */ -+struct inode *au_new_inode(struct dentry *dentry, int must_new) -+{ -+ struct inode *inode, *h_inode; -+ struct dentry *h_dentry; -+ struct super_block *sb; -+ ino_t h_ino, ino; -+ int err, idx, hlinked; -+ aufs_bindex_t btop; -+ -+ sb = dentry->d_sb; -+ btop = au_dbtop(dentry); -+ h_dentry = au_h_dptr(dentry, btop); -+ h_inode = d_inode(h_dentry); -+ h_ino = h_inode->i_ino; -+ hlinked = !d_is_dir(h_dentry) && h_inode->i_nlink > 1; -+ -+new_ino: -+ /* -+ * stop 'race'-ing between hardlinks under different -+ * parents. -+ */ -+ if (hlinked) { -+ err = au_xinondir_enter(sb, btop, h_ino, &idx); -+ inode = ERR_PTR(err); -+ if (unlikely(err)) -+ goto out; -+ } -+ -+ err = au_xino_read(sb, btop, h_ino, &ino); -+ inode = ERR_PTR(err); -+ if (unlikely(err)) -+ goto out_xinondir; -+ -+ if (!ino) { -+ ino = au_xino_new_ino(sb); -+ if (unlikely(!ino)) { -+ inode = ERR_PTR(-EIO); -+ goto out_xinondir; -+ } -+ } -+ -+ AuDbg("i%lu\n", (unsigned long)ino); -+ inode = au_iget_locked(sb, ino); -+ err = PTR_ERR(inode); -+ if (IS_ERR(inode)) -+ goto out_xinondir; -+ -+ AuDbg("%lx, new %d\n", inode->i_state, !!(inode->i_state & I_NEW)); -+ if (inode->i_state & I_NEW) { -+ ii_write_lock_new_child(inode); -+ err = set_inode(inode, dentry); -+ if (!err) { -+ unlock_new_inode(inode); -+ goto out_xinondir; /* success */ -+ } -+ -+ /* -+ * iget_failed() calls iput(), but we need to call -+ * ii_write_unlock() after iget_failed(). so dirty hack for -+ * i_count. -+ */ -+ atomic_inc(&inode->i_count); -+ iget_failed(inode); -+ ii_write_unlock(inode); -+ au_xino_write(sb, btop, h_ino, /*ino*/0); -+ /* ignore this error */ -+ goto out_iput; -+ } else if (!must_new && !IS_DEADDIR(inode) && inode->i_nlink) { -+ /* -+ * horrible race condition between lookup, readdir and copyup -+ * (or something). -+ */ -+ if (hlinked && idx >= 0) -+ au_xinondir_leave(sb, btop, h_ino, idx); -+ err = reval_inode(inode, dentry); -+ if (unlikely(err < 0)) { -+ hlinked = 0; -+ goto out_iput; -+ } -+ if (!err) -+ goto out; /* success */ -+ else if (hlinked && idx >= 0) { -+ err = au_xinondir_enter(sb, btop, h_ino, &idx); -+ if (unlikely(err)) { -+ iput(inode); -+ inode = ERR_PTR(err); -+ goto out; -+ } -+ } -+ } -+ -+ if (unlikely(au_test_fs_unique_ino(h_inode))) -+ AuWarn1("Warning: Un-notified UDBA or repeatedly renamed dir," -+ " b%d, %s, %pd, hi%lu, i%lu.\n", -+ btop, au_sbtype(h_dentry->d_sb), dentry, -+ (unsigned long)h_ino, (unsigned long)ino); -+ ino = 0; -+ err = au_xino_write(sb, btop, h_ino, /*ino*/0); -+ if (!err) { -+ iput(inode); -+ if (hlinked && idx >= 0) -+ au_xinondir_leave(sb, btop, h_ino, idx); -+ goto new_ino; -+ } -+ -+out_iput: -+ iput(inode); -+ inode = ERR_PTR(err); -+out_xinondir: -+ if (hlinked && idx >= 0) -+ au_xinondir_leave(sb, btop, h_ino, idx); -+out: -+ return inode; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+int au_test_ro(struct super_block *sb, aufs_bindex_t bindex, -+ struct inode *inode) -+{ -+ int err; -+ struct inode *hi; -+ -+ err = au_br_rdonly(au_sbr(sb, bindex)); -+ -+ /* pseudo-link after flushed may happen out of bounds */ -+ if (!err -+ && inode -+ && au_ibtop(inode) <= bindex -+ && bindex <= au_ibbot(inode)) { -+ /* -+ * permission check is unnecessary since vfsub routine -+ * will be called later -+ */ -+ hi = au_h_iptr(inode, bindex); -+ if (hi) -+ err = IS_IMMUTABLE(hi) ? -EROFS : 0; -+ } -+ -+ return err; -+} -+ -+int au_test_h_perm(struct inode *h_inode, int mask) -+{ -+ if (uid_eq(current_fsuid(), GLOBAL_ROOT_UID)) -+ return 0; -+ return inode_permission(h_inode, mask); -+} -+ -+int au_test_h_perm_sio(struct inode *h_inode, int mask) -+{ -+ if (au_test_nfs(h_inode->i_sb) -+ && (mask & MAY_WRITE) -+ && S_ISDIR(h_inode->i_mode)) -+ mask |= MAY_READ; /* force permission check */ -+ return au_test_h_perm(h_inode, mask); -+} -diff -Nurp linux-5.10-rc6/fs/aufs/inode.h linux-5.10-rc6.aufs/fs/aufs/inode.h ---- linux-5.10-rc6/fs/aufs/inode.h 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/inode.h 2020-12-02 21:19:51.882036788 +0200 -@@ -0,0 +1,685 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * inode operations -+ */ -+ -+#ifndef __AUFS_INODE_H__ -+#define __AUFS_INODE_H__ -+ -+#ifdef __KERNEL__ -+ -+#include -+#include "rwsem.h" -+ -+struct vfsmount; -+ -+struct au_hnotify { -+#ifdef CONFIG_AUFS_HNOTIFY -+#ifdef CONFIG_AUFS_HFSNOTIFY -+ /* never use fsnotify_add_vfsmount_mark() */ -+ struct fsnotify_mark hn_mark; -+#endif -+ struct inode *hn_aufs_inode; /* no get/put */ -+ struct rcu_head rcu; -+#endif -+} ____cacheline_aligned_in_smp; -+ -+struct au_hinode { -+ struct inode *hi_inode; -+ aufs_bindex_t hi_id; -+#ifdef CONFIG_AUFS_HNOTIFY -+ struct au_hnotify *hi_notify; -+#endif -+ -+ /* reference to the copied-up whiteout with get/put */ -+ struct dentry *hi_whdentry; -+}; -+ -+/* ig_flags */ -+#define AuIG_HALF_REFRESHED 1 -+#define au_ig_ftest(flags, name) ((flags) & AuIG_##name) -+#define au_ig_fset(flags, name) \ -+ do { (flags) |= AuIG_##name; } while (0) -+#define au_ig_fclr(flags, name) \ -+ do { (flags) &= ~AuIG_##name; } while (0) -+ -+struct au_iigen { -+ spinlock_t ig_spin; -+ __u32 ig_generation, ig_flags; -+}; -+ -+struct au_vdir; -+struct au_iinfo { -+ struct au_iigen ii_generation; -+ struct super_block *ii_hsb1; /* no get/put */ -+ -+ struct au_rwsem ii_rwsem; -+ aufs_bindex_t ii_btop, ii_bbot; -+ __u32 ii_higen; -+ struct au_hinode *ii_hinode; -+ struct au_vdir *ii_vdir; -+}; -+ -+struct au_icntnr { -+ struct au_iinfo iinfo; -+ struct inode vfs_inode; -+ struct hlist_bl_node plink; -+ struct rcu_head rcu; -+} ____cacheline_aligned_in_smp; -+ -+/* au_pin flags */ -+#define AuPin_DI_LOCKED 1 -+#define AuPin_MNT_WRITE (1 << 1) -+#define au_ftest_pin(flags, name) ((flags) & AuPin_##name) -+#define au_fset_pin(flags, name) \ -+ do { (flags) |= AuPin_##name; } while (0) -+#define au_fclr_pin(flags, name) \ -+ do { (flags) &= ~AuPin_##name; } while (0) -+ -+struct au_pin { -+ /* input */ -+ struct dentry *dentry; -+ unsigned int udba; -+ unsigned char lsc_di, lsc_hi, flags; -+ aufs_bindex_t bindex; -+ -+ /* output */ -+ struct dentry *parent; -+ struct au_hinode *hdir; -+ struct vfsmount *h_mnt; -+ -+ /* temporary unlock/relock for copyup */ -+ struct dentry *h_dentry, *h_parent; -+ struct au_branch *br; -+ struct task_struct *task; -+}; -+ -+void au_pin_hdir_unlock(struct au_pin *p); -+int au_pin_hdir_lock(struct au_pin *p); -+int au_pin_hdir_relock(struct au_pin *p); -+void au_pin_hdir_acquire_nest(struct au_pin *p); -+void au_pin_hdir_release(struct au_pin *p); -+ -+/* ---------------------------------------------------------------------- */ -+ -+static inline struct au_iinfo *au_ii(struct inode *inode) -+{ -+ BUG_ON(is_bad_inode(inode)); -+ return &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* inode.c */ -+struct inode *au_igrab(struct inode *inode); -+void au_refresh_iop(struct inode *inode, int force_getattr); -+int au_refresh_hinode_self(struct inode *inode); -+int au_refresh_hinode(struct inode *inode, struct dentry *dentry); -+int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, -+ unsigned int d_type, ino_t *ino); -+struct inode *au_new_inode(struct dentry *dentry, int must_new); -+int au_test_ro(struct super_block *sb, aufs_bindex_t bindex, -+ struct inode *inode); -+int au_test_h_perm(struct inode *h_inode, int mask); -+int au_test_h_perm_sio(struct inode *h_inode, int mask); -+ -+static inline int au_wh_ino(struct super_block *sb, aufs_bindex_t bindex, -+ ino_t h_ino, unsigned int d_type, ino_t *ino) -+{ -+#ifdef CONFIG_AUFS_SHWH -+ return au_ino(sb, bindex, h_ino, d_type, ino); -+#else -+ return 0; -+#endif -+} -+ -+/* i_op.c */ -+enum { -+ AuIop_SYMLINK, -+ AuIop_DIR, -+ AuIop_OTHER, -+ AuIop_Last -+}; -+extern struct inode_operations aufs_iop[AuIop_Last], /* not const */ -+ aufs_iop_nogetattr[AuIop_Last]; -+ -+/* au_wr_dir flags */ -+#define AuWrDir_ADD_ENTRY 1 -+#define AuWrDir_ISDIR (1 << 1) -+#define AuWrDir_TMPFILE (1 << 2) -+#define au_ftest_wrdir(flags, name) ((flags) & AuWrDir_##name) -+#define au_fset_wrdir(flags, name) \ -+ do { (flags) |= AuWrDir_##name; } while (0) -+#define au_fclr_wrdir(flags, name) \ -+ do { (flags) &= ~AuWrDir_##name; } while (0) -+ -+struct au_wr_dir_args { -+ aufs_bindex_t force_btgt; -+ unsigned char flags; -+}; -+int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry, -+ struct au_wr_dir_args *args); -+ -+struct dentry *au_pinned_h_parent(struct au_pin *pin); -+void au_pin_init(struct au_pin *pin, struct dentry *dentry, -+ aufs_bindex_t bindex, int lsc_di, int lsc_hi, -+ unsigned int udba, unsigned char flags); -+int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex, -+ unsigned int udba, unsigned char flags) __must_check; -+int au_do_pin(struct au_pin *pin) __must_check; -+void au_unpin(struct au_pin *pin); -+int au_reval_for_attr(struct dentry *dentry, unsigned int sigen); -+ -+#define AuIcpup_DID_CPUP 1 -+#define au_ftest_icpup(flags, name) ((flags) & AuIcpup_##name) -+#define au_fset_icpup(flags, name) \ -+ do { (flags) |= AuIcpup_##name; } while (0) -+#define au_fclr_icpup(flags, name) \ -+ do { (flags) &= ~AuIcpup_##name; } while (0) -+ -+struct au_icpup_args { -+ unsigned char flags; -+ unsigned char pin_flags; -+ aufs_bindex_t btgt; -+ unsigned int udba; -+ struct au_pin pin; -+ struct path h_path; -+ struct inode *h_inode; -+}; -+ -+int au_pin_and_icpup(struct dentry *dentry, struct iattr *ia, -+ struct au_icpup_args *a); -+ -+int au_h_path_getattr(struct dentry *dentry, struct inode *inode, int force, -+ struct path *h_path, int locked); -+ -+/* i_op_add.c */ -+int au_may_add(struct dentry *dentry, aufs_bindex_t bindex, -+ struct dentry *h_parent, int isdir); -+int aufs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, -+ dev_t dev); -+int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname); -+int aufs_create(struct inode *dir, struct dentry *dentry, umode_t mode, -+ bool want_excl); -+struct vfsub_aopen_args; -+int au_aopen_or_create(struct inode *dir, struct dentry *dentry, -+ struct vfsub_aopen_args *args); -+int aufs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode); -+int aufs_link(struct dentry *src_dentry, struct inode *dir, -+ struct dentry *dentry); -+int aufs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode); -+ -+/* i_op_del.c */ -+int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup); -+int au_may_del(struct dentry *dentry, aufs_bindex_t bindex, -+ struct dentry *h_parent, int isdir); -+int aufs_unlink(struct inode *dir, struct dentry *dentry); -+int aufs_rmdir(struct inode *dir, struct dentry *dentry); -+ -+/* i_op_ren.c */ -+int au_wbr(struct dentry *dentry, aufs_bindex_t btgt); -+int aufs_rename(struct inode *src_dir, struct dentry *src_dentry, -+ struct inode *dir, struct dentry *dentry, -+ unsigned int flags); -+ -+/* iinfo.c */ -+struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex); -+void au_hiput(struct au_hinode *hinode); -+void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex, -+ struct dentry *h_wh); -+unsigned int au_hi_flags(struct inode *inode, int isdir); -+ -+/* hinode flags */ -+#define AuHi_XINO 1 -+#define AuHi_HNOTIFY (1 << 1) -+#define au_ftest_hi(flags, name) ((flags) & AuHi_##name) -+#define au_fset_hi(flags, name) \ -+ do { (flags) |= AuHi_##name; } while (0) -+#define au_fclr_hi(flags, name) \ -+ do { (flags) &= ~AuHi_##name; } while (0) -+ -+#ifndef CONFIG_AUFS_HNOTIFY -+#undef AuHi_HNOTIFY -+#define AuHi_HNOTIFY 0 -+#endif -+ -+void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex, -+ struct inode *h_inode, unsigned int flags); -+ -+void au_update_iigen(struct inode *inode, int half); -+void au_update_ibrange(struct inode *inode, int do_put_zero); -+ -+void au_icntnr_init_once(void *_c); -+void au_hinode_init(struct au_hinode *hinode); -+int au_iinfo_init(struct inode *inode); -+void au_iinfo_fin(struct inode *inode); -+int au_hinode_realloc(struct au_iinfo *iinfo, int nbr, int may_shrink); -+ -+#ifdef CONFIG_PROC_FS -+/* plink.c */ -+int au_plink_maint(struct super_block *sb, int flags); -+struct au_sbinfo; -+void au_plink_maint_leave(struct au_sbinfo *sbinfo); -+int au_plink_maint_enter(struct super_block *sb); -+#ifdef CONFIG_AUFS_DEBUG -+void au_plink_list(struct super_block *sb); -+#else -+AuStubVoid(au_plink_list, struct super_block *sb) -+#endif -+int au_plink_test(struct inode *inode); -+struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex); -+void au_plink_append(struct inode *inode, aufs_bindex_t bindex, -+ struct dentry *h_dentry); -+void au_plink_put(struct super_block *sb, int verbose); -+void au_plink_clean(struct super_block *sb, int verbose); -+void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id); -+#else -+AuStubInt0(au_plink_maint, struct super_block *sb, int flags); -+AuStubVoid(au_plink_maint_leave, struct au_sbinfo *sbinfo); -+AuStubInt0(au_plink_maint_enter, struct super_block *sb); -+AuStubVoid(au_plink_list, struct super_block *sb); -+AuStubInt0(au_plink_test, struct inode *inode); -+AuStub(struct dentry *, au_plink_lkup, return NULL, -+ struct inode *inode, aufs_bindex_t bindex); -+AuStubVoid(au_plink_append, struct inode *inode, aufs_bindex_t bindex, -+ struct dentry *h_dentry); -+AuStubVoid(au_plink_put, struct super_block *sb, int verbose); -+AuStubVoid(au_plink_clean, struct super_block *sb, int verbose); -+AuStubVoid(au_plink_half_refresh, struct super_block *sb, aufs_bindex_t br_id); -+#endif /* CONFIG_PROC_FS */ -+ -+#ifdef CONFIG_AUFS_XATTR -+/* xattr.c */ -+int au_cpup_xattr(struct dentry *h_dst, struct dentry *h_src, int ignore_flags, -+ unsigned int verbose); -+ssize_t aufs_listxattr(struct dentry *dentry, char *list, size_t size); -+void au_xattr_init(struct super_block *sb); -+#else -+AuStubInt0(au_cpup_xattr, struct dentry *h_dst, struct dentry *h_src, -+ int ignore_flags, unsigned int verbose); -+AuStubVoid(au_xattr_init, struct super_block *sb); -+#endif -+ -+#ifdef CONFIG_FS_POSIX_ACL -+struct posix_acl *aufs_get_acl(struct inode *inode, int type); -+int aufs_set_acl(struct inode *inode, struct posix_acl *acl, int type); -+#endif -+ -+#if IS_ENABLED(CONFIG_AUFS_XATTR) || IS_ENABLED(CONFIG_FS_POSIX_ACL) -+enum { -+ AU_XATTR_SET, -+ AU_ACL_SET -+}; -+ -+struct au_sxattr { -+ int type; -+ union { -+ struct { -+ const char *name; -+ const void *value; -+ size_t size; -+ int flags; -+ } set; -+ struct { -+ struct posix_acl *acl; -+ int type; -+ } acl_set; -+ } u; -+}; -+ssize_t au_sxattr(struct dentry *dentry, struct inode *inode, -+ struct au_sxattr *arg); -+#endif -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* lock subclass for iinfo */ -+enum { -+ AuLsc_II_CHILD, /* child first */ -+ AuLsc_II_CHILD2, /* rename(2), link(2), and cpup at hnotify */ -+ AuLsc_II_CHILD3, /* copyup dirs */ -+ AuLsc_II_PARENT, /* see AuLsc_I_PARENT in vfsub.h */ -+ AuLsc_II_PARENT2, -+ AuLsc_II_PARENT3, /* copyup dirs */ -+ AuLsc_II_NEW_CHILD -+}; -+ -+/* -+ * ii_read_lock_child, ii_write_lock_child, -+ * ii_read_lock_child2, ii_write_lock_child2, -+ * ii_read_lock_child3, ii_write_lock_child3, -+ * ii_read_lock_parent, ii_write_lock_parent, -+ * ii_read_lock_parent2, ii_write_lock_parent2, -+ * ii_read_lock_parent3, ii_write_lock_parent3, -+ * ii_read_lock_new_child, ii_write_lock_new_child, -+ */ -+#define AuReadLockFunc(name, lsc) \ -+static inline void ii_read_lock_##name(struct inode *i) \ -+{ \ -+ au_rw_read_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \ -+} -+ -+#define AuWriteLockFunc(name, lsc) \ -+static inline void ii_write_lock_##name(struct inode *i) \ -+{ \ -+ au_rw_write_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \ -+} -+ -+#define AuRWLockFuncs(name, lsc) \ -+ AuReadLockFunc(name, lsc) \ -+ AuWriteLockFunc(name, lsc) -+ -+AuRWLockFuncs(child, CHILD); -+AuRWLockFuncs(child2, CHILD2); -+AuRWLockFuncs(child3, CHILD3); -+AuRWLockFuncs(parent, PARENT); -+AuRWLockFuncs(parent2, PARENT2); -+AuRWLockFuncs(parent3, PARENT3); -+AuRWLockFuncs(new_child, NEW_CHILD); -+ -+#undef AuReadLockFunc -+#undef AuWriteLockFunc -+#undef AuRWLockFuncs -+ -+#define ii_read_unlock(i) au_rw_read_unlock(&au_ii(i)->ii_rwsem) -+#define ii_write_unlock(i) au_rw_write_unlock(&au_ii(i)->ii_rwsem) -+#define ii_downgrade_lock(i) au_rw_dgrade_lock(&au_ii(i)->ii_rwsem) -+ -+#define IiMustNoWaiters(i) AuRwMustNoWaiters(&au_ii(i)->ii_rwsem) -+#define IiMustAnyLock(i) AuRwMustAnyLock(&au_ii(i)->ii_rwsem) -+#define IiMustWriteLock(i) AuRwMustWriteLock(&au_ii(i)->ii_rwsem) -+ -+/* ---------------------------------------------------------------------- */ -+ -+static inline void au_icntnr_init(struct au_icntnr *c) -+{ -+#ifdef CONFIG_AUFS_DEBUG -+ c->vfs_inode.i_mode = 0; -+#endif -+} -+ -+static inline unsigned int au_iigen(struct inode *inode, unsigned int *igflags) -+{ -+ unsigned int gen; -+ struct au_iinfo *iinfo; -+ struct au_iigen *iigen; -+ -+ iinfo = au_ii(inode); -+ iigen = &iinfo->ii_generation; -+ spin_lock(&iigen->ig_spin); -+ if (igflags) -+ *igflags = iigen->ig_flags; -+ gen = iigen->ig_generation; -+ spin_unlock(&iigen->ig_spin); -+ -+ return gen; -+} -+ -+/* tiny test for inode number */ -+/* tmpfs generation is too rough */ -+static inline int au_test_higen(struct inode *inode, struct inode *h_inode) -+{ -+ struct au_iinfo *iinfo; -+ -+ iinfo = au_ii(inode); -+ AuRwMustAnyLock(&iinfo->ii_rwsem); -+ return !(iinfo->ii_hsb1 == h_inode->i_sb -+ && iinfo->ii_higen == h_inode->i_generation); -+} -+ -+static inline void au_iigen_dec(struct inode *inode) -+{ -+ struct au_iinfo *iinfo; -+ struct au_iigen *iigen; -+ -+ iinfo = au_ii(inode); -+ iigen = &iinfo->ii_generation; -+ spin_lock(&iigen->ig_spin); -+ iigen->ig_generation--; -+ spin_unlock(&iigen->ig_spin); -+} -+ -+static inline int au_iigen_test(struct inode *inode, unsigned int sigen) -+{ -+ int err; -+ -+ err = 0; -+ if (unlikely(inode && au_iigen(inode, NULL) != sigen)) -+ err = -EIO; -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static inline struct au_hinode *au_hinode(struct au_iinfo *iinfo, -+ aufs_bindex_t bindex) -+{ -+ return iinfo->ii_hinode + bindex; -+} -+ -+static inline int au_is_bad_inode(struct inode *inode) -+{ -+ return !!(is_bad_inode(inode) || !au_hinode(au_ii(inode), 0)); -+} -+ -+static inline aufs_bindex_t au_ii_br_id(struct inode *inode, -+ aufs_bindex_t bindex) -+{ -+ IiMustAnyLock(inode); -+ return au_hinode(au_ii(inode), bindex)->hi_id; -+} -+ -+static inline aufs_bindex_t au_ibtop(struct inode *inode) -+{ -+ IiMustAnyLock(inode); -+ return au_ii(inode)->ii_btop; -+} -+ -+static inline aufs_bindex_t au_ibbot(struct inode *inode) -+{ -+ IiMustAnyLock(inode); -+ return au_ii(inode)->ii_bbot; -+} -+ -+static inline struct au_vdir *au_ivdir(struct inode *inode) -+{ -+ IiMustAnyLock(inode); -+ return au_ii(inode)->ii_vdir; -+} -+ -+static inline struct dentry *au_hi_wh(struct inode *inode, aufs_bindex_t bindex) -+{ -+ IiMustAnyLock(inode); -+ return au_hinode(au_ii(inode), bindex)->hi_whdentry; -+} -+ -+static inline void au_set_ibtop(struct inode *inode, aufs_bindex_t bindex) -+{ -+ IiMustWriteLock(inode); -+ au_ii(inode)->ii_btop = bindex; -+} -+ -+static inline void au_set_ibbot(struct inode *inode, aufs_bindex_t bindex) -+{ -+ IiMustWriteLock(inode); -+ au_ii(inode)->ii_bbot = bindex; -+} -+ -+static inline void au_set_ivdir(struct inode *inode, struct au_vdir *vdir) -+{ -+ IiMustWriteLock(inode); -+ au_ii(inode)->ii_vdir = vdir; -+} -+ -+static inline struct au_hinode *au_hi(struct inode *inode, aufs_bindex_t bindex) -+{ -+ IiMustAnyLock(inode); -+ return au_hinode(au_ii(inode), bindex); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static inline struct dentry *au_pinned_parent(struct au_pin *pin) -+{ -+ if (pin) -+ return pin->parent; -+ return NULL; -+} -+ -+static inline struct inode *au_pinned_h_dir(struct au_pin *pin) -+{ -+ if (pin && pin->hdir) -+ return pin->hdir->hi_inode; -+ return NULL; -+} -+ -+static inline struct au_hinode *au_pinned_hdir(struct au_pin *pin) -+{ -+ if (pin) -+ return pin->hdir; -+ return NULL; -+} -+ -+static inline void au_pin_set_dentry(struct au_pin *pin, struct dentry *dentry) -+{ -+ if (pin) -+ pin->dentry = dentry; -+} -+ -+static inline void au_pin_set_parent_lflag(struct au_pin *pin, -+ unsigned char lflag) -+{ -+ if (pin) { -+ if (lflag) -+ au_fset_pin(pin->flags, DI_LOCKED); -+ else -+ au_fclr_pin(pin->flags, DI_LOCKED); -+ } -+} -+ -+#if 0 /* reserved */ -+static inline void au_pin_set_parent(struct au_pin *pin, struct dentry *parent) -+{ -+ if (pin) { -+ dput(pin->parent); -+ pin->parent = dget(parent); -+ } -+} -+#endif -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct au_branch; -+#ifdef CONFIG_AUFS_HNOTIFY -+struct au_hnotify_op { -+ void (*ctl)(struct au_hinode *hinode, int do_set); -+ int (*alloc)(struct au_hinode *hinode); -+ -+ /* -+ * if it returns true, the the caller should free hinode->hi_notify, -+ * otherwise ->free() frees it. -+ */ -+ int (*free)(struct au_hinode *hinode, -+ struct au_hnotify *hn) __must_check; -+ -+ void (*fin)(void); -+ int (*init)(void); -+ -+ int (*reset_br)(unsigned int udba, struct au_branch *br, int perm); -+ void (*fin_br)(struct au_branch *br); -+ int (*init_br)(struct au_branch *br, int perm); -+}; -+ -+/* hnotify.c */ -+int au_hn_alloc(struct au_hinode *hinode, struct inode *inode); -+void au_hn_free(struct au_hinode *hinode); -+void au_hn_ctl(struct au_hinode *hinode, int do_set); -+void au_hn_reset(struct inode *inode, unsigned int flags); -+int au_hnotify(struct inode *h_dir, struct au_hnotify *hnotify, u32 mask, -+ const struct qstr *h_child_qstr, struct inode *h_child_inode); -+int au_hnotify_reset_br(unsigned int udba, struct au_branch *br, int perm); -+int au_hnotify_init_br(struct au_branch *br, int perm); -+void au_hnotify_fin_br(struct au_branch *br); -+int __init au_hnotify_init(void); -+void au_hnotify_fin(void); -+ -+/* hfsnotify.c */ -+extern const struct au_hnotify_op au_hnotify_op; -+ -+static inline -+void au_hn_init(struct au_hinode *hinode) -+{ -+ hinode->hi_notify = NULL; -+} -+ -+static inline struct au_hnotify *au_hn(struct au_hinode *hinode) -+{ -+ return hinode->hi_notify; -+} -+ -+#else -+AuStub(int, au_hn_alloc, return -EOPNOTSUPP, -+ struct au_hinode *hinode __maybe_unused, -+ struct inode *inode __maybe_unused) -+AuStub(struct au_hnotify *, au_hn, return NULL, struct au_hinode *hinode) -+AuStubVoid(au_hn_free, struct au_hinode *hinode __maybe_unused) -+AuStubVoid(au_hn_ctl, struct au_hinode *hinode __maybe_unused, -+ int do_set __maybe_unused) -+AuStubVoid(au_hn_reset, struct inode *inode __maybe_unused, -+ unsigned int flags __maybe_unused) -+AuStubInt0(au_hnotify_reset_br, unsigned int udba __maybe_unused, -+ struct au_branch *br __maybe_unused, -+ int perm __maybe_unused) -+AuStubInt0(au_hnotify_init_br, struct au_branch *br __maybe_unused, -+ int perm __maybe_unused) -+AuStubVoid(au_hnotify_fin_br, struct au_branch *br __maybe_unused) -+AuStubInt0(__init au_hnotify_init, void) -+AuStubVoid(au_hnotify_fin, void) -+AuStubVoid(au_hn_init, struct au_hinode *hinode __maybe_unused) -+#endif /* CONFIG_AUFS_HNOTIFY */ -+ -+static inline void au_hn_suspend(struct au_hinode *hdir) -+{ -+ au_hn_ctl(hdir, /*do_set*/0); -+} -+ -+static inline void au_hn_resume(struct au_hinode *hdir) -+{ -+ au_hn_ctl(hdir, /*do_set*/1); -+} -+ -+static inline void au_hn_inode_lock(struct au_hinode *hdir) -+{ -+ inode_lock(hdir->hi_inode); -+ au_hn_suspend(hdir); -+} -+ -+static inline void au_hn_inode_lock_nested(struct au_hinode *hdir, -+ unsigned int sc __maybe_unused) -+{ -+ inode_lock_nested(hdir->hi_inode, sc); -+ au_hn_suspend(hdir); -+} -+ -+#if 0 /* unused */ -+#include "vfsub.h" -+static inline void au_hn_inode_lock_shared_nested(struct au_hinode *hdir, -+ unsigned int sc) -+{ -+ inode_lock_shared_nested(hdir->hi_inode, sc); -+ au_hn_suspend(hdir); -+} -+#endif -+ -+static inline void au_hn_inode_unlock(struct au_hinode *hdir) -+{ -+ au_hn_resume(hdir); -+ inode_unlock(hdir->hi_inode); -+} -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_INODE_H__ */ -diff -Nurp linux-5.10-rc6/fs/aufs/ioctl.c linux-5.10-rc6.aufs/fs/aufs/ioctl.c ---- linux-5.10-rc6/fs/aufs/ioctl.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/ioctl.c 2020-12-02 21:19:51.882036788 +0200 -@@ -0,0 +1,207 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * ioctl -+ * plink-management and readdir in userspace. -+ * assist the pathconf(3) wrapper library. -+ * move-down -+ * File-based Hierarchical Storage Management. -+ */ -+ -+#include -+#include -+#include "aufs.h" -+ -+static int au_wbr_fd(struct path *path, struct aufs_wbr_fd __user *arg) -+{ -+ int err, fd; -+ aufs_bindex_t wbi, bindex, bbot; -+ struct file *h_file; -+ struct super_block *sb; -+ struct dentry *root; -+ struct au_branch *br; -+ struct aufs_wbr_fd wbrfd = { -+ .oflags = au_dir_roflags, -+ .brid = -1 -+ }; -+ const int valid = O_RDONLY | O_NONBLOCK | O_LARGEFILE | O_DIRECTORY -+ | O_NOATIME | O_CLOEXEC; -+ -+ AuDebugOn(wbrfd.oflags & ~valid); -+ -+ if (arg) { -+ err = copy_from_user(&wbrfd, arg, sizeof(wbrfd)); -+ if (unlikely(err)) { -+ err = -EFAULT; -+ goto out; -+ } -+ -+ err = -EINVAL; -+ AuDbg("wbrfd{0%o, %d}\n", wbrfd.oflags, wbrfd.brid); -+ wbrfd.oflags |= au_dir_roflags; -+ AuDbg("0%o\n", wbrfd.oflags); -+ if (unlikely(wbrfd.oflags & ~valid)) -+ goto out; -+ } -+ -+ fd = get_unused_fd_flags(0); -+ err = fd; -+ if (unlikely(fd < 0)) -+ goto out; -+ -+ h_file = ERR_PTR(-EINVAL); -+ wbi = 0; -+ br = NULL; -+ sb = path->dentry->d_sb; -+ root = sb->s_root; -+ aufs_read_lock(root, AuLock_IR); -+ bbot = au_sbbot(sb); -+ if (wbrfd.brid >= 0) { -+ wbi = au_br_index(sb, wbrfd.brid); -+ if (unlikely(wbi < 0 || wbi > bbot)) -+ goto out_unlock; -+ } -+ -+ h_file = ERR_PTR(-ENOENT); -+ br = au_sbr(sb, wbi); -+ if (!au_br_writable(br->br_perm)) { -+ if (arg) -+ goto out_unlock; -+ -+ bindex = wbi + 1; -+ wbi = -1; -+ for (; bindex <= bbot; bindex++) { -+ br = au_sbr(sb, bindex); -+ if (au_br_writable(br->br_perm)) { -+ wbi = bindex; -+ br = au_sbr(sb, wbi); -+ break; -+ } -+ } -+ } -+ AuDbg("wbi %d\n", wbi); -+ if (wbi >= 0) -+ h_file = au_h_open(root, wbi, wbrfd.oflags, NULL, -+ /*force_wr*/0); -+ -+out_unlock: -+ aufs_read_unlock(root, AuLock_IR); -+ err = PTR_ERR(h_file); -+ if (IS_ERR(h_file)) -+ goto out_fd; -+ -+ au_lcnt_dec(&br->br_nfiles); /* cf. au_h_open() */ -+ fd_install(fd, h_file); -+ err = fd; -+ goto out; /* success */ -+ -+out_fd: -+ put_unused_fd(fd); -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg) -+{ -+ long err; -+ struct dentry *dentry; -+ -+ switch (cmd) { -+ case AUFS_CTL_RDU: -+ case AUFS_CTL_RDU_INO: -+ err = au_rdu_ioctl(file, cmd, arg); -+ break; -+ -+ case AUFS_CTL_WBR_FD: -+ err = au_wbr_fd(&file->f_path, (void __user *)arg); -+ break; -+ -+ case AUFS_CTL_IBUSY: -+ err = au_ibusy_ioctl(file, arg); -+ break; -+ -+ case AUFS_CTL_BRINFO: -+ err = au_brinfo_ioctl(file, arg); -+ break; -+ -+ case AUFS_CTL_FHSM_FD: -+ dentry = file->f_path.dentry; -+ if (IS_ROOT(dentry)) -+ err = au_fhsm_fd(dentry->d_sb, arg); -+ else -+ err = -ENOTTY; -+ break; -+ -+ default: -+ /* do not call the lower */ -+ AuDbg("0x%x\n", cmd); -+ err = -ENOTTY; -+ } -+ -+ AuTraceErr(err); -+ return err; -+} -+ -+long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg) -+{ -+ long err; -+ -+ switch (cmd) { -+ case AUFS_CTL_MVDOWN: -+ err = au_mvdown(file->f_path.dentry, (void __user *)arg); -+ break; -+ -+ case AUFS_CTL_WBR_FD: -+ err = au_wbr_fd(&file->f_path, (void __user *)arg); -+ break; -+ -+ default: -+ /* do not call the lower */ -+ AuDbg("0x%x\n", cmd); -+ err = -ENOTTY; -+ } -+ -+ AuTraceErr(err); -+ return err; -+} -+ -+#ifdef CONFIG_COMPAT -+long aufs_compat_ioctl_dir(struct file *file, unsigned int cmd, -+ unsigned long arg) -+{ -+ long err; -+ -+ switch (cmd) { -+ case AUFS_CTL_RDU: -+ case AUFS_CTL_RDU_INO: -+ err = au_rdu_compat_ioctl(file, cmd, arg); -+ break; -+ -+ case AUFS_CTL_IBUSY: -+ err = au_ibusy_compat_ioctl(file, arg); -+ break; -+ -+ case AUFS_CTL_BRINFO: -+ err = au_brinfo_compat_ioctl(file, arg); -+ break; -+ -+ default: -+ err = aufs_ioctl_dir(file, cmd, arg); -+ } -+ -+ AuTraceErr(err); -+ return err; -+} -+ -+long aufs_compat_ioctl_nondir(struct file *file, unsigned int cmd, -+ unsigned long arg) -+{ -+ return aufs_ioctl_nondir(file, cmd, (unsigned long)compat_ptr(arg)); -+} -+#endif -diff -Nurp linux-5.10-rc6/fs/aufs/i_op_add.c linux-5.10-rc6.aufs/fs/aufs/i_op_add.c ---- linux-5.10-rc6/fs/aufs/i_op_add.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/i_op_add.c 2020-12-02 21:19:51.882036788 +0200 -@@ -0,0 +1,923 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * inode operations (add entry) -+ */ -+ -+#include -+#include "aufs.h" -+ -+/* -+ * final procedure of adding a new entry, except link(2). -+ * remove whiteout, instantiate, copyup the parent dir's times and size -+ * and update version. -+ * if it failed, re-create the removed whiteout. -+ */ -+static int epilog(struct inode *dir, aufs_bindex_t bindex, -+ struct dentry *wh_dentry, struct dentry *dentry) -+{ -+ int err, rerr; -+ aufs_bindex_t bwh; -+ struct path h_path; -+ struct super_block *sb; -+ struct inode *inode, *h_dir; -+ struct dentry *wh; -+ -+ bwh = -1; -+ sb = dir->i_sb; -+ if (wh_dentry) { -+ h_dir = d_inode(wh_dentry->d_parent); /* dir inode is locked */ -+ IMustLock(h_dir); -+ AuDebugOn(au_h_iptr(dir, bindex) != h_dir); -+ bwh = au_dbwh(dentry); -+ h_path.dentry = wh_dentry; -+ h_path.mnt = au_sbr_mnt(sb, bindex); -+ err = au_wh_unlink_dentry(au_h_iptr(dir, bindex), &h_path, -+ dentry); -+ if (unlikely(err)) -+ goto out; -+ } -+ -+ inode = au_new_inode(dentry, /*must_new*/1); -+ if (!IS_ERR(inode)) { -+ d_instantiate(dentry, inode); -+ dir = d_inode(dentry->d_parent); /* dir inode is locked */ -+ IMustLock(dir); -+ au_dir_ts(dir, bindex); -+ inode_inc_iversion(dir); -+ au_fhsm_wrote(sb, bindex, /*force*/0); -+ return 0; /* success */ -+ } -+ -+ err = PTR_ERR(inode); -+ if (!wh_dentry) -+ goto out; -+ -+ /* revert */ -+ /* dir inode is locked */ -+ wh = au_wh_create(dentry, bwh, wh_dentry->d_parent); -+ rerr = PTR_ERR(wh); -+ if (IS_ERR(wh)) { -+ AuIOErr("%pd reverting whiteout failed(%d, %d)\n", -+ dentry, err, rerr); -+ err = -EIO; -+ } else -+ dput(wh); -+ -+out: -+ return err; -+} -+ -+static int au_d_may_add(struct dentry *dentry) -+{ -+ int err; -+ -+ err = 0; -+ if (unlikely(d_unhashed(dentry))) -+ err = -ENOENT; -+ if (unlikely(d_really_is_positive(dentry))) -+ err = -EEXIST; -+ return err; -+} -+ -+/* -+ * simple tests for the adding inode operations. -+ * following the checks in vfs, plus the parent-child relationship. -+ */ -+int au_may_add(struct dentry *dentry, aufs_bindex_t bindex, -+ struct dentry *h_parent, int isdir) -+{ -+ int err; -+ umode_t h_mode; -+ struct dentry *h_dentry; -+ struct inode *h_inode; -+ -+ err = -ENAMETOOLONG; -+ if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN)) -+ goto out; -+ -+ h_dentry = au_h_dptr(dentry, bindex); -+ if (d_really_is_negative(dentry)) { -+ err = -EEXIST; -+ if (unlikely(d_is_positive(h_dentry))) -+ goto out; -+ } else { -+ /* rename(2) case */ -+ err = -EIO; -+ if (unlikely(d_is_negative(h_dentry))) -+ goto out; -+ h_inode = d_inode(h_dentry); -+ if (unlikely(!h_inode->i_nlink)) -+ goto out; -+ -+ h_mode = h_inode->i_mode; -+ if (!isdir) { -+ err = -EISDIR; -+ if (unlikely(S_ISDIR(h_mode))) -+ goto out; -+ } else if (unlikely(!S_ISDIR(h_mode))) { -+ err = -ENOTDIR; -+ goto out; -+ } -+ } -+ -+ err = 0; -+ /* expected parent dir is locked */ -+ if (unlikely(h_parent != h_dentry->d_parent)) -+ err = -EIO; -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+/* -+ * initial procedure of adding a new entry. -+ * prepare writable branch and the parent dir, lock it, -+ * and lookup whiteout for the new entry. -+ */ -+static struct dentry* -+lock_hdir_lkup_wh(struct dentry *dentry, struct au_dtime *dt, -+ struct dentry *src_dentry, struct au_pin *pin, -+ struct au_wr_dir_args *wr_dir_args) -+{ -+ struct dentry *wh_dentry, *h_parent; -+ struct super_block *sb; -+ struct au_branch *br; -+ int err; -+ unsigned int udba; -+ aufs_bindex_t bcpup; -+ -+ AuDbg("%pd\n", dentry); -+ -+ err = au_wr_dir(dentry, src_dentry, wr_dir_args); -+ bcpup = err; -+ wh_dentry = ERR_PTR(err); -+ if (unlikely(err < 0)) -+ goto out; -+ -+ sb = dentry->d_sb; -+ udba = au_opt_udba(sb); -+ err = au_pin(pin, dentry, bcpup, udba, -+ AuPin_DI_LOCKED | AuPin_MNT_WRITE); -+ wh_dentry = ERR_PTR(err); -+ if (unlikely(err)) -+ goto out; -+ -+ h_parent = au_pinned_h_parent(pin); -+ if (udba != AuOpt_UDBA_NONE -+ && au_dbtop(dentry) == bcpup) -+ err = au_may_add(dentry, bcpup, h_parent, -+ au_ftest_wrdir(wr_dir_args->flags, ISDIR)); -+ else if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN)) -+ err = -ENAMETOOLONG; -+ wh_dentry = ERR_PTR(err); -+ if (unlikely(err)) -+ goto out_unpin; -+ -+ br = au_sbr(sb, bcpup); -+ if (dt) { -+ struct path tmp = { -+ .dentry = h_parent, -+ .mnt = au_br_mnt(br) -+ }; -+ au_dtime_store(dt, au_pinned_parent(pin), &tmp); -+ } -+ -+ wh_dentry = NULL; -+ if (bcpup != au_dbwh(dentry)) -+ goto out; /* success */ -+ -+ /* -+ * ENAMETOOLONG here means that if we allowed create such name, then it -+ * would not be able to removed in the future. So we don't allow such -+ * name here and we don't handle ENAMETOOLONG differently here. -+ */ -+ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, br); -+ -+out_unpin: -+ if (IS_ERR(wh_dentry)) -+ au_unpin(pin); -+out: -+ return wh_dentry; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+enum { Mknod, Symlink, Creat }; -+struct simple_arg { -+ int type; -+ union { -+ struct { -+ umode_t mode; -+ bool want_excl; -+ bool try_aopen; -+ struct vfsub_aopen_args *aopen; -+ } c; -+ struct { -+ const char *symname; -+ } s; -+ struct { -+ umode_t mode; -+ dev_t dev; -+ } m; -+ } u; -+}; -+ -+static int add_simple(struct inode *dir, struct dentry *dentry, -+ struct simple_arg *arg) -+{ -+ int err, rerr; -+ aufs_bindex_t btop; -+ unsigned char created; -+ const unsigned char try_aopen -+ = (arg->type == Creat && arg->u.c.try_aopen); -+ struct vfsub_aopen_args *aopen = arg->u.c.aopen; -+ struct dentry *wh_dentry, *parent; -+ struct inode *h_dir; -+ struct super_block *sb; -+ struct au_branch *br; -+ /* to reduce stack size */ -+ struct { -+ struct au_dtime dt; -+ struct au_pin pin; -+ struct path h_path; -+ struct au_wr_dir_args wr_dir_args; -+ } *a; -+ -+ AuDbg("%pd\n", dentry); -+ IMustLock(dir); -+ -+ err = -ENOMEM; -+ a = kmalloc(sizeof(*a), GFP_NOFS); -+ if (unlikely(!a)) -+ goto out; -+ a->wr_dir_args.force_btgt = -1; -+ a->wr_dir_args.flags = AuWrDir_ADD_ENTRY; -+ -+ parent = dentry->d_parent; /* dir inode is locked */ -+ if (!try_aopen) { -+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN); -+ if (unlikely(err)) -+ goto out_free; -+ } -+ err = au_d_may_add(dentry); -+ if (unlikely(err)) -+ goto out_unlock; -+ if (!try_aopen) -+ di_write_lock_parent(parent); -+ wh_dentry = lock_hdir_lkup_wh(dentry, &a->dt, /*src_dentry*/NULL, -+ &a->pin, &a->wr_dir_args); -+ err = PTR_ERR(wh_dentry); -+ if (IS_ERR(wh_dentry)) -+ goto out_parent; -+ -+ btop = au_dbtop(dentry); -+ sb = dentry->d_sb; -+ br = au_sbr(sb, btop); -+ a->h_path.dentry = au_h_dptr(dentry, btop); -+ a->h_path.mnt = au_br_mnt(br); -+ h_dir = au_pinned_h_dir(&a->pin); -+ switch (arg->type) { -+ case Creat: -+ if (!try_aopen || !h_dir->i_op->atomic_open) { -+ err = vfsub_create(h_dir, &a->h_path, arg->u.c.mode, -+ arg->u.c.want_excl); -+ created = !err; -+ if (!err && try_aopen) -+ aopen->file->f_mode |= FMODE_CREATED; -+ } else { -+ aopen->br = br; -+ err = vfsub_atomic_open(h_dir, a->h_path.dentry, aopen); -+ AuDbg("err %d\n", err); -+ AuDbgFile(aopen->file); -+ created = err >= 0 -+ && !!(aopen->file->f_mode & FMODE_CREATED); -+ } -+ break; -+ case Symlink: -+ err = vfsub_symlink(h_dir, &a->h_path, arg->u.s.symname); -+ created = !err; -+ break; -+ case Mknod: -+ err = vfsub_mknod(h_dir, &a->h_path, arg->u.m.mode, -+ arg->u.m.dev); -+ created = !err; -+ break; -+ default: -+ BUG(); -+ } -+ if (unlikely(err < 0)) -+ goto out_unpin; -+ -+ err = epilog(dir, btop, wh_dentry, dentry); -+ if (!err) -+ goto out_unpin; /* success */ -+ -+ /* revert */ -+ if (created /* && d_is_positive(a->h_path.dentry) */) { -+ /* no delegation since it is just created */ -+ rerr = vfsub_unlink(h_dir, &a->h_path, /*delegated*/NULL, -+ /*force*/0); -+ if (rerr) { -+ AuIOErr("%pd revert failure(%d, %d)\n", -+ dentry, err, rerr); -+ err = -EIO; -+ } -+ au_dtime_revert(&a->dt); -+ } -+ if (try_aopen && h_dir->i_op->atomic_open -+ && (aopen->file->f_mode & FMODE_OPENED)) -+ /* aopen->file is still opened */ -+ au_lcnt_dec(&aopen->br->br_nfiles); -+ -+out_unpin: -+ au_unpin(&a->pin); -+ dput(wh_dentry); -+out_parent: -+ if (!try_aopen) -+ di_write_unlock(parent); -+out_unlock: -+ if (unlikely(err)) { -+ au_update_dbtop(dentry); -+ d_drop(dentry); -+ } -+ if (!try_aopen) -+ aufs_read_unlock(dentry, AuLock_DW); -+out_free: -+ au_kfree_rcu(a); -+out: -+ return err; -+} -+ -+int aufs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, -+ dev_t dev) -+{ -+ struct simple_arg arg = { -+ .type = Mknod, -+ .u.m = { -+ .mode = mode, -+ .dev = dev -+ } -+ }; -+ return add_simple(dir, dentry, &arg); -+} -+ -+int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) -+{ -+ struct simple_arg arg = { -+ .type = Symlink, -+ .u.s.symname = symname -+ }; -+ return add_simple(dir, dentry, &arg); -+} -+ -+int aufs_create(struct inode *dir, struct dentry *dentry, umode_t mode, -+ bool want_excl) -+{ -+ struct simple_arg arg = { -+ .type = Creat, -+ .u.c = { -+ .mode = mode, -+ .want_excl = want_excl -+ } -+ }; -+ return add_simple(dir, dentry, &arg); -+} -+ -+int au_aopen_or_create(struct inode *dir, struct dentry *dentry, -+ struct vfsub_aopen_args *aopen_args) -+{ -+ struct simple_arg arg = { -+ .type = Creat, -+ .u.c = { -+ .mode = aopen_args->create_mode, -+ .want_excl = aopen_args->open_flag & O_EXCL, -+ .try_aopen = true, -+ .aopen = aopen_args -+ } -+ }; -+ return add_simple(dir, dentry, &arg); -+} -+ -+int aufs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode) -+{ -+ int err; -+ aufs_bindex_t bindex; -+ struct super_block *sb; -+ struct dentry *parent, *h_parent, *h_dentry; -+ struct inode *h_dir, *inode; -+ struct vfsmount *h_mnt; -+ struct au_wr_dir_args wr_dir_args = { -+ .force_btgt = -1, -+ .flags = AuWrDir_TMPFILE -+ }; -+ -+ /* copy-up may happen */ -+ inode_lock(dir); -+ -+ sb = dir->i_sb; -+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM); -+ if (unlikely(err)) -+ goto out; -+ -+ err = au_di_init(dentry); -+ if (unlikely(err)) -+ goto out_si; -+ -+ err = -EBUSY; -+ parent = d_find_any_alias(dir); -+ AuDebugOn(!parent); -+ di_write_lock_parent(parent); -+ if (unlikely(d_inode(parent) != dir)) -+ goto out_parent; -+ -+ err = au_digen_test(parent, au_sigen(sb)); -+ if (unlikely(err)) -+ goto out_parent; -+ -+ bindex = au_dbtop(parent); -+ au_set_dbtop(dentry, bindex); -+ au_set_dbbot(dentry, bindex); -+ err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args); -+ bindex = err; -+ if (unlikely(err < 0)) -+ goto out_parent; -+ -+ err = -EOPNOTSUPP; -+ h_dir = au_h_iptr(dir, bindex); -+ if (unlikely(!h_dir->i_op->tmpfile)) -+ goto out_parent; -+ -+ h_mnt = au_sbr_mnt(sb, bindex); -+ err = vfsub_mnt_want_write(h_mnt); -+ if (unlikely(err)) -+ goto out_parent; -+ -+ h_parent = au_h_dptr(parent, bindex); -+ h_dentry = vfs_tmpfile(h_parent, mode, /*open_flag*/0); -+ if (IS_ERR(h_dentry)) { -+ err = PTR_ERR(h_dentry); -+ goto out_mnt; -+ } -+ -+ au_set_dbtop(dentry, bindex); -+ au_set_dbbot(dentry, bindex); -+ au_set_h_dptr(dentry, bindex, dget(h_dentry)); -+ inode = au_new_inode(dentry, /*must_new*/1); -+ if (IS_ERR(inode)) { -+ err = PTR_ERR(inode); -+ au_set_h_dptr(dentry, bindex, NULL); -+ au_set_dbtop(dentry, -1); -+ au_set_dbbot(dentry, -1); -+ } else { -+ if (!inode->i_nlink) -+ set_nlink(inode, 1); -+ d_tmpfile(dentry, inode); -+ au_di(dentry)->di_tmpfile = 1; -+ -+ /* update without i_mutex */ -+ if (au_ibtop(dir) == au_dbtop(dentry)) -+ au_cpup_attr_timesizes(dir); -+ } -+ dput(h_dentry); -+ -+out_mnt: -+ vfsub_mnt_drop_write(h_mnt); -+out_parent: -+ di_write_unlock(parent); -+ dput(parent); -+ di_write_unlock(dentry); -+ if (unlikely(err)) { -+ au_di_fin(dentry); -+ dentry->d_fsdata = NULL; -+ } -+out_si: -+ si_read_unlock(sb); -+out: -+ inode_unlock(dir); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct au_link_args { -+ aufs_bindex_t bdst, bsrc; -+ struct au_pin pin; -+ struct path h_path; -+ struct dentry *src_parent, *parent; -+}; -+ -+static int au_cpup_before_link(struct dentry *src_dentry, -+ struct au_link_args *a) -+{ -+ int err; -+ struct dentry *h_src_dentry; -+ struct au_cp_generic cpg = { -+ .dentry = src_dentry, -+ .bdst = a->bdst, -+ .bsrc = a->bsrc, -+ .len = -1, -+ .pin = &a->pin, -+ .flags = AuCpup_DTIME | AuCpup_HOPEN /* | AuCpup_KEEPLINO */ -+ }; -+ -+ di_read_lock_parent(a->src_parent, AuLock_IR); -+ err = au_test_and_cpup_dirs(src_dentry, a->bdst); -+ if (unlikely(err)) -+ goto out; -+ -+ h_src_dentry = au_h_dptr(src_dentry, a->bsrc); -+ err = au_pin(&a->pin, src_dentry, a->bdst, -+ au_opt_udba(src_dentry->d_sb), -+ AuPin_DI_LOCKED | AuPin_MNT_WRITE); -+ if (unlikely(err)) -+ goto out; -+ -+ err = au_sio_cpup_simple(&cpg); -+ au_unpin(&a->pin); -+ -+out: -+ di_read_unlock(a->src_parent, AuLock_IR); -+ return err; -+} -+ -+static int au_cpup_or_link(struct dentry *src_dentry, struct dentry *dentry, -+ struct au_link_args *a) -+{ -+ int err; -+ unsigned char plink; -+ aufs_bindex_t bbot; -+ struct dentry *h_src_dentry; -+ struct inode *h_inode, *inode, *delegated; -+ struct super_block *sb; -+ struct file *h_file; -+ -+ plink = 0; -+ h_inode = NULL; -+ sb = src_dentry->d_sb; -+ inode = d_inode(src_dentry); -+ if (au_ibtop(inode) <= a->bdst) -+ h_inode = au_h_iptr(inode, a->bdst); -+ if (!h_inode || !h_inode->i_nlink) { -+ /* copyup src_dentry as the name of dentry. */ -+ bbot = au_dbbot(dentry); -+ if (bbot < a->bsrc) -+ au_set_dbbot(dentry, a->bsrc); -+ au_set_h_dptr(dentry, a->bsrc, -+ dget(au_h_dptr(src_dentry, a->bsrc))); -+ dget(a->h_path.dentry); -+ au_set_h_dptr(dentry, a->bdst, NULL); -+ AuDbg("temporary d_inode...\n"); -+ spin_lock(&dentry->d_lock); -+ dentry->d_inode = d_inode(src_dentry); /* tmp */ -+ spin_unlock(&dentry->d_lock); -+ h_file = au_h_open_pre(dentry, a->bsrc, /*force_wr*/0); -+ if (IS_ERR(h_file)) -+ err = PTR_ERR(h_file); -+ else { -+ struct au_cp_generic cpg = { -+ .dentry = dentry, -+ .bdst = a->bdst, -+ .bsrc = -1, -+ .len = -1, -+ .pin = &a->pin, -+ .flags = AuCpup_KEEPLINO -+ }; -+ err = au_sio_cpup_simple(&cpg); -+ au_h_open_post(dentry, a->bsrc, h_file); -+ if (!err) { -+ dput(a->h_path.dentry); -+ a->h_path.dentry = au_h_dptr(dentry, a->bdst); -+ } else -+ au_set_h_dptr(dentry, a->bdst, -+ a->h_path.dentry); -+ } -+ spin_lock(&dentry->d_lock); -+ dentry->d_inode = NULL; /* restore */ -+ spin_unlock(&dentry->d_lock); -+ AuDbg("temporary d_inode...done\n"); -+ au_set_h_dptr(dentry, a->bsrc, NULL); -+ au_set_dbbot(dentry, bbot); -+ } else { -+ /* the inode of src_dentry already exists on a.bdst branch */ -+ h_src_dentry = d_find_alias(h_inode); -+ if (!h_src_dentry && au_plink_test(inode)) { -+ plink = 1; -+ h_src_dentry = au_plink_lkup(inode, a->bdst); -+ err = PTR_ERR(h_src_dentry); -+ if (IS_ERR(h_src_dentry)) -+ goto out; -+ -+ if (unlikely(d_is_negative(h_src_dentry))) { -+ dput(h_src_dentry); -+ h_src_dentry = NULL; -+ } -+ -+ } -+ if (h_src_dentry) { -+ delegated = NULL; -+ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin), -+ &a->h_path, &delegated); -+ if (unlikely(err == -EWOULDBLOCK)) { -+ pr_warn("cannot retry for NFSv4 delegation" -+ " for an internal link\n"); -+ iput(delegated); -+ } -+ dput(h_src_dentry); -+ } else { -+ AuIOErr("no dentry found for hi%lu on b%d\n", -+ h_inode->i_ino, a->bdst); -+ err = -EIO; -+ } -+ } -+ -+ if (!err && !plink) -+ au_plink_append(inode, a->bdst, a->h_path.dentry); -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+int aufs_link(struct dentry *src_dentry, struct inode *dir, -+ struct dentry *dentry) -+{ -+ int err, rerr; -+ struct au_dtime dt; -+ struct au_link_args *a; -+ struct dentry *wh_dentry, *h_src_dentry; -+ struct inode *inode, *delegated; -+ struct super_block *sb; -+ struct au_wr_dir_args wr_dir_args = { -+ /* .force_btgt = -1, */ -+ .flags = AuWrDir_ADD_ENTRY -+ }; -+ -+ IMustLock(dir); -+ inode = d_inode(src_dentry); -+ IMustLock(inode); -+ -+ err = -ENOMEM; -+ a = kzalloc(sizeof(*a), GFP_NOFS); -+ if (unlikely(!a)) -+ goto out; -+ -+ a->parent = dentry->d_parent; /* dir inode is locked */ -+ err = aufs_read_and_write_lock2(dentry, src_dentry, -+ AuLock_NOPLM | AuLock_GEN); -+ if (unlikely(err)) -+ goto out_kfree; -+ err = au_d_linkable(src_dentry); -+ if (unlikely(err)) -+ goto out_unlock; -+ err = au_d_may_add(dentry); -+ if (unlikely(err)) -+ goto out_unlock; -+ -+ a->src_parent = dget_parent(src_dentry); -+ wr_dir_args.force_btgt = au_ibtop(inode); -+ -+ di_write_lock_parent(a->parent); -+ wr_dir_args.force_btgt = au_wbr(dentry, wr_dir_args.force_btgt); -+ wh_dentry = lock_hdir_lkup_wh(dentry, &dt, src_dentry, &a->pin, -+ &wr_dir_args); -+ err = PTR_ERR(wh_dentry); -+ if (IS_ERR(wh_dentry)) -+ goto out_parent; -+ -+ err = 0; -+ sb = dentry->d_sb; -+ a->bdst = au_dbtop(dentry); -+ a->h_path.dentry = au_h_dptr(dentry, a->bdst); -+ a->h_path.mnt = au_sbr_mnt(sb, a->bdst); -+ a->bsrc = au_ibtop(inode); -+ h_src_dentry = au_h_d_alias(src_dentry, a->bsrc); -+ if (!h_src_dentry && au_di(src_dentry)->di_tmpfile) -+ h_src_dentry = dget(au_hi_wh(inode, a->bsrc)); -+ if (!h_src_dentry) { -+ a->bsrc = au_dbtop(src_dentry); -+ h_src_dentry = au_h_d_alias(src_dentry, a->bsrc); -+ AuDebugOn(!h_src_dentry); -+ } else if (IS_ERR(h_src_dentry)) { -+ err = PTR_ERR(h_src_dentry); -+ goto out_parent; -+ } -+ -+ /* -+ * aufs doesn't touch the credential so -+ * security_dentry_create_files_as() is unnecessary. -+ */ -+ if (au_opt_test(au_mntflags(sb), PLINK)) { -+ if (a->bdst < a->bsrc -+ /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */) -+ err = au_cpup_or_link(src_dentry, dentry, a); -+ else { -+ delegated = NULL; -+ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin), -+ &a->h_path, &delegated); -+ if (unlikely(err == -EWOULDBLOCK)) { -+ pr_warn("cannot retry for NFSv4 delegation" -+ " for an internal link\n"); -+ iput(delegated); -+ } -+ } -+ dput(h_src_dentry); -+ } else { -+ /* -+ * copyup src_dentry to the branch we process, -+ * and then link(2) to it. -+ */ -+ dput(h_src_dentry); -+ if (a->bdst < a->bsrc -+ /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */) { -+ au_unpin(&a->pin); -+ di_write_unlock(a->parent); -+ err = au_cpup_before_link(src_dentry, a); -+ di_write_lock_parent(a->parent); -+ if (!err) -+ err = au_pin(&a->pin, dentry, a->bdst, -+ au_opt_udba(sb), -+ AuPin_DI_LOCKED | AuPin_MNT_WRITE); -+ if (unlikely(err)) -+ goto out_wh; -+ } -+ if (!err) { -+ h_src_dentry = au_h_dptr(src_dentry, a->bdst); -+ err = -ENOENT; -+ if (h_src_dentry && d_is_positive(h_src_dentry)) { -+ delegated = NULL; -+ err = vfsub_link(h_src_dentry, -+ au_pinned_h_dir(&a->pin), -+ &a->h_path, &delegated); -+ if (unlikely(err == -EWOULDBLOCK)) { -+ pr_warn("cannot retry" -+ " for NFSv4 delegation" -+ " for an internal link\n"); -+ iput(delegated); -+ } -+ } -+ } -+ } -+ if (unlikely(err)) -+ goto out_unpin; -+ -+ if (wh_dentry) { -+ a->h_path.dentry = wh_dentry; -+ err = au_wh_unlink_dentry(au_pinned_h_dir(&a->pin), &a->h_path, -+ dentry); -+ if (unlikely(err)) -+ goto out_revert; -+ } -+ -+ au_dir_ts(dir, a->bdst); -+ inode_inc_iversion(dir); -+ inc_nlink(inode); -+ inode->i_ctime = dir->i_ctime; -+ d_instantiate(dentry, au_igrab(inode)); -+ if (d_unhashed(a->h_path.dentry)) -+ /* some filesystem calls d_drop() */ -+ d_drop(dentry); -+ /* some filesystems consume an inode even hardlink */ -+ au_fhsm_wrote(sb, a->bdst, /*force*/0); -+ goto out_unpin; /* success */ -+ -+out_revert: -+ /* no delegation since it is just created */ -+ rerr = vfsub_unlink(au_pinned_h_dir(&a->pin), &a->h_path, -+ /*delegated*/NULL, /*force*/0); -+ if (unlikely(rerr)) { -+ AuIOErr("%pd reverting failed(%d, %d)\n", dentry, err, rerr); -+ err = -EIO; -+ } -+ au_dtime_revert(&dt); -+out_unpin: -+ au_unpin(&a->pin); -+out_wh: -+ dput(wh_dentry); -+out_parent: -+ di_write_unlock(a->parent); -+ dput(a->src_parent); -+out_unlock: -+ if (unlikely(err)) { -+ au_update_dbtop(dentry); -+ d_drop(dentry); -+ } -+ aufs_read_and_write_unlock2(dentry, src_dentry); -+out_kfree: -+ au_kfree_rcu(a); -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+int aufs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) -+{ -+ int err, rerr; -+ aufs_bindex_t bindex; -+ unsigned char diropq; -+ struct path h_path; -+ struct dentry *wh_dentry, *parent, *opq_dentry; -+ struct inode *h_inode; -+ struct super_block *sb; -+ struct { -+ struct au_pin pin; -+ struct au_dtime dt; -+ } *a; /* reduce the stack usage */ -+ struct au_wr_dir_args wr_dir_args = { -+ .force_btgt = -1, -+ .flags = AuWrDir_ADD_ENTRY | AuWrDir_ISDIR -+ }; -+ -+ IMustLock(dir); -+ -+ err = -ENOMEM; -+ a = kmalloc(sizeof(*a), GFP_NOFS); -+ if (unlikely(!a)) -+ goto out; -+ -+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN); -+ if (unlikely(err)) -+ goto out_free; -+ err = au_d_may_add(dentry); -+ if (unlikely(err)) -+ goto out_unlock; -+ -+ parent = dentry->d_parent; /* dir inode is locked */ -+ di_write_lock_parent(parent); -+ wh_dentry = lock_hdir_lkup_wh(dentry, &a->dt, /*src_dentry*/NULL, -+ &a->pin, &wr_dir_args); -+ err = PTR_ERR(wh_dentry); -+ if (IS_ERR(wh_dentry)) -+ goto out_parent; -+ -+ sb = dentry->d_sb; -+ bindex = au_dbtop(dentry); -+ h_path.dentry = au_h_dptr(dentry, bindex); -+ h_path.mnt = au_sbr_mnt(sb, bindex); -+ err = vfsub_mkdir(au_pinned_h_dir(&a->pin), &h_path, mode); -+ if (unlikely(err)) -+ goto out_unpin; -+ -+ /* make the dir opaque */ -+ diropq = 0; -+ h_inode = d_inode(h_path.dentry); -+ if (wh_dentry -+ || au_opt_test(au_mntflags(sb), ALWAYS_DIROPQ)) { -+ inode_lock_nested(h_inode, AuLsc_I_CHILD); -+ opq_dentry = au_diropq_create(dentry, bindex); -+ inode_unlock(h_inode); -+ err = PTR_ERR(opq_dentry); -+ if (IS_ERR(opq_dentry)) -+ goto out_dir; -+ dput(opq_dentry); -+ diropq = 1; -+ } -+ -+ err = epilog(dir, bindex, wh_dentry, dentry); -+ if (!err) { -+ inc_nlink(dir); -+ goto out_unpin; /* success */ -+ } -+ -+ /* revert */ -+ if (diropq) { -+ AuLabel(revert opq); -+ inode_lock_nested(h_inode, AuLsc_I_CHILD); -+ rerr = au_diropq_remove(dentry, bindex); -+ inode_unlock(h_inode); -+ if (rerr) { -+ AuIOErr("%pd reverting diropq failed(%d, %d)\n", -+ dentry, err, rerr); -+ err = -EIO; -+ } -+ } -+ -+out_dir: -+ AuLabel(revert dir); -+ rerr = vfsub_rmdir(au_pinned_h_dir(&a->pin), &h_path); -+ if (rerr) { -+ AuIOErr("%pd reverting dir failed(%d, %d)\n", -+ dentry, err, rerr); -+ err = -EIO; -+ } -+ au_dtime_revert(&a->dt); -+out_unpin: -+ au_unpin(&a->pin); -+ dput(wh_dentry); -+out_parent: -+ di_write_unlock(parent); -+out_unlock: -+ if (unlikely(err)) { -+ au_update_dbtop(dentry); -+ d_drop(dentry); -+ } -+ aufs_read_unlock(dentry, AuLock_DW); -+out_free: -+ au_kfree_rcu(a); -+out: -+ return err; -+} -diff -Nurp linux-5.10-rc6/fs/aufs/i_op.c linux-5.10-rc6.aufs/fs/aufs/i_op.c ---- linux-5.10-rc6/fs/aufs/i_op.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/i_op.c 2020-12-02 21:19:51.882036788 +0200 -@@ -0,0 +1,1489 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * inode operations (except add/del/rename) -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include "aufs.h" -+ -+static int h_permission(struct inode *h_inode, int mask, -+ struct path *h_path, int brperm) -+{ -+ int err; -+ const unsigned char write_mask = !!(mask & (MAY_WRITE | MAY_APPEND)); -+ -+ err = -EPERM; -+ if (write_mask && IS_IMMUTABLE(h_inode)) -+ goto out; -+ -+ err = -EACCES; -+ if (((mask & MAY_EXEC) -+ && S_ISREG(h_inode->i_mode) -+ && (path_noexec(h_path) -+ || !(h_inode->i_mode & 0111)))) -+ goto out; -+ -+ /* -+ * - skip the lower fs test in the case of write to ro branch. -+ * - nfs dir permission write check is optimized, but a policy for -+ * link/rename requires a real check. -+ * - nfs always sets SB_POSIXACL regardless its mount option 'noacl.' -+ * in this case, generic_permission() returns -EOPNOTSUPP. -+ */ -+ if ((write_mask && !au_br_writable(brperm)) -+ || (au_test_nfs(h_inode->i_sb) && S_ISDIR(h_inode->i_mode) -+ && write_mask && !(mask & MAY_READ)) -+ || !h_inode->i_op->permission) { -+ /* AuLabel(generic_permission); */ -+ /* AuDbg("get_acl %ps\n", h_inode->i_op->get_acl); */ -+ err = generic_permission(h_inode, mask); -+ if (err == -EOPNOTSUPP && au_test_nfs_noacl(h_inode)) -+ err = h_inode->i_op->permission(h_inode, mask); -+ AuTraceErr(err); -+ } else { -+ /* AuLabel(h_inode->permission); */ -+ err = h_inode->i_op->permission(h_inode, mask); -+ AuTraceErr(err); -+ } -+ -+ if (!err) -+ err = devcgroup_inode_permission(h_inode, mask); -+ if (!err) -+ err = security_inode_permission(h_inode, mask); -+ -+out: -+ return err; -+} -+ -+static int aufs_permission(struct inode *inode, int mask) -+{ -+ int err; -+ aufs_bindex_t bindex, bbot; -+ const unsigned char isdir = !!S_ISDIR(inode->i_mode), -+ write_mask = !!(mask & (MAY_WRITE | MAY_APPEND)); -+ struct inode *h_inode; -+ struct super_block *sb; -+ struct au_branch *br; -+ -+ /* todo: support rcu-walk? */ -+ if (mask & MAY_NOT_BLOCK) -+ return -ECHILD; -+ -+ sb = inode->i_sb; -+ si_read_lock(sb, AuLock_FLUSH); -+ ii_read_lock_child(inode); -+#if 0 /* reserved for future use */ -+ /* -+ * This test may be rather 'too much' since the test is essentially done -+ * in the aufs_lookup(). Theoretically it is possible that the inode -+ * generation doesn't match to the superblock's here. But it isn't a -+ * big deal I suppose. -+ */ -+ err = au_iigen_test(inode, au_sigen(sb)); -+ if (unlikely(err)) -+ goto out; -+#endif -+ -+ if (!isdir -+ || write_mask -+ || au_opt_test(au_mntflags(sb), DIRPERM1)) { -+ err = au_busy_or_stale(); -+ h_inode = au_h_iptr(inode, au_ibtop(inode)); -+ if (unlikely(!h_inode -+ || (h_inode->i_mode & S_IFMT) -+ != (inode->i_mode & S_IFMT))) -+ goto out; -+ -+ err = 0; -+ bindex = au_ibtop(inode); -+ br = au_sbr(sb, bindex); -+ err = h_permission(h_inode, mask, &br->br_path, br->br_perm); -+ if (write_mask -+ && !err -+ && !special_file(h_inode->i_mode)) { -+ /* test whether the upper writable branch exists */ -+ err = -EROFS; -+ for (; bindex >= 0; bindex--) -+ if (!au_br_rdonly(au_sbr(sb, bindex))) { -+ err = 0; -+ break; -+ } -+ } -+ goto out; -+ } -+ -+ /* non-write to dir */ -+ err = 0; -+ bbot = au_ibbot(inode); -+ for (bindex = au_ibtop(inode); !err && bindex <= bbot; bindex++) { -+ h_inode = au_h_iptr(inode, bindex); -+ if (h_inode) { -+ err = au_busy_or_stale(); -+ if (unlikely(!S_ISDIR(h_inode->i_mode))) -+ break; -+ -+ br = au_sbr(sb, bindex); -+ err = h_permission(h_inode, mask, &br->br_path, -+ br->br_perm); -+ } -+ } -+ -+out: -+ ii_read_unlock(inode); -+ si_read_unlock(sb); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static struct dentry *aufs_lookup(struct inode *dir, struct dentry *dentry, -+ unsigned int flags) -+{ -+ struct dentry *ret, *parent; -+ struct inode *inode; -+ struct super_block *sb; -+ int err, npositive; -+ -+ IMustLock(dir); -+ -+ /* todo: support rcu-walk? */ -+ ret = ERR_PTR(-ECHILD); -+ if (flags & LOOKUP_RCU) -+ goto out; -+ -+ ret = ERR_PTR(-ENAMETOOLONG); -+ if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN)) -+ goto out; -+ -+ sb = dir->i_sb; -+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM); -+ ret = ERR_PTR(err); -+ if (unlikely(err)) -+ goto out; -+ -+ err = au_di_init(dentry); -+ ret = ERR_PTR(err); -+ if (unlikely(err)) -+ goto out_si; -+ -+ inode = NULL; -+ npositive = 0; /* suppress a warning */ -+ parent = dentry->d_parent; /* dir inode is locked */ -+ di_read_lock_parent(parent, AuLock_IR); -+ err = au_alive_dir(parent); -+ if (!err) -+ err = au_digen_test(parent, au_sigen(sb)); -+ if (!err) { -+ /* regardless LOOKUP_CREATE, always ALLOW_NEG */ -+ npositive = au_lkup_dentry(dentry, au_dbtop(parent), -+ AuLkup_ALLOW_NEG); -+ err = npositive; -+ } -+ di_read_unlock(parent, AuLock_IR); -+ ret = ERR_PTR(err); -+ if (unlikely(err < 0)) -+ goto out_unlock; -+ -+ if (npositive) { -+ inode = au_new_inode(dentry, /*must_new*/0); -+ if (IS_ERR(inode)) { -+ ret = (void *)inode; -+ inode = NULL; -+ goto out_unlock; -+ } -+ } -+ -+ if (inode) -+ atomic_inc(&inode->i_count); -+ ret = d_splice_alias(inode, dentry); -+#if 0 /* reserved for future use */ -+ if (unlikely(d_need_lookup(dentry))) { -+ spin_lock(&dentry->d_lock); -+ dentry->d_flags &= ~DCACHE_NEED_LOOKUP; -+ spin_unlock(&dentry->d_lock); -+ } else -+#endif -+ if (inode) { -+ if (!IS_ERR(ret)) { -+ iput(inode); -+ if (ret && ret != dentry) -+ ii_write_unlock(inode); -+ } else { -+ ii_write_unlock(inode); -+ iput(inode); -+ inode = NULL; -+ } -+ } -+ -+out_unlock: -+ di_write_unlock(dentry); -+out_si: -+ si_read_unlock(sb); -+out: -+ return ret; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * very dirty and complicated aufs ->atomic_open(). -+ * aufs_atomic_open() -+ * + au_aopen_or_create() -+ * + add_simple() -+ * + vfsub_atomic_open() -+ * + branch fs ->atomic_open() -+ * may call the actual 'open' for h_file -+ * + inc br_nfiles only if opened -+ * + au_aopen_no_open() or au_aopen_do_open() -+ * -+ * au_aopen_do_open() -+ * + finish_open() -+ * + au_do_aopen() -+ * + au_do_open() the body of all 'open' -+ * + au_do_open_nondir() -+ * set the passed h_file -+ * -+ * au_aopen_no_open() -+ * + finish_no_open() -+ */ -+ -+struct aopen_node { -+ struct hlist_bl_node hblist; -+ struct file *file, *h_file; -+}; -+ -+static int au_do_aopen(struct inode *inode, struct file *file) -+{ -+ struct hlist_bl_head *aopen; -+ struct hlist_bl_node *pos; -+ struct aopen_node *node; -+ struct au_do_open_args args = { -+ .aopen = 1, -+ .open = au_do_open_nondir -+ }; -+ -+ aopen = &au_sbi(inode->i_sb)->si_aopen; -+ hlist_bl_lock(aopen); -+ hlist_bl_for_each_entry(node, pos, aopen, hblist) -+ if (node->file == file) { -+ args.h_file = node->h_file; -+ break; -+ } -+ hlist_bl_unlock(aopen); -+ /* AuDebugOn(!args.h_file); */ -+ -+ return au_do_open(file, &args); -+} -+ -+static int au_aopen_do_open(struct file *file, struct dentry *dentry, -+ struct aopen_node *aopen_node) -+{ -+ int err; -+ struct hlist_bl_head *aopen; -+ -+ AuLabel(here); -+ aopen = &au_sbi(dentry->d_sb)->si_aopen; -+ au_hbl_add(&aopen_node->hblist, aopen); -+ err = finish_open(file, dentry, au_do_aopen); -+ au_hbl_del(&aopen_node->hblist, aopen); -+ /* AuDbgFile(file); */ -+ AuDbg("%pd%s%s\n", dentry, -+ (file->f_mode & FMODE_CREATED) ? " created" : "", -+ (file->f_mode & FMODE_OPENED) ? " opened" : ""); -+ -+ AuTraceErr(err); -+ return err; -+} -+ -+static int au_aopen_no_open(struct file *file, struct dentry *dentry) -+{ -+ int err; -+ -+ AuLabel(here); -+ dget(dentry); -+ err = finish_no_open(file, dentry); -+ -+ AuTraceErr(err); -+ return err; -+} -+ -+static int aufs_atomic_open(struct inode *dir, struct dentry *dentry, -+ struct file *file, unsigned int open_flag, -+ umode_t create_mode) -+{ -+ int err, did_open; -+ unsigned int lkup_flags; -+ aufs_bindex_t bindex; -+ struct super_block *sb; -+ struct dentry *parent, *d; -+ struct vfsub_aopen_args args = { -+ .open_flag = open_flag, -+ .create_mode = create_mode -+ }; -+ struct aopen_node aopen_node = { -+ .file = file -+ }; -+ -+ IMustLock(dir); -+ AuDbg("open_flag 0%o\n", open_flag); -+ AuDbgDentry(dentry); -+ -+ err = 0; -+ if (!au_di(dentry)) { -+ lkup_flags = LOOKUP_OPEN; -+ if (open_flag & O_CREAT) -+ lkup_flags |= LOOKUP_CREATE; -+ d = aufs_lookup(dir, dentry, lkup_flags); -+ if (IS_ERR(d)) { -+ err = PTR_ERR(d); -+ AuTraceErr(err); -+ goto out; -+ } else if (d) { -+ /* -+ * obsoleted dentry found. -+ * another error will be returned later. -+ */ -+ d_drop(d); -+ AuDbgDentry(d); -+ dput(d); -+ } -+ AuDbgDentry(dentry); -+ } -+ -+ if (d_is_positive(dentry) -+ || d_unhashed(dentry) -+ || d_unlinked(dentry) -+ || !(open_flag & O_CREAT)) { -+ err = au_aopen_no_open(file, dentry); -+ goto out; /* success */ -+ } -+ -+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH | AuLock_GEN); -+ if (unlikely(err)) -+ goto out; -+ -+ sb = dentry->d_sb; -+ parent = dentry->d_parent; /* dir is locked */ -+ di_write_lock_parent(parent); -+ err = au_lkup_dentry(dentry, /*btop*/0, AuLkup_ALLOW_NEG); -+ if (unlikely(err < 0)) -+ goto out_parent; -+ -+ AuDbgDentry(dentry); -+ if (d_is_positive(dentry)) { -+ err = au_aopen_no_open(file, dentry); -+ goto out_parent; /* success */ -+ } -+ -+ args.file = alloc_empty_file(file->f_flags, current_cred()); -+ err = PTR_ERR(args.file); -+ if (IS_ERR(args.file)) -+ goto out_parent; -+ -+ bindex = au_dbtop(dentry); -+ err = au_aopen_or_create(dir, dentry, &args); -+ AuTraceErr(err); -+ AuDbgFile(args.file); -+ file->f_mode = args.file->f_mode & ~FMODE_OPENED; -+ did_open = !!(args.file->f_mode & FMODE_OPENED); -+ if (!did_open) { -+ fput(args.file); -+ args.file = NULL; -+ } -+ di_write_unlock(parent); -+ di_write_unlock(dentry); -+ if (unlikely(err < 0)) { -+ if (args.file) -+ fput(args.file); -+ goto out_sb; -+ } -+ -+ if (!did_open) -+ err = au_aopen_no_open(file, dentry); -+ else { -+ aopen_node.h_file = args.file; -+ err = au_aopen_do_open(file, dentry, &aopen_node); -+ } -+ if (unlikely(err < 0)) { -+ if (args.file) -+ fput(args.file); -+ if (did_open) -+ au_lcnt_dec(&args.br->br_nfiles); -+ } -+ goto out_sb; /* success */ -+ -+out_parent: -+ di_write_unlock(parent); -+ di_write_unlock(dentry); -+out_sb: -+ si_read_unlock(sb); -+out: -+ AuTraceErr(err); -+ AuDbgFile(file); -+ return err; -+} -+ -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int au_wr_dir_cpup(struct dentry *dentry, struct dentry *parent, -+ const unsigned char add_entry, aufs_bindex_t bcpup, -+ aufs_bindex_t btop) -+{ -+ int err; -+ struct dentry *h_parent; -+ struct inode *h_dir; -+ -+ if (add_entry) -+ IMustLock(d_inode(parent)); -+ else -+ di_write_lock_parent(parent); -+ -+ err = 0; -+ if (!au_h_dptr(parent, bcpup)) { -+ if (btop > bcpup) -+ err = au_cpup_dirs(dentry, bcpup); -+ else if (btop < bcpup) -+ err = au_cpdown_dirs(dentry, bcpup); -+ else -+ BUG(); -+ } -+ if (!err && add_entry && !au_ftest_wrdir(add_entry, TMPFILE)) { -+ h_parent = au_h_dptr(parent, bcpup); -+ h_dir = d_inode(h_parent); -+ inode_lock_shared_nested(h_dir, AuLsc_I_PARENT); -+ err = au_lkup_neg(dentry, bcpup, /*wh*/0); -+ /* todo: no unlock here */ -+ inode_unlock_shared(h_dir); -+ -+ AuDbg("bcpup %d\n", bcpup); -+ if (!err) { -+ if (d_really_is_negative(dentry)) -+ au_set_h_dptr(dentry, btop, NULL); -+ au_update_dbrange(dentry, /*do_put_zero*/0); -+ } -+ } -+ -+ if (!add_entry) -+ di_write_unlock(parent); -+ if (!err) -+ err = bcpup; /* success */ -+ -+ AuTraceErr(err); -+ return err; -+} -+ -+/* -+ * decide the branch and the parent dir where we will create a new entry. -+ * returns new bindex or an error. -+ * copyup the parent dir if needed. -+ */ -+int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry, -+ struct au_wr_dir_args *args) -+{ -+ int err; -+ unsigned int flags; -+ aufs_bindex_t bcpup, btop, src_btop; -+ const unsigned char add_entry -+ = au_ftest_wrdir(args->flags, ADD_ENTRY) -+ | au_ftest_wrdir(args->flags, TMPFILE); -+ struct super_block *sb; -+ struct dentry *parent; -+ struct au_sbinfo *sbinfo; -+ -+ sb = dentry->d_sb; -+ sbinfo = au_sbi(sb); -+ parent = dget_parent(dentry); -+ btop = au_dbtop(dentry); -+ bcpup = btop; -+ if (args->force_btgt < 0) { -+ if (src_dentry) { -+ src_btop = au_dbtop(src_dentry); -+ if (src_btop < btop) -+ bcpup = src_btop; -+ } else if (add_entry) { -+ flags = 0; -+ if (au_ftest_wrdir(args->flags, ISDIR)) -+ au_fset_wbr(flags, DIR); -+ err = AuWbrCreate(sbinfo, dentry, flags); -+ bcpup = err; -+ } -+ -+ if (bcpup < 0 || au_test_ro(sb, bcpup, d_inode(dentry))) { -+ if (add_entry) -+ err = AuWbrCopyup(sbinfo, dentry); -+ else { -+ if (!IS_ROOT(dentry)) { -+ di_read_lock_parent(parent, !AuLock_IR); -+ err = AuWbrCopyup(sbinfo, dentry); -+ di_read_unlock(parent, !AuLock_IR); -+ } else -+ err = AuWbrCopyup(sbinfo, dentry); -+ } -+ bcpup = err; -+ if (unlikely(err < 0)) -+ goto out; -+ } -+ } else { -+ bcpup = args->force_btgt; -+ AuDebugOn(au_test_ro(sb, bcpup, d_inode(dentry))); -+ } -+ -+ AuDbg("btop %d, bcpup %d\n", btop, bcpup); -+ err = bcpup; -+ if (bcpup == btop) -+ goto out; /* success */ -+ -+ /* copyup the new parent into the branch we process */ -+ err = au_wr_dir_cpup(dentry, parent, add_entry, bcpup, btop); -+ if (err >= 0) { -+ if (d_really_is_negative(dentry)) { -+ au_set_h_dptr(dentry, btop, NULL); -+ au_set_dbtop(dentry, bcpup); -+ au_set_dbbot(dentry, bcpup); -+ } -+ AuDebugOn(add_entry -+ && !au_ftest_wrdir(args->flags, TMPFILE) -+ && !au_h_dptr(dentry, bcpup)); -+ } -+ -+out: -+ dput(parent); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+void au_pin_hdir_unlock(struct au_pin *p) -+{ -+ if (p->hdir) -+ au_hn_inode_unlock(p->hdir); -+} -+ -+int au_pin_hdir_lock(struct au_pin *p) -+{ -+ int err; -+ -+ err = 0; -+ if (!p->hdir) -+ goto out; -+ -+ /* even if an error happens later, keep this lock */ -+ au_hn_inode_lock_nested(p->hdir, p->lsc_hi); -+ -+ err = -EBUSY; -+ if (unlikely(p->hdir->hi_inode != d_inode(p->h_parent))) -+ goto out; -+ -+ err = 0; -+ if (p->h_dentry) -+ err = au_h_verify(p->h_dentry, p->udba, p->hdir->hi_inode, -+ p->h_parent, p->br); -+ -+out: -+ return err; -+} -+ -+int au_pin_hdir_relock(struct au_pin *p) -+{ -+ int err, i; -+ struct inode *h_i; -+ struct dentry *h_d[] = { -+ p->h_dentry, -+ p->h_parent -+ }; -+ -+ err = au_pin_hdir_lock(p); -+ if (unlikely(err)) -+ goto out; -+ -+ for (i = 0; !err && i < sizeof(h_d)/sizeof(*h_d); i++) { -+ if (!h_d[i]) -+ continue; -+ if (d_is_positive(h_d[i])) { -+ h_i = d_inode(h_d[i]); -+ err = !h_i->i_nlink; -+ } -+ } -+ -+out: -+ return err; -+} -+ -+static void au_pin_hdir_set_owner(struct au_pin *p, struct task_struct *task) -+{ -+ atomic_long_set(&p->hdir->hi_inode->i_rwsem.owner, (long)task); -+} -+ -+void au_pin_hdir_acquire_nest(struct au_pin *p) -+{ -+ if (p->hdir) { -+ rwsem_acquire_nest(&p->hdir->hi_inode->i_rwsem.dep_map, -+ p->lsc_hi, 0, NULL, _RET_IP_); -+ au_pin_hdir_set_owner(p, current); -+ } -+} -+ -+void au_pin_hdir_release(struct au_pin *p) -+{ -+ if (p->hdir) { -+ au_pin_hdir_set_owner(p, p->task); -+ rwsem_release(&p->hdir->hi_inode->i_rwsem.dep_map, _RET_IP_); -+ } -+} -+ -+struct dentry *au_pinned_h_parent(struct au_pin *pin) -+{ -+ if (pin && pin->parent) -+ return au_h_dptr(pin->parent, pin->bindex); -+ return NULL; -+} -+ -+void au_unpin(struct au_pin *p) -+{ -+ if (p->hdir) -+ au_pin_hdir_unlock(p); -+ if (p->h_mnt && au_ftest_pin(p->flags, MNT_WRITE)) -+ vfsub_mnt_drop_write(p->h_mnt); -+ if (!p->hdir) -+ return; -+ -+ if (!au_ftest_pin(p->flags, DI_LOCKED)) -+ di_read_unlock(p->parent, AuLock_IR); -+ iput(p->hdir->hi_inode); -+ dput(p->parent); -+ p->parent = NULL; -+ p->hdir = NULL; -+ p->h_mnt = NULL; -+ /* do not clear p->task */ -+} -+ -+int au_do_pin(struct au_pin *p) -+{ -+ int err; -+ struct super_block *sb; -+ struct inode *h_dir; -+ -+ err = 0; -+ sb = p->dentry->d_sb; -+ p->br = au_sbr(sb, p->bindex); -+ if (IS_ROOT(p->dentry)) { -+ if (au_ftest_pin(p->flags, MNT_WRITE)) { -+ p->h_mnt = au_br_mnt(p->br); -+ err = vfsub_mnt_want_write(p->h_mnt); -+ if (unlikely(err)) { -+ au_fclr_pin(p->flags, MNT_WRITE); -+ goto out_err; -+ } -+ } -+ goto out; -+ } -+ -+ p->h_dentry = NULL; -+ if (p->bindex <= au_dbbot(p->dentry)) -+ p->h_dentry = au_h_dptr(p->dentry, p->bindex); -+ -+ p->parent = dget_parent(p->dentry); -+ if (!au_ftest_pin(p->flags, DI_LOCKED)) -+ di_read_lock(p->parent, AuLock_IR, p->lsc_di); -+ -+ h_dir = NULL; -+ p->h_parent = au_h_dptr(p->parent, p->bindex); -+ p->hdir = au_hi(d_inode(p->parent), p->bindex); -+ if (p->hdir) -+ h_dir = p->hdir->hi_inode; -+ -+ /* -+ * udba case, or -+ * if DI_LOCKED is not set, then p->parent may be different -+ * and h_parent can be NULL. -+ */ -+ if (unlikely(!p->hdir || !h_dir || !p->h_parent)) { -+ err = -EBUSY; -+ if (!au_ftest_pin(p->flags, DI_LOCKED)) -+ di_read_unlock(p->parent, AuLock_IR); -+ dput(p->parent); -+ p->parent = NULL; -+ goto out_err; -+ } -+ -+ if (au_ftest_pin(p->flags, MNT_WRITE)) { -+ p->h_mnt = au_br_mnt(p->br); -+ err = vfsub_mnt_want_write(p->h_mnt); -+ if (unlikely(err)) { -+ au_fclr_pin(p->flags, MNT_WRITE); -+ if (!au_ftest_pin(p->flags, DI_LOCKED)) -+ di_read_unlock(p->parent, AuLock_IR); -+ dput(p->parent); -+ p->parent = NULL; -+ goto out_err; -+ } -+ } -+ -+ au_igrab(h_dir); -+ err = au_pin_hdir_lock(p); -+ if (!err) -+ goto out; /* success */ -+ -+ au_unpin(p); -+ -+out_err: -+ pr_err("err %d\n", err); -+ err = au_busy_or_stale(); -+out: -+ return err; -+} -+ -+void au_pin_init(struct au_pin *p, struct dentry *dentry, -+ aufs_bindex_t bindex, int lsc_di, int lsc_hi, -+ unsigned int udba, unsigned char flags) -+{ -+ p->dentry = dentry; -+ p->udba = udba; -+ p->lsc_di = lsc_di; -+ p->lsc_hi = lsc_hi; -+ p->flags = flags; -+ p->bindex = bindex; -+ -+ p->parent = NULL; -+ p->hdir = NULL; -+ p->h_mnt = NULL; -+ -+ p->h_dentry = NULL; -+ p->h_parent = NULL; -+ p->br = NULL; -+ p->task = current; -+} -+ -+int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex, -+ unsigned int udba, unsigned char flags) -+{ -+ au_pin_init(pin, dentry, bindex, AuLsc_DI_PARENT, AuLsc_I_PARENT2, -+ udba, flags); -+ return au_do_pin(pin); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * ->setattr() and ->getattr() are called in various cases. -+ * chmod, stat: dentry is revalidated. -+ * fchmod, fstat: file and dentry are not revalidated, additionally they may be -+ * unhashed. -+ * for ->setattr(), ia->ia_file is passed from ftruncate only. -+ */ -+/* todo: consolidate with do_refresh() and simple_reval_dpath() */ -+int au_reval_for_attr(struct dentry *dentry, unsigned int sigen) -+{ -+ int err; -+ struct dentry *parent; -+ -+ err = 0; -+ if (au_digen_test(dentry, sigen)) { -+ parent = dget_parent(dentry); -+ di_read_lock_parent(parent, AuLock_IR); -+ err = au_refresh_dentry(dentry, parent); -+ di_read_unlock(parent, AuLock_IR); -+ dput(parent); -+ } -+ -+ AuTraceErr(err); -+ return err; -+} -+ -+int au_pin_and_icpup(struct dentry *dentry, struct iattr *ia, -+ struct au_icpup_args *a) -+{ -+ int err; -+ loff_t sz; -+ aufs_bindex_t btop, ibtop; -+ struct dentry *hi_wh, *parent; -+ struct inode *inode; -+ struct au_wr_dir_args wr_dir_args = { -+ .force_btgt = -1, -+ .flags = 0 -+ }; -+ -+ if (d_is_dir(dentry)) -+ au_fset_wrdir(wr_dir_args.flags, ISDIR); -+ /* plink or hi_wh() case */ -+ btop = au_dbtop(dentry); -+ inode = d_inode(dentry); -+ ibtop = au_ibtop(inode); -+ if (btop != ibtop && !au_test_ro(inode->i_sb, ibtop, inode)) -+ wr_dir_args.force_btgt = ibtop; -+ err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args); -+ if (unlikely(err < 0)) -+ goto out; -+ a->btgt = err; -+ if (err != btop) -+ au_fset_icpup(a->flags, DID_CPUP); -+ -+ err = 0; -+ a->pin_flags = AuPin_MNT_WRITE; -+ parent = NULL; -+ if (!IS_ROOT(dentry)) { -+ au_fset_pin(a->pin_flags, DI_LOCKED); -+ parent = dget_parent(dentry); -+ di_write_lock_parent(parent); -+ } -+ -+ err = au_pin(&a->pin, dentry, a->btgt, a->udba, a->pin_flags); -+ if (unlikely(err)) -+ goto out_parent; -+ -+ sz = -1; -+ a->h_path.dentry = au_h_dptr(dentry, btop); -+ a->h_inode = d_inode(a->h_path.dentry); -+ if (ia && (ia->ia_valid & ATTR_SIZE)) { -+ inode_lock_shared_nested(a->h_inode, AuLsc_I_CHILD); -+ if (ia->ia_size < i_size_read(a->h_inode)) -+ sz = ia->ia_size; -+ inode_unlock_shared(a->h_inode); -+ } -+ -+ hi_wh = NULL; -+ if (au_ftest_icpup(a->flags, DID_CPUP) && d_unlinked(dentry)) { -+ hi_wh = au_hi_wh(inode, a->btgt); -+ if (!hi_wh) { -+ struct au_cp_generic cpg = { -+ .dentry = dentry, -+ .bdst = a->btgt, -+ .bsrc = -1, -+ .len = sz, -+ .pin = &a->pin -+ }; -+ err = au_sio_cpup_wh(&cpg, /*file*/NULL); -+ if (unlikely(err)) -+ goto out_unlock; -+ hi_wh = au_hi_wh(inode, a->btgt); -+ /* todo: revalidate hi_wh? */ -+ } -+ } -+ -+ if (parent) { -+ au_pin_set_parent_lflag(&a->pin, /*lflag*/0); -+ di_downgrade_lock(parent, AuLock_IR); -+ dput(parent); -+ parent = NULL; -+ } -+ if (!au_ftest_icpup(a->flags, DID_CPUP)) -+ goto out; /* success */ -+ -+ if (!d_unhashed(dentry)) { -+ struct au_cp_generic cpg = { -+ .dentry = dentry, -+ .bdst = a->btgt, -+ .bsrc = btop, -+ .len = sz, -+ .pin = &a->pin, -+ .flags = AuCpup_DTIME | AuCpup_HOPEN -+ }; -+ err = au_sio_cpup_simple(&cpg); -+ if (!err) -+ a->h_path.dentry = au_h_dptr(dentry, a->btgt); -+ } else if (!hi_wh) -+ a->h_path.dentry = au_h_dptr(dentry, a->btgt); -+ else -+ a->h_path.dentry = hi_wh; /* do not dget here */ -+ -+out_unlock: -+ a->h_inode = d_inode(a->h_path.dentry); -+ if (!err) -+ goto out; /* success */ -+ au_unpin(&a->pin); -+out_parent: -+ if (parent) { -+ di_write_unlock(parent); -+ dput(parent); -+ } -+out: -+ if (!err) -+ inode_lock_nested(a->h_inode, AuLsc_I_CHILD); -+ return err; -+} -+ -+static int aufs_setattr(struct dentry *dentry, struct iattr *ia) -+{ -+ int err; -+ struct inode *inode, *delegated; -+ struct super_block *sb; -+ struct file *file; -+ struct au_icpup_args *a; -+ -+ inode = d_inode(dentry); -+ IMustLock(inode); -+ -+ err = setattr_prepare(dentry, ia); -+ if (unlikely(err)) -+ goto out; -+ -+ err = -ENOMEM; -+ a = kzalloc(sizeof(*a), GFP_NOFS); -+ if (unlikely(!a)) -+ goto out; -+ -+ if (ia->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID)) -+ ia->ia_valid &= ~ATTR_MODE; -+ -+ file = NULL; -+ sb = dentry->d_sb; -+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM); -+ if (unlikely(err)) -+ goto out_kfree; -+ -+ if (ia->ia_valid & ATTR_FILE) { -+ /* currently ftruncate(2) only */ -+ AuDebugOn(!d_is_reg(dentry)); -+ file = ia->ia_file; -+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1, -+ /*fi_lsc*/0); -+ if (unlikely(err)) -+ goto out_si; -+ ia->ia_file = au_hf_top(file); -+ a->udba = AuOpt_UDBA_NONE; -+ } else { -+ /* fchmod() doesn't pass ia_file */ -+ a->udba = au_opt_udba(sb); -+ di_write_lock_child(dentry); -+ /* no d_unlinked(), to set UDBA_NONE for root */ -+ if (d_unhashed(dentry)) -+ a->udba = AuOpt_UDBA_NONE; -+ if (a->udba != AuOpt_UDBA_NONE) { -+ AuDebugOn(IS_ROOT(dentry)); -+ err = au_reval_for_attr(dentry, au_sigen(sb)); -+ if (unlikely(err)) -+ goto out_dentry; -+ } -+ } -+ -+ err = au_pin_and_icpup(dentry, ia, a); -+ if (unlikely(err < 0)) -+ goto out_dentry; -+ if (au_ftest_icpup(a->flags, DID_CPUP)) { -+ ia->ia_file = NULL; -+ ia->ia_valid &= ~ATTR_FILE; -+ } -+ -+ a->h_path.mnt = au_sbr_mnt(sb, a->btgt); -+ if ((ia->ia_valid & (ATTR_MODE | ATTR_CTIME)) -+ == (ATTR_MODE | ATTR_CTIME)) { -+ err = security_path_chmod(&a->h_path, ia->ia_mode); -+ if (unlikely(err)) -+ goto out_unlock; -+ } else if ((ia->ia_valid & (ATTR_UID | ATTR_GID)) -+ && (ia->ia_valid & ATTR_CTIME)) { -+ err = security_path_chown(&a->h_path, ia->ia_uid, ia->ia_gid); -+ if (unlikely(err)) -+ goto out_unlock; -+ } -+ -+ if (ia->ia_valid & ATTR_SIZE) { -+ struct file *f; -+ -+ if (ia->ia_size < i_size_read(inode)) -+ /* unmap only */ -+ truncate_setsize(inode, ia->ia_size); -+ -+ f = NULL; -+ if (ia->ia_valid & ATTR_FILE) -+ f = ia->ia_file; -+ inode_unlock(a->h_inode); -+ err = vfsub_trunc(&a->h_path, ia->ia_size, ia->ia_valid, f); -+ inode_lock_nested(a->h_inode, AuLsc_I_CHILD); -+ } else { -+ delegated = NULL; -+ while (1) { -+ err = vfsub_notify_change(&a->h_path, ia, &delegated); -+ if (delegated) { -+ err = break_deleg_wait(&delegated); -+ if (!err) -+ continue; -+ } -+ break; -+ } -+ } -+ /* -+ * regardless aufs 'acl' option setting. -+ * why don't all acl-aware fs call this func from their ->setattr()? -+ */ -+ if (!err && (ia->ia_valid & ATTR_MODE)) -+ err = vfsub_acl_chmod(a->h_inode, ia->ia_mode); -+ if (!err) -+ au_cpup_attr_changeable(inode); -+ -+out_unlock: -+ inode_unlock(a->h_inode); -+ au_unpin(&a->pin); -+ if (unlikely(err)) -+ au_update_dbtop(dentry); -+out_dentry: -+ di_write_unlock(dentry); -+ if (file) { -+ fi_write_unlock(file); -+ ia->ia_file = file; -+ ia->ia_valid |= ATTR_FILE; -+ } -+out_si: -+ si_read_unlock(sb); -+out_kfree: -+ au_kfree_rcu(a); -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+#if IS_ENABLED(CONFIG_AUFS_XATTR) || IS_ENABLED(CONFIG_FS_POSIX_ACL) -+static int au_h_path_to_set_attr(struct dentry *dentry, -+ struct au_icpup_args *a, struct path *h_path) -+{ -+ int err; -+ struct super_block *sb; -+ -+ sb = dentry->d_sb; -+ a->udba = au_opt_udba(sb); -+ /* no d_unlinked(), to set UDBA_NONE for root */ -+ if (d_unhashed(dentry)) -+ a->udba = AuOpt_UDBA_NONE; -+ if (a->udba != AuOpt_UDBA_NONE) { -+ AuDebugOn(IS_ROOT(dentry)); -+ err = au_reval_for_attr(dentry, au_sigen(sb)); -+ if (unlikely(err)) -+ goto out; -+ } -+ err = au_pin_and_icpup(dentry, /*ia*/NULL, a); -+ if (unlikely(err < 0)) -+ goto out; -+ -+ h_path->dentry = a->h_path.dentry; -+ h_path->mnt = au_sbr_mnt(sb, a->btgt); -+ -+out: -+ return err; -+} -+ -+ssize_t au_sxattr(struct dentry *dentry, struct inode *inode, -+ struct au_sxattr *arg) -+{ -+ int err; -+ struct path h_path; -+ struct super_block *sb; -+ struct au_icpup_args *a; -+ struct inode *h_inode; -+ -+ IMustLock(inode); -+ -+ err = -ENOMEM; -+ a = kzalloc(sizeof(*a), GFP_NOFS); -+ if (unlikely(!a)) -+ goto out; -+ -+ sb = dentry->d_sb; -+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM); -+ if (unlikely(err)) -+ goto out_kfree; -+ -+ h_path.dentry = NULL; /* silence gcc */ -+ di_write_lock_child(dentry); -+ err = au_h_path_to_set_attr(dentry, a, &h_path); -+ if (unlikely(err)) -+ goto out_di; -+ -+ inode_unlock(a->h_inode); -+ switch (arg->type) { -+ case AU_XATTR_SET: -+ AuDebugOn(d_is_negative(h_path.dentry)); -+ err = vfsub_setxattr(h_path.dentry, -+ arg->u.set.name, arg->u.set.value, -+ arg->u.set.size, arg->u.set.flags); -+ break; -+ case AU_ACL_SET: -+ err = -EOPNOTSUPP; -+ h_inode = d_inode(h_path.dentry); -+ if (h_inode->i_op->set_acl) -+ /* this will call posix_acl_update_mode */ -+ err = h_inode->i_op->set_acl(h_inode, -+ arg->u.acl_set.acl, -+ arg->u.acl_set.type); -+ break; -+ } -+ if (!err) -+ au_cpup_attr_timesizes(inode); -+ -+ au_unpin(&a->pin); -+ if (unlikely(err)) -+ au_update_dbtop(dentry); -+ -+out_di: -+ di_write_unlock(dentry); -+ si_read_unlock(sb); -+out_kfree: -+ au_kfree_rcu(a); -+out: -+ AuTraceErr(err); -+ return err; -+} -+#endif -+ -+static void au_refresh_iattr(struct inode *inode, struct kstat *st, -+ unsigned int nlink) -+{ -+ unsigned int n; -+ -+ inode->i_mode = st->mode; -+ /* don't i_[ug]id_write() here */ -+ inode->i_uid = st->uid; -+ inode->i_gid = st->gid; -+ inode->i_atime = st->atime; -+ inode->i_mtime = st->mtime; -+ inode->i_ctime = st->ctime; -+ -+ au_cpup_attr_nlink(inode, /*force*/0); -+ if (S_ISDIR(inode->i_mode)) { -+ n = inode->i_nlink; -+ n -= nlink; -+ n += st->nlink; -+ smp_mb(); /* for i_nlink */ -+ /* 0 can happen */ -+ set_nlink(inode, n); -+ } -+ -+ spin_lock(&inode->i_lock); -+ inode->i_blocks = st->blocks; -+ i_size_write(inode, st->size); -+ spin_unlock(&inode->i_lock); -+} -+ -+/* -+ * common routine for aufs_getattr() and au_getxattr(). -+ * returns zero or negative (an error). -+ * @dentry will be read-locked in success. -+ */ -+int au_h_path_getattr(struct dentry *dentry, struct inode *inode, int force, -+ struct path *h_path, int locked) -+{ -+ int err; -+ unsigned int mnt_flags, sigen; -+ unsigned char udba_none; -+ aufs_bindex_t bindex; -+ struct super_block *sb, *h_sb; -+ -+ h_path->mnt = NULL; -+ h_path->dentry = NULL; -+ -+ err = 0; -+ sb = dentry->d_sb; -+ mnt_flags = au_mntflags(sb); -+ udba_none = !!au_opt_test(mnt_flags, UDBA_NONE); -+ -+ if (unlikely(locked)) -+ goto body; /* skip locking dinfo */ -+ -+ /* support fstat(2) */ -+ if (!d_unlinked(dentry) && !udba_none) { -+ sigen = au_sigen(sb); -+ err = au_digen_test(dentry, sigen); -+ if (!err) { -+ di_read_lock_child(dentry, AuLock_IR); -+ err = au_dbrange_test(dentry); -+ if (unlikely(err)) { -+ di_read_unlock(dentry, AuLock_IR); -+ goto out; -+ } -+ } else { -+ AuDebugOn(IS_ROOT(dentry)); -+ di_write_lock_child(dentry); -+ err = au_dbrange_test(dentry); -+ if (!err) -+ err = au_reval_for_attr(dentry, sigen); -+ if (!err) -+ di_downgrade_lock(dentry, AuLock_IR); -+ else { -+ di_write_unlock(dentry); -+ goto out; -+ } -+ } -+ } else -+ di_read_lock_child(dentry, AuLock_IR); -+ -+body: -+ if (!inode) { -+ inode = d_inode(dentry); -+ if (unlikely(!inode)) -+ goto out; -+ } -+ bindex = au_ibtop(inode); -+ h_path->mnt = au_sbr_mnt(sb, bindex); -+ h_sb = h_path->mnt->mnt_sb; -+ if (!force -+ && !au_test_fs_bad_iattr(h_sb) -+ && udba_none) -+ goto out; /* success */ -+ -+ if (au_dbtop(dentry) == bindex) -+ h_path->dentry = au_h_dptr(dentry, bindex); -+ else if (au_opt_test(mnt_flags, PLINK) && au_plink_test(inode)) { -+ h_path->dentry = au_plink_lkup(inode, bindex); -+ if (IS_ERR(h_path->dentry)) -+ /* pretending success */ -+ h_path->dentry = NULL; -+ else -+ dput(h_path->dentry); -+ } -+ -+out: -+ return err; -+} -+ -+static int aufs_getattr(const struct path *path, struct kstat *st, -+ u32 request, unsigned int query) -+{ -+ int err; -+ unsigned char positive; -+ struct path h_path; -+ struct dentry *dentry; -+ struct inode *inode; -+ struct super_block *sb; -+ -+ dentry = path->dentry; -+ inode = d_inode(dentry); -+ sb = dentry->d_sb; -+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM); -+ if (unlikely(err)) -+ goto out; -+ err = au_h_path_getattr(dentry, /*inode*/NULL, /*force*/0, &h_path, -+ /*locked*/0); -+ if (unlikely(err)) -+ goto out_si; -+ if (unlikely(!h_path.dentry)) -+ /* illegally overlapped or something */ -+ goto out_fill; /* pretending success */ -+ -+ positive = d_is_positive(h_path.dentry); -+ if (positive) -+ /* no vfsub version */ -+ err = vfs_getattr(&h_path, st, request, query); -+ if (!err) { -+ if (positive) -+ au_refresh_iattr(inode, st, -+ d_inode(h_path.dentry)->i_nlink); -+ goto out_fill; /* success */ -+ } -+ AuTraceErr(err); -+ goto out_di; -+ -+out_fill: -+ generic_fillattr(inode, st); -+out_di: -+ di_read_unlock(dentry, AuLock_IR); -+out_si: -+ si_read_unlock(sb); -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static const char *aufs_get_link(struct dentry *dentry, struct inode *inode, -+ struct delayed_call *done) -+{ -+ const char *ret; -+ struct dentry *h_dentry; -+ struct inode *h_inode; -+ int err; -+ aufs_bindex_t bindex; -+ -+ ret = NULL; /* suppress a warning */ -+ err = -ECHILD; -+ if (!dentry) -+ goto out; -+ -+ err = aufs_read_lock(dentry, AuLock_IR | AuLock_GEN); -+ if (unlikely(err)) -+ goto out; -+ -+ err = au_d_hashed_positive(dentry); -+ if (unlikely(err)) -+ goto out_unlock; -+ -+ err = -EINVAL; -+ inode = d_inode(dentry); -+ bindex = au_ibtop(inode); -+ h_inode = au_h_iptr(inode, bindex); -+ if (unlikely(!h_inode->i_op->get_link)) -+ goto out_unlock; -+ -+ err = -EBUSY; -+ h_dentry = NULL; -+ if (au_dbtop(dentry) <= bindex) { -+ h_dentry = au_h_dptr(dentry, bindex); -+ if (h_dentry) -+ dget(h_dentry); -+ } -+ if (!h_dentry) { -+ h_dentry = d_find_any_alias(h_inode); -+ if (IS_ERR(h_dentry)) { -+ err = PTR_ERR(h_dentry); -+ goto out_unlock; -+ } -+ } -+ if (unlikely(!h_dentry)) -+ goto out_unlock; -+ -+ err = 0; -+ AuDbg("%ps\n", h_inode->i_op->get_link); -+ AuDbgDentry(h_dentry); -+ ret = vfs_get_link(h_dentry, done); -+ dput(h_dentry); -+ if (IS_ERR(ret)) -+ err = PTR_ERR(ret); -+ -+out_unlock: -+ aufs_read_unlock(dentry, AuLock_IR); -+out: -+ if (unlikely(err)) -+ ret = ERR_PTR(err); -+ AuTraceErrPtr(ret); -+ return ret; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int au_is_special(struct inode *inode) -+{ -+ return (inode->i_mode & (S_IFBLK | S_IFCHR | S_IFIFO | S_IFSOCK)); -+} -+ -+static int aufs_update_time(struct inode *inode, struct timespec64 *ts, -+ int flags) -+{ -+ int err; -+ aufs_bindex_t bindex; -+ struct super_block *sb; -+ struct inode *h_inode; -+ struct vfsmount *h_mnt; -+ -+ sb = inode->i_sb; -+ WARN_ONCE((flags & S_ATIME) && !IS_NOATIME(inode), -+ "unexpected s_flags 0x%lx", sb->s_flags); -+ -+ /* mmap_sem might be acquired already, cf. aufs_mmap() */ -+ lockdep_off(); -+ si_read_lock(sb, AuLock_FLUSH); -+ ii_write_lock_child(inode); -+ -+ err = 0; -+ bindex = au_ibtop(inode); -+ h_inode = au_h_iptr(inode, bindex); -+ if (!au_test_ro(sb, bindex, inode)) { -+ h_mnt = au_sbr_mnt(sb, bindex); -+ err = vfsub_mnt_want_write(h_mnt); -+ if (!err) { -+ err = vfsub_update_time(h_inode, ts, flags); -+ vfsub_mnt_drop_write(h_mnt); -+ } -+ } else if (au_is_special(h_inode)) { -+ /* -+ * Never copy-up here. -+ * These special files may already be opened and used for -+ * communicating. If we copied it up, then the communication -+ * would be corrupted. -+ */ -+ AuWarn1("timestamps for i%lu are ignored " -+ "since it is on readonly branch (hi%lu).\n", -+ inode->i_ino, h_inode->i_ino); -+ } else if (flags & ~S_ATIME) { -+ err = -EIO; -+ AuIOErr1("unexpected flags 0x%x\n", flags); -+ AuDebugOn(1); -+ } -+ -+ if (!err) -+ au_cpup_attr_timesizes(inode); -+ ii_write_unlock(inode); -+ si_read_unlock(sb); -+ lockdep_on(); -+ -+ if (!err && (flags & S_VERSION)) -+ inode_inc_iversion(inode); -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* no getattr version will be set by module.c:aufs_init() */ -+struct inode_operations aufs_iop_nogetattr[AuIop_Last], -+ aufs_iop[] = { -+ [AuIop_SYMLINK] = { -+ .permission = aufs_permission, -+#ifdef CONFIG_FS_POSIX_ACL -+ .get_acl = aufs_get_acl, -+ .set_acl = aufs_set_acl, /* unsupport for symlink? */ -+#endif -+ -+ .setattr = aufs_setattr, -+ .getattr = aufs_getattr, -+ -+#ifdef CONFIG_AUFS_XATTR -+ .listxattr = aufs_listxattr, -+#endif -+ -+ .get_link = aufs_get_link, -+ -+ /* .update_time = aufs_update_time */ -+ }, -+ [AuIop_DIR] = { -+ .create = aufs_create, -+ .lookup = aufs_lookup, -+ .link = aufs_link, -+ .unlink = aufs_unlink, -+ .symlink = aufs_symlink, -+ .mkdir = aufs_mkdir, -+ .rmdir = aufs_rmdir, -+ .mknod = aufs_mknod, -+ .rename = aufs_rename, -+ -+ .permission = aufs_permission, -+#ifdef CONFIG_FS_POSIX_ACL -+ .get_acl = aufs_get_acl, -+ .set_acl = aufs_set_acl, -+#endif -+ -+ .setattr = aufs_setattr, -+ .getattr = aufs_getattr, -+ -+#ifdef CONFIG_AUFS_XATTR -+ .listxattr = aufs_listxattr, -+#endif -+ -+ .update_time = aufs_update_time, -+ .atomic_open = aufs_atomic_open, -+ .tmpfile = aufs_tmpfile -+ }, -+ [AuIop_OTHER] = { -+ .permission = aufs_permission, -+#ifdef CONFIG_FS_POSIX_ACL -+ .get_acl = aufs_get_acl, -+ .set_acl = aufs_set_acl, -+#endif -+ -+ .setattr = aufs_setattr, -+ .getattr = aufs_getattr, -+ -+#ifdef CONFIG_AUFS_XATTR -+ .listxattr = aufs_listxattr, -+#endif -+ -+ .update_time = aufs_update_time -+ } -+}; -diff -Nurp linux-5.10-rc6/fs/aufs/i_op_del.c linux-5.10-rc6.aufs/fs/aufs/i_op_del.c ---- linux-5.10-rc6/fs/aufs/i_op_del.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/i_op_del.c 2020-12-02 21:19:51.882036788 +0200 -@@ -0,0 +1,500 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * inode operations (del entry) -+ */ -+ -+#include -+#include "aufs.h" -+ -+/* -+ * decide if a new whiteout for @dentry is necessary or not. -+ * when it is necessary, prepare the parent dir for the upper branch whose -+ * branch index is @bcpup for creation. the actual creation of the whiteout will -+ * be done by caller. -+ * return value: -+ * 0: wh is unnecessary -+ * plus: wh is necessary -+ * minus: error -+ */ -+int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup) -+{ -+ int need_wh, err; -+ aufs_bindex_t btop; -+ struct super_block *sb; -+ -+ sb = dentry->d_sb; -+ btop = au_dbtop(dentry); -+ if (*bcpup < 0) { -+ *bcpup = btop; -+ if (au_test_ro(sb, btop, d_inode(dentry))) { -+ err = AuWbrCopyup(au_sbi(sb), dentry); -+ *bcpup = err; -+ if (unlikely(err < 0)) -+ goto out; -+ } -+ } else -+ AuDebugOn(btop < *bcpup -+ || au_test_ro(sb, *bcpup, d_inode(dentry))); -+ AuDbg("bcpup %d, btop %d\n", *bcpup, btop); -+ -+ if (*bcpup != btop) { -+ err = au_cpup_dirs(dentry, *bcpup); -+ if (unlikely(err)) -+ goto out; -+ need_wh = 1; -+ } else { -+ struct au_dinfo *dinfo, *tmp; -+ -+ need_wh = -ENOMEM; -+ dinfo = au_di(dentry); -+ tmp = au_di_alloc(sb, AuLsc_DI_TMP); -+ if (tmp) { -+ au_di_cp(tmp, dinfo); -+ au_di_swap(tmp, dinfo); -+ /* returns the number of positive dentries */ -+ need_wh = au_lkup_dentry(dentry, btop + 1, -+ /* AuLkup_IGNORE_PERM */ 0); -+ au_di_swap(tmp, dinfo); -+ au_rw_write_unlock(&tmp->di_rwsem); -+ au_di_free(tmp); -+ } -+ } -+ AuDbg("need_wh %d\n", need_wh); -+ err = need_wh; -+ -+out: -+ return err; -+} -+ -+/* -+ * simple tests for the del-entry operations. -+ * following the checks in vfs, plus the parent-child relationship. -+ */ -+int au_may_del(struct dentry *dentry, aufs_bindex_t bindex, -+ struct dentry *h_parent, int isdir) -+{ -+ int err; -+ umode_t h_mode; -+ struct dentry *h_dentry, *h_latest; -+ struct inode *h_inode; -+ -+ h_dentry = au_h_dptr(dentry, bindex); -+ if (d_really_is_positive(dentry)) { -+ err = -ENOENT; -+ if (unlikely(d_is_negative(h_dentry))) -+ goto out; -+ h_inode = d_inode(h_dentry); -+ if (unlikely(!h_inode->i_nlink)) -+ goto out; -+ -+ h_mode = h_inode->i_mode; -+ if (!isdir) { -+ err = -EISDIR; -+ if (unlikely(S_ISDIR(h_mode))) -+ goto out; -+ } else if (unlikely(!S_ISDIR(h_mode))) { -+ err = -ENOTDIR; -+ goto out; -+ } -+ } else { -+ /* rename(2) case */ -+ err = -EIO; -+ if (unlikely(d_is_positive(h_dentry))) -+ goto out; -+ } -+ -+ err = -ENOENT; -+ /* expected parent dir is locked */ -+ if (unlikely(h_parent != h_dentry->d_parent)) -+ goto out; -+ err = 0; -+ -+ /* -+ * rmdir a dir may break the consistency on some filesystem. -+ * let's try heavy test. -+ */ -+ err = -EACCES; -+ if (unlikely(!au_opt_test(au_mntflags(dentry->d_sb), DIRPERM1) -+ && au_test_h_perm(d_inode(h_parent), -+ MAY_EXEC | MAY_WRITE))) -+ goto out; -+ -+ h_latest = au_sio_lkup_one(&dentry->d_name, h_parent); -+ err = -EIO; -+ if (IS_ERR(h_latest)) -+ goto out; -+ if (h_latest == h_dentry) -+ err = 0; -+ dput(h_latest); -+ -+out: -+ return err; -+} -+ -+/* -+ * decide the branch where we operate for @dentry. the branch index will be set -+ * @rbcpup. after deciding it, 'pin' it and store the timestamps of the parent -+ * dir for reverting. -+ * when a new whiteout is necessary, create it. -+ */ -+static struct dentry* -+lock_hdir_create_wh(struct dentry *dentry, int isdir, aufs_bindex_t *rbcpup, -+ struct au_dtime *dt, struct au_pin *pin) -+{ -+ struct dentry *wh_dentry; -+ struct super_block *sb; -+ struct path h_path; -+ int err, need_wh; -+ unsigned int udba; -+ aufs_bindex_t bcpup; -+ -+ need_wh = au_wr_dir_need_wh(dentry, isdir, rbcpup); -+ wh_dentry = ERR_PTR(need_wh); -+ if (unlikely(need_wh < 0)) -+ goto out; -+ -+ sb = dentry->d_sb; -+ udba = au_opt_udba(sb); -+ bcpup = *rbcpup; -+ err = au_pin(pin, dentry, bcpup, udba, -+ AuPin_DI_LOCKED | AuPin_MNT_WRITE); -+ wh_dentry = ERR_PTR(err); -+ if (unlikely(err)) -+ goto out; -+ -+ h_path.dentry = au_pinned_h_parent(pin); -+ if (udba != AuOpt_UDBA_NONE -+ && au_dbtop(dentry) == bcpup) { -+ err = au_may_del(dentry, bcpup, h_path.dentry, isdir); -+ wh_dentry = ERR_PTR(err); -+ if (unlikely(err)) -+ goto out_unpin; -+ } -+ -+ h_path.mnt = au_sbr_mnt(sb, bcpup); -+ au_dtime_store(dt, au_pinned_parent(pin), &h_path); -+ wh_dentry = NULL; -+ if (!need_wh) -+ goto out; /* success, no need to create whiteout */ -+ -+ wh_dentry = au_wh_create(dentry, bcpup, h_path.dentry); -+ if (IS_ERR(wh_dentry)) -+ goto out_unpin; -+ -+ /* returns with the parent is locked and wh_dentry is dget-ed */ -+ goto out; /* success */ -+ -+out_unpin: -+ au_unpin(pin); -+out: -+ return wh_dentry; -+} -+ -+/* -+ * when removing a dir, rename it to a unique temporary whiteout-ed name first -+ * in order to be revertible and save time for removing many child whiteouts -+ * under the dir. -+ * returns 1 when there are too many child whiteout and caller should remove -+ * them asynchronously. returns 0 when the number of children is enough small to -+ * remove now or the branch fs is a remote fs. -+ * otherwise return an error. -+ */ -+static int renwh_and_rmdir(struct dentry *dentry, aufs_bindex_t bindex, -+ struct au_nhash *whlist, struct inode *dir) -+{ -+ int rmdir_later, err, dirwh; -+ struct dentry *h_dentry; -+ struct super_block *sb; -+ struct inode *inode; -+ -+ sb = dentry->d_sb; -+ SiMustAnyLock(sb); -+ h_dentry = au_h_dptr(dentry, bindex); -+ err = au_whtmp_ren(h_dentry, au_sbr(sb, bindex)); -+ if (unlikely(err)) -+ goto out; -+ -+ /* stop monitoring */ -+ inode = d_inode(dentry); -+ au_hn_free(au_hi(inode, bindex)); -+ -+ if (!au_test_fs_remote(h_dentry->d_sb)) { -+ dirwh = au_sbi(sb)->si_dirwh; -+ rmdir_later = (dirwh <= 1); -+ if (!rmdir_later) -+ rmdir_later = au_nhash_test_longer_wh(whlist, bindex, -+ dirwh); -+ if (rmdir_later) -+ return rmdir_later; -+ } -+ -+ err = au_whtmp_rmdir(dir, bindex, h_dentry, whlist); -+ if (unlikely(err)) { -+ AuIOErr("rmdir %pd, b%d failed, %d. ignored\n", -+ h_dentry, bindex, err); -+ err = 0; -+ } -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+/* -+ * final procedure for deleting a entry. -+ * maintain dentry and iattr. -+ */ -+static void epilog(struct inode *dir, struct dentry *dentry, -+ aufs_bindex_t bindex) -+{ -+ struct inode *inode; -+ -+ inode = d_inode(dentry); -+ d_drop(dentry); -+ inode->i_ctime = dir->i_ctime; -+ -+ au_dir_ts(dir, bindex); -+ inode_inc_iversion(dir); -+} -+ -+/* -+ * when an error happened, remove the created whiteout and revert everything. -+ */ -+static int do_revert(int err, struct inode *dir, aufs_bindex_t bindex, -+ aufs_bindex_t bwh, struct dentry *wh_dentry, -+ struct dentry *dentry, struct au_dtime *dt) -+{ -+ int rerr; -+ struct path h_path = { -+ .dentry = wh_dentry, -+ .mnt = au_sbr_mnt(dir->i_sb, bindex) -+ }; -+ -+ rerr = au_wh_unlink_dentry(au_h_iptr(dir, bindex), &h_path, dentry); -+ if (!rerr) { -+ au_set_dbwh(dentry, bwh); -+ au_dtime_revert(dt); -+ return 0; -+ } -+ -+ AuIOErr("%pd reverting whiteout failed(%d, %d)\n", dentry, err, rerr); -+ return -EIO; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+int aufs_unlink(struct inode *dir, struct dentry *dentry) -+{ -+ int err; -+ aufs_bindex_t bwh, bindex, btop; -+ struct inode *inode, *h_dir, *delegated; -+ struct dentry *parent, *wh_dentry; -+ /* to reduce stack size */ -+ struct { -+ struct au_dtime dt; -+ struct au_pin pin; -+ struct path h_path; -+ } *a; -+ -+ IMustLock(dir); -+ -+ err = -ENOMEM; -+ a = kmalloc(sizeof(*a), GFP_NOFS); -+ if (unlikely(!a)) -+ goto out; -+ -+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN); -+ if (unlikely(err)) -+ goto out_free; -+ err = au_d_hashed_positive(dentry); -+ if (unlikely(err)) -+ goto out_unlock; -+ inode = d_inode(dentry); -+ IMustLock(inode); -+ err = -EISDIR; -+ if (unlikely(d_is_dir(dentry))) -+ goto out_unlock; /* possible? */ -+ -+ btop = au_dbtop(dentry); -+ bwh = au_dbwh(dentry); -+ bindex = -1; -+ parent = dentry->d_parent; /* dir inode is locked */ -+ di_write_lock_parent(parent); -+ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/0, &bindex, &a->dt, -+ &a->pin); -+ err = PTR_ERR(wh_dentry); -+ if (IS_ERR(wh_dentry)) -+ goto out_parent; -+ -+ a->h_path.mnt = au_sbr_mnt(dentry->d_sb, btop); -+ a->h_path.dentry = au_h_dptr(dentry, btop); -+ dget(a->h_path.dentry); -+ if (bindex == btop) { -+ h_dir = au_pinned_h_dir(&a->pin); -+ delegated = NULL; -+ err = vfsub_unlink(h_dir, &a->h_path, &delegated, /*force*/0); -+ if (unlikely(err == -EWOULDBLOCK)) { -+ pr_warn("cannot retry for NFSv4 delegation" -+ " for an internal unlink\n"); -+ iput(delegated); -+ } -+ } else { -+ /* dir inode is locked */ -+ h_dir = d_inode(wh_dentry->d_parent); -+ IMustLock(h_dir); -+ err = 0; -+ } -+ -+ if (!err) { -+ vfsub_drop_nlink(inode); -+ epilog(dir, dentry, bindex); -+ -+ /* update target timestamps */ -+ if (bindex == btop) { -+ vfsub_update_h_iattr(&a->h_path, /*did*/NULL); -+ /*ignore*/ -+ inode->i_ctime = d_inode(a->h_path.dentry)->i_ctime; -+ } else -+ /* todo: this timestamp may be reverted later */ -+ inode->i_ctime = h_dir->i_ctime; -+ goto out_unpin; /* success */ -+ } -+ -+ /* revert */ -+ if (wh_dentry) { -+ int rerr; -+ -+ rerr = do_revert(err, dir, bindex, bwh, wh_dentry, dentry, -+ &a->dt); -+ if (rerr) -+ err = rerr; -+ } -+ -+out_unpin: -+ au_unpin(&a->pin); -+ dput(wh_dentry); -+ dput(a->h_path.dentry); -+out_parent: -+ di_write_unlock(parent); -+out_unlock: -+ aufs_read_unlock(dentry, AuLock_DW); -+out_free: -+ au_kfree_rcu(a); -+out: -+ return err; -+} -+ -+int aufs_rmdir(struct inode *dir, struct dentry *dentry) -+{ -+ int err, rmdir_later; -+ aufs_bindex_t bwh, bindex, btop; -+ struct inode *inode; -+ struct dentry *parent, *wh_dentry, *h_dentry; -+ struct au_whtmp_rmdir *args; -+ /* to reduce stack size */ -+ struct { -+ struct au_dtime dt; -+ struct au_pin pin; -+ } *a; -+ -+ IMustLock(dir); -+ -+ err = -ENOMEM; -+ a = kmalloc(sizeof(*a), GFP_NOFS); -+ if (unlikely(!a)) -+ goto out; -+ -+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH | AuLock_GEN); -+ if (unlikely(err)) -+ goto out_free; -+ err = au_alive_dir(dentry); -+ if (unlikely(err)) -+ goto out_unlock; -+ inode = d_inode(dentry); -+ IMustLock(inode); -+ err = -ENOTDIR; -+ if (unlikely(!d_is_dir(dentry))) -+ goto out_unlock; /* possible? */ -+ -+ err = -ENOMEM; -+ args = au_whtmp_rmdir_alloc(dir->i_sb, GFP_NOFS); -+ if (unlikely(!args)) -+ goto out_unlock; -+ -+ parent = dentry->d_parent; /* dir inode is locked */ -+ di_write_lock_parent(parent); -+ err = au_test_empty(dentry, &args->whlist); -+ if (unlikely(err)) -+ goto out_parent; -+ -+ btop = au_dbtop(dentry); -+ bwh = au_dbwh(dentry); -+ bindex = -1; -+ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/1, &bindex, &a->dt, -+ &a->pin); -+ err = PTR_ERR(wh_dentry); -+ if (IS_ERR(wh_dentry)) -+ goto out_parent; -+ -+ h_dentry = au_h_dptr(dentry, btop); -+ dget(h_dentry); -+ rmdir_later = 0; -+ if (bindex == btop) { -+ err = renwh_and_rmdir(dentry, btop, &args->whlist, dir); -+ if (err > 0) { -+ rmdir_later = err; -+ err = 0; -+ } -+ } else { -+ /* stop monitoring */ -+ au_hn_free(au_hi(inode, btop)); -+ -+ /* dir inode is locked */ -+ IMustLock(d_inode(wh_dentry->d_parent)); -+ err = 0; -+ } -+ -+ if (!err) { -+ vfsub_dead_dir(inode); -+ au_set_dbdiropq(dentry, -1); -+ epilog(dir, dentry, bindex); -+ -+ if (rmdir_later) { -+ au_whtmp_kick_rmdir(dir, btop, h_dentry, args); -+ args = NULL; -+ } -+ -+ goto out_unpin; /* success */ -+ } -+ -+ /* revert */ -+ AuLabel(revert); -+ if (wh_dentry) { -+ int rerr; -+ -+ rerr = do_revert(err, dir, bindex, bwh, wh_dentry, dentry, -+ &a->dt); -+ if (rerr) -+ err = rerr; -+ } -+ -+out_unpin: -+ au_unpin(&a->pin); -+ dput(wh_dentry); -+ dput(h_dentry); -+out_parent: -+ di_write_unlock(parent); -+ if (args) -+ au_whtmp_rmdir_free(args); -+out_unlock: -+ aufs_read_unlock(dentry, AuLock_DW); -+out_free: -+ au_kfree_rcu(a); -+out: -+ AuTraceErr(err); -+ return err; -+} -diff -Nurp linux-5.10-rc6/fs/aufs/i_op_ren.c linux-5.10-rc6.aufs/fs/aufs/i_op_ren.c ---- linux-5.10-rc6/fs/aufs/i_op_ren.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/i_op_ren.c 2020-12-02 21:19:51.882036788 +0200 -@@ -0,0 +1,1237 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * inode operation (rename entry) -+ * todo: this is crazy monster -+ */ -+ -+#include -+#include "aufs.h" -+ -+enum { AuSRC, AuDST, AuSrcDst }; -+enum { AuPARENT, AuCHILD, AuParentChild }; -+ -+#define AuRen_ISDIR_SRC 1 -+#define AuRen_ISDIR_DST (1 << 1) -+#define AuRen_ISSAMEDIR (1 << 2) -+#define AuRen_WHSRC (1 << 3) -+#define AuRen_WHDST (1 << 4) -+#define AuRen_MNT_WRITE (1 << 5) -+#define AuRen_DT_DSTDIR (1 << 6) -+#define AuRen_DIROPQ_SRC (1 << 7) -+#define AuRen_DIROPQ_DST (1 << 8) -+#define AuRen_DIRREN (1 << 9) -+#define AuRen_DROPPED_SRC (1 << 10) -+#define AuRen_DROPPED_DST (1 << 11) -+#define au_ftest_ren(flags, name) ((flags) & AuRen_##name) -+#define au_fset_ren(flags, name) \ -+ do { (flags) |= AuRen_##name; } while (0) -+#define au_fclr_ren(flags, name) \ -+ do { (flags) &= ~AuRen_##name; } while (0) -+ -+#ifndef CONFIG_AUFS_DIRREN -+#undef AuRen_DIRREN -+#define AuRen_DIRREN 0 -+#endif -+ -+struct au_ren_args { -+ struct { -+ struct dentry *dentry, *h_dentry, *parent, *h_parent, -+ *wh_dentry; -+ struct inode *dir, *inode; -+ struct au_hinode *hdir, *hinode; -+ struct au_dtime dt[AuParentChild]; -+ aufs_bindex_t btop, bdiropq; -+ } sd[AuSrcDst]; -+ -+#define src_dentry sd[AuSRC].dentry -+#define src_dir sd[AuSRC].dir -+#define src_inode sd[AuSRC].inode -+#define src_h_dentry sd[AuSRC].h_dentry -+#define src_parent sd[AuSRC].parent -+#define src_h_parent sd[AuSRC].h_parent -+#define src_wh_dentry sd[AuSRC].wh_dentry -+#define src_hdir sd[AuSRC].hdir -+#define src_hinode sd[AuSRC].hinode -+#define src_h_dir sd[AuSRC].hdir->hi_inode -+#define src_dt sd[AuSRC].dt -+#define src_btop sd[AuSRC].btop -+#define src_bdiropq sd[AuSRC].bdiropq -+ -+#define dst_dentry sd[AuDST].dentry -+#define dst_dir sd[AuDST].dir -+#define dst_inode sd[AuDST].inode -+#define dst_h_dentry sd[AuDST].h_dentry -+#define dst_parent sd[AuDST].parent -+#define dst_h_parent sd[AuDST].h_parent -+#define dst_wh_dentry sd[AuDST].wh_dentry -+#define dst_hdir sd[AuDST].hdir -+#define dst_hinode sd[AuDST].hinode -+#define dst_h_dir sd[AuDST].hdir->hi_inode -+#define dst_dt sd[AuDST].dt -+#define dst_btop sd[AuDST].btop -+#define dst_bdiropq sd[AuDST].bdiropq -+ -+ struct dentry *h_trap; -+ struct au_branch *br; -+ struct path h_path; -+ struct au_nhash whlist; -+ aufs_bindex_t btgt, src_bwh; -+ -+ struct { -+ unsigned short auren_flags; -+ unsigned char flags; /* syscall parameter */ -+ unsigned char exchange; -+ } __packed; -+ -+ struct au_whtmp_rmdir *thargs; -+ struct dentry *h_dst; -+ struct au_hinode *h_root; -+}; -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * functions for reverting. -+ * when an error happened in a single rename systemcall, we should revert -+ * everything as if nothing happened. -+ * we don't need to revert the copied-up/down the parent dir since they are -+ * harmless. -+ */ -+ -+#define RevertFailure(fmt, ...) do { \ -+ AuIOErr("revert failure: " fmt " (%d, %d)\n", \ -+ ##__VA_ARGS__, err, rerr); \ -+ err = -EIO; \ -+} while (0) -+ -+static void au_ren_do_rev_diropq(int err, struct au_ren_args *a, int idx) -+{ -+ int rerr; -+ struct dentry *d; -+#define src_or_dst(member) a->sd[idx].member -+ -+ d = src_or_dst(dentry); /* {src,dst}_dentry */ -+ au_hn_inode_lock_nested(src_or_dst(hinode), AuLsc_I_CHILD); -+ rerr = au_diropq_remove(d, a->btgt); -+ au_hn_inode_unlock(src_or_dst(hinode)); -+ au_set_dbdiropq(d, src_or_dst(bdiropq)); -+ if (rerr) -+ RevertFailure("remove diropq %pd", d); -+ -+#undef src_or_dst_ -+} -+ -+static void au_ren_rev_diropq(int err, struct au_ren_args *a) -+{ -+ if (au_ftest_ren(a->auren_flags, DIROPQ_SRC)) -+ au_ren_do_rev_diropq(err, a, AuSRC); -+ if (au_ftest_ren(a->auren_flags, DIROPQ_DST)) -+ au_ren_do_rev_diropq(err, a, AuDST); -+} -+ -+static void au_ren_rev_rename(int err, struct au_ren_args *a) -+{ -+ int rerr; -+ struct inode *delegated; -+ -+ a->h_path.dentry = vfsub_lkup_one(&a->src_dentry->d_name, -+ a->src_h_parent); -+ rerr = PTR_ERR(a->h_path.dentry); -+ if (IS_ERR(a->h_path.dentry)) { -+ RevertFailure("lkup one %pd", a->src_dentry); -+ return; -+ } -+ -+ delegated = NULL; -+ rerr = vfsub_rename(a->dst_h_dir, -+ au_h_dptr(a->src_dentry, a->btgt), -+ a->src_h_dir, &a->h_path, &delegated, a->flags); -+ if (unlikely(rerr == -EWOULDBLOCK)) { -+ pr_warn("cannot retry for NFSv4 delegation" -+ " for an internal rename\n"); -+ iput(delegated); -+ } -+ d_drop(a->h_path.dentry); -+ dput(a->h_path.dentry); -+ /* au_set_h_dptr(a->src_dentry, a->btgt, NULL); */ -+ if (rerr) -+ RevertFailure("rename %pd", a->src_dentry); -+} -+ -+static void au_ren_rev_whtmp(int err, struct au_ren_args *a) -+{ -+ int rerr; -+ struct inode *delegated; -+ -+ a->h_path.dentry = vfsub_lkup_one(&a->dst_dentry->d_name, -+ a->dst_h_parent); -+ rerr = PTR_ERR(a->h_path.dentry); -+ if (IS_ERR(a->h_path.dentry)) { -+ RevertFailure("lkup one %pd", a->dst_dentry); -+ return; -+ } -+ if (d_is_positive(a->h_path.dentry)) { -+ d_drop(a->h_path.dentry); -+ dput(a->h_path.dentry); -+ return; -+ } -+ -+ delegated = NULL; -+ rerr = vfsub_rename(a->dst_h_dir, a->h_dst, a->dst_h_dir, &a->h_path, -+ &delegated, a->flags); -+ if (unlikely(rerr == -EWOULDBLOCK)) { -+ pr_warn("cannot retry for NFSv4 delegation" -+ " for an internal rename\n"); -+ iput(delegated); -+ } -+ d_drop(a->h_path.dentry); -+ dput(a->h_path.dentry); -+ if (!rerr) -+ au_set_h_dptr(a->dst_dentry, a->btgt, dget(a->h_dst)); -+ else -+ RevertFailure("rename %pd", a->h_dst); -+} -+ -+static void au_ren_rev_whsrc(int err, struct au_ren_args *a) -+{ -+ int rerr; -+ -+ a->h_path.dentry = a->src_wh_dentry; -+ rerr = au_wh_unlink_dentry(a->src_h_dir, &a->h_path, a->src_dentry); -+ au_set_dbwh(a->src_dentry, a->src_bwh); -+ if (rerr) -+ RevertFailure("unlink %pd", a->src_wh_dentry); -+} -+#undef RevertFailure -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * when we have to copyup the renaming entry, do it with the rename-target name -+ * in order to minimize the cost (the later actual rename is unnecessary). -+ * otherwise rename it on the target branch. -+ */ -+static int au_ren_or_cpup(struct au_ren_args *a) -+{ -+ int err; -+ struct dentry *d; -+ struct inode *delegated; -+ -+ d = a->src_dentry; -+ if (au_dbtop(d) == a->btgt) { -+ a->h_path.dentry = a->dst_h_dentry; -+ AuDebugOn(au_dbtop(d) != a->btgt); -+ delegated = NULL; -+ err = vfsub_rename(a->src_h_dir, au_h_dptr(d, a->btgt), -+ a->dst_h_dir, &a->h_path, &delegated, -+ a->flags); -+ if (unlikely(err == -EWOULDBLOCK)) { -+ pr_warn("cannot retry for NFSv4 delegation" -+ " for an internal rename\n"); -+ iput(delegated); -+ } -+ } else -+ BUG(); -+ -+ if (!err && a->h_dst) -+ /* it will be set to dinfo later */ -+ dget(a->h_dst); -+ -+ return err; -+} -+ -+/* cf. aufs_rmdir() */ -+static int au_ren_del_whtmp(struct au_ren_args *a) -+{ -+ int err; -+ struct inode *dir; -+ -+ dir = a->dst_dir; -+ SiMustAnyLock(dir->i_sb); -+ if (!au_nhash_test_longer_wh(&a->whlist, a->btgt, -+ au_sbi(dir->i_sb)->si_dirwh) -+ || au_test_fs_remote(a->h_dst->d_sb)) { -+ err = au_whtmp_rmdir(dir, a->btgt, a->h_dst, &a->whlist); -+ if (unlikely(err)) -+ pr_warn("failed removing whtmp dir %pd (%d), " -+ "ignored.\n", a->h_dst, err); -+ } else { -+ au_nhash_wh_free(&a->thargs->whlist); -+ a->thargs->whlist = a->whlist; -+ a->whlist.nh_num = 0; -+ au_whtmp_kick_rmdir(dir, a->btgt, a->h_dst, a->thargs); -+ dput(a->h_dst); -+ a->thargs = NULL; -+ } -+ -+ return 0; -+} -+ -+/* make it 'opaque' dir. */ -+static int au_ren_do_diropq(struct au_ren_args *a, int idx) -+{ -+ int err; -+ struct dentry *d, *diropq; -+#define src_or_dst(member) a->sd[idx].member -+ -+ err = 0; -+ d = src_or_dst(dentry); /* {src,dst}_dentry */ -+ src_or_dst(bdiropq) = au_dbdiropq(d); -+ src_or_dst(hinode) = au_hi(src_or_dst(inode), a->btgt); -+ au_hn_inode_lock_nested(src_or_dst(hinode), AuLsc_I_CHILD); -+ diropq = au_diropq_create(d, a->btgt); -+ au_hn_inode_unlock(src_or_dst(hinode)); -+ if (IS_ERR(diropq)) -+ err = PTR_ERR(diropq); -+ else -+ dput(diropq); -+ -+#undef src_or_dst_ -+ return err; -+} -+ -+static int au_ren_diropq(struct au_ren_args *a) -+{ -+ int err; -+ unsigned char always; -+ struct dentry *d; -+ -+ err = 0; -+ d = a->dst_dentry; /* already renamed on the branch */ -+ always = !!au_opt_test(au_mntflags(d->d_sb), ALWAYS_DIROPQ); -+ if (au_ftest_ren(a->auren_flags, ISDIR_SRC) -+ && !au_ftest_ren(a->auren_flags, DIRREN) -+ && a->btgt != au_dbdiropq(a->src_dentry) -+ && (a->dst_wh_dentry -+ || a->btgt <= au_dbdiropq(d) -+ /* hide the lower to keep xino */ -+ /* the lowers may not be a dir, but we hide them anyway */ -+ || a->btgt < au_dbbot(d) -+ || always)) { -+ AuDbg("here\n"); -+ err = au_ren_do_diropq(a, AuSRC); -+ if (unlikely(err)) -+ goto out; -+ au_fset_ren(a->auren_flags, DIROPQ_SRC); -+ } -+ if (!a->exchange) -+ goto out; /* success */ -+ -+ d = a->src_dentry; /* already renamed on the branch */ -+ if (au_ftest_ren(a->auren_flags, ISDIR_DST) -+ && a->btgt != au_dbdiropq(a->dst_dentry) -+ && (a->btgt < au_dbdiropq(d) -+ || a->btgt < au_dbbot(d) -+ || always)) { -+ AuDbgDentry(a->src_dentry); -+ AuDbgDentry(a->dst_dentry); -+ err = au_ren_do_diropq(a, AuDST); -+ if (unlikely(err)) -+ goto out_rev_src; -+ au_fset_ren(a->auren_flags, DIROPQ_DST); -+ } -+ goto out; /* success */ -+ -+out_rev_src: -+ AuDbg("err %d, reverting src\n", err); -+ au_ren_rev_diropq(err, a); -+out: -+ return err; -+} -+ -+static int do_rename(struct au_ren_args *a) -+{ -+ int err; -+ struct dentry *d, *h_d; -+ -+ if (!a->exchange) { -+ /* prepare workqueue args for asynchronous rmdir */ -+ h_d = a->dst_h_dentry; -+ if (au_ftest_ren(a->auren_flags, ISDIR_DST) -+ /* && !au_ftest_ren(a->auren_flags, DIRREN) */ -+ && d_is_positive(h_d)) { -+ err = -ENOMEM; -+ a->thargs = au_whtmp_rmdir_alloc(a->src_dentry->d_sb, -+ GFP_NOFS); -+ if (unlikely(!a->thargs)) -+ goto out; -+ a->h_dst = dget(h_d); -+ } -+ -+ /* create whiteout for src_dentry */ -+ if (au_ftest_ren(a->auren_flags, WHSRC)) { -+ a->src_bwh = au_dbwh(a->src_dentry); -+ AuDebugOn(a->src_bwh >= 0); -+ a->src_wh_dentry = au_wh_create(a->src_dentry, a->btgt, -+ a->src_h_parent); -+ err = PTR_ERR(a->src_wh_dentry); -+ if (IS_ERR(a->src_wh_dentry)) -+ goto out_thargs; -+ } -+ -+ /* lookup whiteout for dentry */ -+ if (au_ftest_ren(a->auren_flags, WHDST)) { -+ h_d = au_wh_lkup(a->dst_h_parent, -+ &a->dst_dentry->d_name, a->br); -+ err = PTR_ERR(h_d); -+ if (IS_ERR(h_d)) -+ goto out_whsrc; -+ if (d_is_negative(h_d)) -+ dput(h_d); -+ else -+ a->dst_wh_dentry = h_d; -+ } -+ -+ /* rename dentry to tmpwh */ -+ if (a->thargs) { -+ err = au_whtmp_ren(a->dst_h_dentry, a->br); -+ if (unlikely(err)) -+ goto out_whdst; -+ -+ d = a->dst_dentry; -+ au_set_h_dptr(d, a->btgt, NULL); -+ err = au_lkup_neg(d, a->btgt, /*wh*/0); -+ if (unlikely(err)) -+ goto out_whtmp; -+ a->dst_h_dentry = au_h_dptr(d, a->btgt); -+ } -+ } -+ -+ BUG_ON(d_is_positive(a->dst_h_dentry) && a->src_btop != a->btgt); -+#if 0 /* debugging */ -+ BUG_ON(!au_ftest_ren(a->auren_flags, DIRREN) -+ && d_is_positive(a->dst_h_dentry) -+ && a->src_btop != a->btgt); -+#endif -+ -+ /* rename by vfs_rename or cpup */ -+ err = au_ren_or_cpup(a); -+ if (unlikely(err)) -+ /* leave the copied-up one */ -+ goto out_whtmp; -+ -+ /* make dir opaque */ -+ err = au_ren_diropq(a); -+ if (unlikely(err)) -+ goto out_rename; -+ -+ /* update target timestamps */ -+ if (a->exchange) { -+ AuDebugOn(au_dbtop(a->dst_dentry) != a->btgt); -+ a->h_path.dentry = au_h_dptr(a->dst_dentry, a->btgt); -+ vfsub_update_h_iattr(&a->h_path, /*did*/NULL); /*ignore*/ -+ a->dst_inode->i_ctime = d_inode(a->h_path.dentry)->i_ctime; -+ } -+ AuDebugOn(au_dbtop(a->src_dentry) != a->btgt); -+ a->h_path.dentry = au_h_dptr(a->src_dentry, a->btgt); -+ vfsub_update_h_iattr(&a->h_path, /*did*/NULL); /*ignore*/ -+ a->src_inode->i_ctime = d_inode(a->h_path.dentry)->i_ctime; -+ -+ if (!a->exchange) { -+ /* remove whiteout for dentry */ -+ if (a->dst_wh_dentry) { -+ a->h_path.dentry = a->dst_wh_dentry; -+ err = au_wh_unlink_dentry(a->dst_h_dir, &a->h_path, -+ a->dst_dentry); -+ if (unlikely(err)) -+ goto out_diropq; -+ } -+ -+ /* remove whtmp */ -+ if (a->thargs) -+ au_ren_del_whtmp(a); /* ignore this error */ -+ -+ au_fhsm_wrote(a->src_dentry->d_sb, a->btgt, /*force*/0); -+ } -+ err = 0; -+ goto out_success; -+ -+out_diropq: -+ au_ren_rev_diropq(err, a); -+out_rename: -+ au_ren_rev_rename(err, a); -+ dput(a->h_dst); -+out_whtmp: -+ if (a->thargs) -+ au_ren_rev_whtmp(err, a); -+out_whdst: -+ dput(a->dst_wh_dentry); -+ a->dst_wh_dentry = NULL; -+out_whsrc: -+ if (a->src_wh_dentry) -+ au_ren_rev_whsrc(err, a); -+out_success: -+ dput(a->src_wh_dentry); -+ dput(a->dst_wh_dentry); -+out_thargs: -+ if (a->thargs) { -+ dput(a->h_dst); -+ au_whtmp_rmdir_free(a->thargs); -+ a->thargs = NULL; -+ } -+out: -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * test if @dentry dir can be rename destination or not. -+ * success means, it is a logically empty dir. -+ */ -+static int may_rename_dstdir(struct dentry *dentry, struct au_nhash *whlist) -+{ -+ return au_test_empty(dentry, whlist); -+} -+ -+/* -+ * test if @a->src_dentry dir can be rename source or not. -+ * if it can, return 0. -+ * success means, -+ * - it is a logically empty dir. -+ * - or, it exists on writable branch and has no children including whiteouts -+ * on the lower branch unless DIRREN is on. -+ */ -+static int may_rename_srcdir(struct au_ren_args *a) -+{ -+ int err; -+ unsigned int rdhash; -+ aufs_bindex_t btop, btgt; -+ struct dentry *dentry; -+ struct super_block *sb; -+ struct au_sbinfo *sbinfo; -+ -+ dentry = a->src_dentry; -+ sb = dentry->d_sb; -+ sbinfo = au_sbi(sb); -+ if (au_opt_test(sbinfo->si_mntflags, DIRREN)) -+ au_fset_ren(a->auren_flags, DIRREN); -+ -+ btgt = a->btgt; -+ btop = au_dbtop(dentry); -+ if (btop != btgt) { -+ struct au_nhash whlist; -+ -+ SiMustAnyLock(sb); -+ rdhash = sbinfo->si_rdhash; -+ if (!rdhash) -+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, -+ dentry)); -+ err = au_nhash_alloc(&whlist, rdhash, GFP_NOFS); -+ if (unlikely(err)) -+ goto out; -+ err = au_test_empty(dentry, &whlist); -+ au_nhash_wh_free(&whlist); -+ goto out; -+ } -+ -+ if (btop == au_dbtaildir(dentry)) -+ return 0; /* success */ -+ -+ err = au_test_empty_lower(dentry); -+ -+out: -+ if (err == -ENOTEMPTY) { -+ if (au_ftest_ren(a->auren_flags, DIRREN)) { -+ err = 0; -+ } else { -+ AuWarn1("renaming dir who has child(ren) on multiple " -+ "branches, is not supported\n"); -+ err = -EXDEV; -+ } -+ } -+ return err; -+} -+ -+/* side effect: sets whlist and h_dentry */ -+static int au_ren_may_dir(struct au_ren_args *a) -+{ -+ int err; -+ unsigned int rdhash; -+ struct dentry *d; -+ -+ d = a->dst_dentry; -+ SiMustAnyLock(d->d_sb); -+ -+ err = 0; -+ if (au_ftest_ren(a->auren_flags, ISDIR_DST) && a->dst_inode) { -+ rdhash = au_sbi(d->d_sb)->si_rdhash; -+ if (!rdhash) -+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, d)); -+ err = au_nhash_alloc(&a->whlist, rdhash, GFP_NOFS); -+ if (unlikely(err)) -+ goto out; -+ -+ if (!a->exchange) { -+ au_set_dbtop(d, a->dst_btop); -+ err = may_rename_dstdir(d, &a->whlist); -+ au_set_dbtop(d, a->btgt); -+ } else -+ err = may_rename_srcdir(a); -+ } -+ a->dst_h_dentry = au_h_dptr(d, au_dbtop(d)); -+ if (unlikely(err)) -+ goto out; -+ -+ d = a->src_dentry; -+ a->src_h_dentry = au_h_dptr(d, au_dbtop(d)); -+ if (au_ftest_ren(a->auren_flags, ISDIR_SRC)) { -+ err = may_rename_srcdir(a); -+ if (unlikely(err)) { -+ au_nhash_wh_free(&a->whlist); -+ a->whlist.nh_num = 0; -+ } -+ } -+out: -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * simple tests for rename. -+ * following the checks in vfs, plus the parent-child relationship. -+ */ -+static int au_may_ren(struct au_ren_args *a) -+{ -+ int err, isdir; -+ struct inode *h_inode; -+ -+ if (a->src_btop == a->btgt) { -+ err = au_may_del(a->src_dentry, a->btgt, a->src_h_parent, -+ au_ftest_ren(a->auren_flags, ISDIR_SRC)); -+ if (unlikely(err)) -+ goto out; -+ err = -EINVAL; -+ if (unlikely(a->src_h_dentry == a->h_trap)) -+ goto out; -+ } -+ -+ err = 0; -+ if (a->dst_btop != a->btgt) -+ goto out; -+ -+ err = -ENOTEMPTY; -+ if (unlikely(a->dst_h_dentry == a->h_trap)) -+ goto out; -+ -+ err = -EIO; -+ isdir = !!au_ftest_ren(a->auren_flags, ISDIR_DST); -+ if (d_really_is_negative(a->dst_dentry)) { -+ if (d_is_negative(a->dst_h_dentry)) -+ err = au_may_add(a->dst_dentry, a->btgt, -+ a->dst_h_parent, isdir); -+ } else { -+ if (unlikely(d_is_negative(a->dst_h_dentry))) -+ goto out; -+ h_inode = d_inode(a->dst_h_dentry); -+ if (h_inode->i_nlink) -+ err = au_may_del(a->dst_dentry, a->btgt, -+ a->dst_h_parent, isdir); -+ } -+ -+out: -+ if (unlikely(err == -ENOENT || err == -EEXIST)) -+ err = -EIO; -+ AuTraceErr(err); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * locking order -+ * (VFS) -+ * - src_dir and dir by lock_rename() -+ * - inode if exists -+ * (aufs) -+ * - lock all -+ * + src_dentry and dentry by aufs_read_and_write_lock2() which calls, -+ * + si_read_lock -+ * + di_write_lock2_child() -+ * + di_write_lock_child() -+ * + ii_write_lock_child() -+ * + di_write_lock_child2() -+ * + ii_write_lock_child2() -+ * + src_parent and parent -+ * + di_write_lock_parent() -+ * + ii_write_lock_parent() -+ * + di_write_lock_parent2() -+ * + ii_write_lock_parent2() -+ * + lower src_dir and dir by vfsub_lock_rename() -+ * + verify the every relationships between child and parent. if any -+ * of them failed, unlock all and return -EBUSY. -+ */ -+static void au_ren_unlock(struct au_ren_args *a) -+{ -+ vfsub_unlock_rename(a->src_h_parent, a->src_hdir, -+ a->dst_h_parent, a->dst_hdir); -+ if (au_ftest_ren(a->auren_flags, DIRREN) -+ && a->h_root) -+ au_hn_inode_unlock(a->h_root); -+ if (au_ftest_ren(a->auren_flags, MNT_WRITE)) -+ vfsub_mnt_drop_write(au_br_mnt(a->br)); -+} -+ -+static int au_ren_lock(struct au_ren_args *a) -+{ -+ int err; -+ unsigned int udba; -+ -+ err = 0; -+ a->src_h_parent = au_h_dptr(a->src_parent, a->btgt); -+ a->src_hdir = au_hi(a->src_dir, a->btgt); -+ a->dst_h_parent = au_h_dptr(a->dst_parent, a->btgt); -+ a->dst_hdir = au_hi(a->dst_dir, a->btgt); -+ -+ err = vfsub_mnt_want_write(au_br_mnt(a->br)); -+ if (unlikely(err)) -+ goto out; -+ au_fset_ren(a->auren_flags, MNT_WRITE); -+ if (au_ftest_ren(a->auren_flags, DIRREN)) { -+ struct dentry *root; -+ struct inode *dir; -+ -+ /* -+ * sbinfo is already locked, so this ii_read_lock is -+ * unnecessary. but our debugging feature checks it. -+ */ -+ root = a->src_inode->i_sb->s_root; -+ if (root != a->src_parent && root != a->dst_parent) { -+ dir = d_inode(root); -+ ii_read_lock_parent3(dir); -+ a->h_root = au_hi(dir, a->btgt); -+ ii_read_unlock(dir); -+ au_hn_inode_lock_nested(a->h_root, AuLsc_I_PARENT3); -+ } -+ } -+ a->h_trap = vfsub_lock_rename(a->src_h_parent, a->src_hdir, -+ a->dst_h_parent, a->dst_hdir); -+ udba = au_opt_udba(a->src_dentry->d_sb); -+ if (unlikely(a->src_hdir->hi_inode != d_inode(a->src_h_parent) -+ || a->dst_hdir->hi_inode != d_inode(a->dst_h_parent))) -+ err = au_busy_or_stale(); -+ if (!err && au_dbtop(a->src_dentry) == a->btgt) -+ err = au_h_verify(a->src_h_dentry, udba, -+ d_inode(a->src_h_parent), a->src_h_parent, -+ a->br); -+ if (!err && au_dbtop(a->dst_dentry) == a->btgt) -+ err = au_h_verify(a->dst_h_dentry, udba, -+ d_inode(a->dst_h_parent), a->dst_h_parent, -+ a->br); -+ if (!err) -+ goto out; /* success */ -+ -+ err = au_busy_or_stale(); -+ au_ren_unlock(a); -+ -+out: -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static void au_ren_refresh_dir(struct au_ren_args *a) -+{ -+ struct inode *dir; -+ -+ dir = a->dst_dir; -+ inode_inc_iversion(dir); -+ if (au_ftest_ren(a->auren_flags, ISDIR_SRC)) { -+ /* is this updating defined in POSIX? */ -+ au_cpup_attr_timesizes(a->src_inode); -+ au_cpup_attr_nlink(dir, /*force*/1); -+ } -+ au_dir_ts(dir, a->btgt); -+ -+ if (a->exchange) { -+ dir = a->src_dir; -+ inode_inc_iversion(dir); -+ if (au_ftest_ren(a->auren_flags, ISDIR_DST)) { -+ /* is this updating defined in POSIX? */ -+ au_cpup_attr_timesizes(a->dst_inode); -+ au_cpup_attr_nlink(dir, /*force*/1); -+ } -+ au_dir_ts(dir, a->btgt); -+ } -+ -+ if (au_ftest_ren(a->auren_flags, ISSAMEDIR)) -+ return; -+ -+ dir = a->src_dir; -+ inode_inc_iversion(dir); -+ if (au_ftest_ren(a->auren_flags, ISDIR_SRC)) -+ au_cpup_attr_nlink(dir, /*force*/1); -+ au_dir_ts(dir, a->btgt); -+} -+ -+static void au_ren_refresh(struct au_ren_args *a) -+{ -+ aufs_bindex_t bbot, bindex; -+ struct dentry *d, *h_d; -+ struct inode *i, *h_i; -+ struct super_block *sb; -+ -+ d = a->dst_dentry; -+ d_drop(d); -+ if (a->h_dst) -+ /* already dget-ed by au_ren_or_cpup() */ -+ au_set_h_dptr(d, a->btgt, a->h_dst); -+ -+ i = a->dst_inode; -+ if (i) { -+ if (!a->exchange) { -+ if (!au_ftest_ren(a->auren_flags, ISDIR_DST)) -+ vfsub_drop_nlink(i); -+ else { -+ vfsub_dead_dir(i); -+ au_cpup_attr_timesizes(i); -+ } -+ au_update_dbrange(d, /*do_put_zero*/1); -+ } else -+ au_cpup_attr_nlink(i, /*force*/1); -+ } else { -+ bbot = a->btgt; -+ for (bindex = au_dbtop(d); bindex < bbot; bindex++) -+ au_set_h_dptr(d, bindex, NULL); -+ bbot = au_dbbot(d); -+ for (bindex = a->btgt + 1; bindex <= bbot; bindex++) -+ au_set_h_dptr(d, bindex, NULL); -+ au_update_dbrange(d, /*do_put_zero*/0); -+ } -+ -+ if (a->exchange -+ || au_ftest_ren(a->auren_flags, DIRREN)) { -+ d_drop(a->src_dentry); -+ if (au_ftest_ren(a->auren_flags, DIRREN)) -+ au_set_dbwh(a->src_dentry, -1); -+ return; -+ } -+ -+ d = a->src_dentry; -+ au_set_dbwh(d, -1); -+ bbot = au_dbbot(d); -+ for (bindex = a->btgt + 1; bindex <= bbot; bindex++) { -+ h_d = au_h_dptr(d, bindex); -+ if (h_d) -+ au_set_h_dptr(d, bindex, NULL); -+ } -+ au_set_dbbot(d, a->btgt); -+ -+ sb = d->d_sb; -+ i = a->src_inode; -+ if (au_opt_test(au_mntflags(sb), PLINK) && au_plink_test(i)) -+ return; /* success */ -+ -+ bbot = au_ibbot(i); -+ for (bindex = a->btgt + 1; bindex <= bbot; bindex++) { -+ h_i = au_h_iptr(i, bindex); -+ if (h_i) { -+ au_xino_write(sb, bindex, h_i->i_ino, /*ino*/0); -+ /* ignore this error */ -+ au_set_h_iptr(i, bindex, NULL, 0); -+ } -+ } -+ au_set_ibbot(i, a->btgt); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* mainly for link(2) and rename(2) */ -+int au_wbr(struct dentry *dentry, aufs_bindex_t btgt) -+{ -+ aufs_bindex_t bdiropq, bwh; -+ struct dentry *parent; -+ struct au_branch *br; -+ -+ parent = dentry->d_parent; -+ IMustLock(d_inode(parent)); /* dir is locked */ -+ -+ bdiropq = au_dbdiropq(parent); -+ bwh = au_dbwh(dentry); -+ br = au_sbr(dentry->d_sb, btgt); -+ if (au_br_rdonly(br) -+ || (0 <= bdiropq && bdiropq < btgt) -+ || (0 <= bwh && bwh < btgt)) -+ btgt = -1; -+ -+ AuDbg("btgt %d\n", btgt); -+ return btgt; -+} -+ -+/* sets src_btop, dst_btop and btgt */ -+static int au_ren_wbr(struct au_ren_args *a) -+{ -+ int err; -+ struct au_wr_dir_args wr_dir_args = { -+ /* .force_btgt = -1, */ -+ .flags = AuWrDir_ADD_ENTRY -+ }; -+ -+ a->src_btop = au_dbtop(a->src_dentry); -+ a->dst_btop = au_dbtop(a->dst_dentry); -+ if (au_ftest_ren(a->auren_flags, ISDIR_SRC) -+ || au_ftest_ren(a->auren_flags, ISDIR_DST)) -+ au_fset_wrdir(wr_dir_args.flags, ISDIR); -+ wr_dir_args.force_btgt = a->src_btop; -+ if (a->dst_inode && a->dst_btop < a->src_btop) -+ wr_dir_args.force_btgt = a->dst_btop; -+ wr_dir_args.force_btgt = au_wbr(a->dst_dentry, wr_dir_args.force_btgt); -+ err = au_wr_dir(a->dst_dentry, a->src_dentry, &wr_dir_args); -+ a->btgt = err; -+ if (a->exchange) -+ au_update_dbtop(a->dst_dentry); -+ -+ return err; -+} -+ -+static void au_ren_dt(struct au_ren_args *a) -+{ -+ a->h_path.dentry = a->src_h_parent; -+ au_dtime_store(a->src_dt + AuPARENT, a->src_parent, &a->h_path); -+ if (!au_ftest_ren(a->auren_flags, ISSAMEDIR)) { -+ a->h_path.dentry = a->dst_h_parent; -+ au_dtime_store(a->dst_dt + AuPARENT, a->dst_parent, &a->h_path); -+ } -+ -+ au_fclr_ren(a->auren_flags, DT_DSTDIR); -+ if (!au_ftest_ren(a->auren_flags, ISDIR_SRC) -+ && !a->exchange) -+ return; -+ -+ a->h_path.dentry = a->src_h_dentry; -+ au_dtime_store(a->src_dt + AuCHILD, a->src_dentry, &a->h_path); -+ if (d_is_positive(a->dst_h_dentry)) { -+ au_fset_ren(a->auren_flags, DT_DSTDIR); -+ a->h_path.dentry = a->dst_h_dentry; -+ au_dtime_store(a->dst_dt + AuCHILD, a->dst_dentry, &a->h_path); -+ } -+} -+ -+static void au_ren_rev_dt(int err, struct au_ren_args *a) -+{ -+ struct dentry *h_d; -+ struct inode *h_inode; -+ -+ au_dtime_revert(a->src_dt + AuPARENT); -+ if (!au_ftest_ren(a->auren_flags, ISSAMEDIR)) -+ au_dtime_revert(a->dst_dt + AuPARENT); -+ -+ if (au_ftest_ren(a->auren_flags, ISDIR_SRC) && err != -EIO) { -+ h_d = a->src_dt[AuCHILD].dt_h_path.dentry; -+ h_inode = d_inode(h_d); -+ inode_lock_nested(h_inode, AuLsc_I_CHILD); -+ au_dtime_revert(a->src_dt + AuCHILD); -+ inode_unlock(h_inode); -+ -+ if (au_ftest_ren(a->auren_flags, DT_DSTDIR)) { -+ h_d = a->dst_dt[AuCHILD].dt_h_path.dentry; -+ h_inode = d_inode(h_d); -+ inode_lock_nested(h_inode, AuLsc_I_CHILD); -+ au_dtime_revert(a->dst_dt + AuCHILD); -+ inode_unlock(h_inode); -+ } -+ } -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+int aufs_rename(struct inode *_src_dir, struct dentry *_src_dentry, -+ struct inode *_dst_dir, struct dentry *_dst_dentry, -+ unsigned int _flags) -+{ -+ int err, lock_flags; -+ void *rev; -+ /* reduce stack space */ -+ struct au_ren_args *a; -+ struct au_pin pin; -+ -+ AuDbg("%pd, %pd, 0x%x\n", _src_dentry, _dst_dentry, _flags); -+ IMustLock(_src_dir); -+ IMustLock(_dst_dir); -+ -+ err = -EINVAL; -+ if (unlikely(_flags & RENAME_WHITEOUT)) -+ goto out; -+ -+ err = -ENOMEM; -+ BUILD_BUG_ON(sizeof(*a) > PAGE_SIZE); -+ a = kzalloc(sizeof(*a), GFP_NOFS); -+ if (unlikely(!a)) -+ goto out; -+ -+ a->flags = _flags; -+ BUILD_BUG_ON(sizeof(a->exchange) == sizeof(u8) -+ && RENAME_EXCHANGE > U8_MAX); -+ a->exchange = _flags & RENAME_EXCHANGE; -+ a->src_dir = _src_dir; -+ a->src_dentry = _src_dentry; -+ a->src_inode = NULL; -+ if (d_really_is_positive(a->src_dentry)) -+ a->src_inode = d_inode(a->src_dentry); -+ a->src_parent = a->src_dentry->d_parent; /* dir inode is locked */ -+ a->dst_dir = _dst_dir; -+ a->dst_dentry = _dst_dentry; -+ a->dst_inode = NULL; -+ if (d_really_is_positive(a->dst_dentry)) -+ a->dst_inode = d_inode(a->dst_dentry); -+ a->dst_parent = a->dst_dentry->d_parent; /* dir inode is locked */ -+ if (a->dst_inode) { -+ /* -+ * if EXCHANGE && src is non-dir && dst is dir, -+ * dst is not locked. -+ */ -+ /* IMustLock(a->dst_inode); */ -+ au_igrab(a->dst_inode); -+ } -+ -+ err = -ENOTDIR; -+ lock_flags = AuLock_FLUSH | AuLock_NOPLM | AuLock_GEN; -+ if (d_is_dir(a->src_dentry)) { -+ au_fset_ren(a->auren_flags, ISDIR_SRC); -+ if (unlikely(!a->exchange -+ && d_really_is_positive(a->dst_dentry) -+ && !d_is_dir(a->dst_dentry))) -+ goto out_free; -+ lock_flags |= AuLock_DIRS; -+ } -+ if (a->dst_inode && d_is_dir(a->dst_dentry)) { -+ au_fset_ren(a->auren_flags, ISDIR_DST); -+ if (unlikely(!a->exchange -+ && d_really_is_positive(a->src_dentry) -+ && !d_is_dir(a->src_dentry))) -+ goto out_free; -+ lock_flags |= AuLock_DIRS; -+ } -+ err = aufs_read_and_write_lock2(a->dst_dentry, a->src_dentry, -+ lock_flags); -+ if (unlikely(err)) -+ goto out_free; -+ -+ err = au_d_hashed_positive(a->src_dentry); -+ if (unlikely(err)) -+ goto out_unlock; -+ err = -ENOENT; -+ if (a->dst_inode) { -+ /* -+ * If it is a dir, VFS unhash it before this -+ * function. It means we cannot rely upon d_unhashed(). -+ */ -+ if (unlikely(!a->dst_inode->i_nlink)) -+ goto out_unlock; -+ if (!au_ftest_ren(a->auren_flags, ISDIR_DST)) { -+ err = au_d_hashed_positive(a->dst_dentry); -+ if (unlikely(err && !a->exchange)) -+ goto out_unlock; -+ } else if (unlikely(IS_DEADDIR(a->dst_inode))) -+ goto out_unlock; -+ } else if (unlikely(d_unhashed(a->dst_dentry))) -+ goto out_unlock; -+ -+ /* -+ * is it possible? -+ * yes, it happened (in linux-3.3-rcN) but I don't know why. -+ * there may exist a problem somewhere else. -+ */ -+ err = -EINVAL; -+ if (unlikely(d_inode(a->dst_parent) == d_inode(a->src_dentry))) -+ goto out_unlock; -+ -+ au_fset_ren(a->auren_flags, ISSAMEDIR); /* temporary */ -+ di_write_lock_parent(a->dst_parent); -+ -+ /* which branch we process */ -+ err = au_ren_wbr(a); -+ if (unlikely(err < 0)) -+ goto out_parent; -+ a->br = au_sbr(a->dst_dentry->d_sb, a->btgt); -+ a->h_path.mnt = au_br_mnt(a->br); -+ -+ /* are they available to be renamed */ -+ err = au_ren_may_dir(a); -+ if (unlikely(err)) -+ goto out_children; -+ -+ /* prepare the writable parent dir on the same branch */ -+ if (a->dst_btop == a->btgt) { -+ au_fset_ren(a->auren_flags, WHDST); -+ } else { -+ err = au_cpup_dirs(a->dst_dentry, a->btgt); -+ if (unlikely(err)) -+ goto out_children; -+ } -+ -+ err = 0; -+ if (!a->exchange) { -+ if (a->src_dir != a->dst_dir) { -+ /* -+ * this temporary unlock is safe, -+ * because both dir->i_mutex are locked. -+ */ -+ di_write_unlock(a->dst_parent); -+ di_write_lock_parent(a->src_parent); -+ err = au_wr_dir_need_wh(a->src_dentry, -+ au_ftest_ren(a->auren_flags, -+ ISDIR_SRC), -+ &a->btgt); -+ di_write_unlock(a->src_parent); -+ di_write_lock2_parent(a->src_parent, a->dst_parent, -+ /*isdir*/1); -+ au_fclr_ren(a->auren_flags, ISSAMEDIR); -+ } else -+ err = au_wr_dir_need_wh(a->src_dentry, -+ au_ftest_ren(a->auren_flags, -+ ISDIR_SRC), -+ &a->btgt); -+ } -+ if (unlikely(err < 0)) -+ goto out_children; -+ if (err) -+ au_fset_ren(a->auren_flags, WHSRC); -+ -+ /* cpup src */ -+ if (a->src_btop != a->btgt) { -+ err = au_pin(&pin, a->src_dentry, a->btgt, -+ au_opt_udba(a->src_dentry->d_sb), -+ AuPin_DI_LOCKED | AuPin_MNT_WRITE); -+ if (!err) { -+ struct au_cp_generic cpg = { -+ .dentry = a->src_dentry, -+ .bdst = a->btgt, -+ .bsrc = a->src_btop, -+ .len = -1, -+ .pin = &pin, -+ .flags = AuCpup_DTIME | AuCpup_HOPEN -+ }; -+ AuDebugOn(au_dbtop(a->src_dentry) != a->src_btop); -+ err = au_sio_cpup_simple(&cpg); -+ au_unpin(&pin); -+ } -+ if (unlikely(err)) -+ goto out_children; -+ a->src_btop = a->btgt; -+ a->src_h_dentry = au_h_dptr(a->src_dentry, a->btgt); -+ if (!a->exchange) -+ au_fset_ren(a->auren_flags, WHSRC); -+ } -+ -+ /* cpup dst */ -+ if (a->exchange && a->dst_inode -+ && a->dst_btop != a->btgt) { -+ err = au_pin(&pin, a->dst_dentry, a->btgt, -+ au_opt_udba(a->dst_dentry->d_sb), -+ AuPin_DI_LOCKED | AuPin_MNT_WRITE); -+ if (!err) { -+ struct au_cp_generic cpg = { -+ .dentry = a->dst_dentry, -+ .bdst = a->btgt, -+ .bsrc = a->dst_btop, -+ .len = -1, -+ .pin = &pin, -+ .flags = AuCpup_DTIME | AuCpup_HOPEN -+ }; -+ err = au_sio_cpup_simple(&cpg); -+ au_unpin(&pin); -+ } -+ if (unlikely(err)) -+ goto out_children; -+ a->dst_btop = a->btgt; -+ a->dst_h_dentry = au_h_dptr(a->dst_dentry, a->btgt); -+ } -+ -+ /* lock them all */ -+ err = au_ren_lock(a); -+ if (unlikely(err)) -+ /* leave the copied-up one */ -+ goto out_children; -+ -+ if (!a->exchange) { -+ if (!au_opt_test(au_mntflags(a->dst_dir->i_sb), UDBA_NONE)) -+ err = au_may_ren(a); -+ else if (unlikely(a->dst_dentry->d_name.len > AUFS_MAX_NAMELEN)) -+ err = -ENAMETOOLONG; -+ if (unlikely(err)) -+ goto out_hdir; -+ } -+ -+ /* store timestamps to be revertible */ -+ au_ren_dt(a); -+ -+ /* store dirren info */ -+ if (au_ftest_ren(a->auren_flags, DIRREN)) { -+ err = au_dr_rename(a->src_dentry, a->btgt, -+ &a->dst_dentry->d_name, &rev); -+ AuTraceErr(err); -+ if (unlikely(err)) -+ goto out_dt; -+ } -+ -+ /* here we go */ -+ err = do_rename(a); -+ if (unlikely(err)) -+ goto out_dirren; -+ -+ if (au_ftest_ren(a->auren_flags, DIRREN)) -+ au_dr_rename_fin(a->src_dentry, a->btgt, rev); -+ -+ /* update dir attributes */ -+ au_ren_refresh_dir(a); -+ -+ /* dput/iput all lower dentries */ -+ au_ren_refresh(a); -+ -+ goto out_hdir; /* success */ -+ -+out_dirren: -+ if (au_ftest_ren(a->auren_flags, DIRREN)) -+ au_dr_rename_rev(a->src_dentry, a->btgt, rev); -+out_dt: -+ au_ren_rev_dt(err, a); -+out_hdir: -+ au_ren_unlock(a); -+out_children: -+ au_nhash_wh_free(&a->whlist); -+ if (err && a->dst_inode && a->dst_btop != a->btgt) { -+ AuDbg("btop %d, btgt %d\n", a->dst_btop, a->btgt); -+ au_set_h_dptr(a->dst_dentry, a->btgt, NULL); -+ au_set_dbtop(a->dst_dentry, a->dst_btop); -+ } -+out_parent: -+ if (!err) { -+ if (d_unhashed(a->src_dentry)) -+ au_fset_ren(a->auren_flags, DROPPED_SRC); -+ if (d_unhashed(a->dst_dentry)) -+ au_fset_ren(a->auren_flags, DROPPED_DST); -+ if (!a->exchange) -+ d_move(a->src_dentry, a->dst_dentry); -+ else { -+ d_exchange(a->src_dentry, a->dst_dentry); -+ if (au_ftest_ren(a->auren_flags, DROPPED_DST)) -+ d_drop(a->dst_dentry); -+ } -+ if (au_ftest_ren(a->auren_flags, DROPPED_SRC)) -+ d_drop(a->src_dentry); -+ } else { -+ au_update_dbtop(a->dst_dentry); -+ if (!a->dst_inode) -+ d_drop(a->dst_dentry); -+ } -+ if (au_ftest_ren(a->auren_flags, ISSAMEDIR)) -+ di_write_unlock(a->dst_parent); -+ else -+ di_write_unlock2(a->src_parent, a->dst_parent); -+out_unlock: -+ aufs_read_and_write_unlock2(a->dst_dentry, a->src_dentry); -+out_free: -+ iput(a->dst_inode); -+ if (a->thargs) -+ au_whtmp_rmdir_free(a->thargs); -+ au_kfree_rcu(a); -+out: -+ AuTraceErr(err); -+ return err; -+} -diff -Nurp linux-5.10-rc6/fs/aufs/Kconfig linux-5.10-rc6.aufs/fs/aufs/Kconfig ---- linux-5.10-rc6/fs/aufs/Kconfig 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/Kconfig 2020-12-02 21:19:51.879036653 +0200 -@@ -0,0 +1,199 @@ -+# SPDX-License-Identifier: GPL-2.0 -+config AUFS_FS -+ tristate "Aufs (Advanced multi layered unification filesystem) support" -+ help -+ Aufs is a stackable unification filesystem such as Unionfs, -+ which unifies several directories and provides a merged single -+ directory. -+ In the early days, aufs was entirely re-designed and -+ re-implemented Unionfs Version 1.x series. Introducing many -+ original ideas, approaches and improvements, it becomes totally -+ different from Unionfs while keeping the basic features. -+ -+if AUFS_FS -+choice -+ prompt "Maximum number of branches" -+ default AUFS_BRANCH_MAX_127 -+ help -+ Specifies the maximum number of branches (or member directories) -+ in a single aufs. The larger value consumes more system -+ resources and has a minor impact to performance. -+config AUFS_BRANCH_MAX_127 -+ bool "127" -+ help -+ Specifies the maximum number of branches (or member directories) -+ in a single aufs. The larger value consumes more system -+ resources and has a minor impact to performance. -+config AUFS_BRANCH_MAX_511 -+ bool "511" -+ help -+ Specifies the maximum number of branches (or member directories) -+ in a single aufs. The larger value consumes more system -+ resources and has a minor impact to performance. -+config AUFS_BRANCH_MAX_1023 -+ bool "1023" -+ help -+ Specifies the maximum number of branches (or member directories) -+ in a single aufs. The larger value consumes more system -+ resources and has a minor impact to performance. -+config AUFS_BRANCH_MAX_32767 -+ bool "32767" -+ help -+ Specifies the maximum number of branches (or member directories) -+ in a single aufs. The larger value consumes more system -+ resources and has a minor impact to performance. -+endchoice -+ -+config AUFS_SBILIST -+ bool -+ depends on AUFS_MAGIC_SYSRQ || PROC_FS -+ default y -+ help -+ Automatic configuration for internal use. -+ When aufs supports Magic SysRq or /proc, enabled automatically. -+ -+config AUFS_HNOTIFY -+ bool "Detect direct branch access (bypassing aufs)" -+ help -+ If you want to modify files on branches directly, eg. bypassing aufs, -+ and want aufs to detect the changes of them fully, then enable this -+ option and use 'udba=notify' mount option. -+ Currently there is only one available configuration, "fsnotify". -+ It will have a negative impact to the performance. -+ See detail in aufs.5. -+ -+choice -+ prompt "method" if AUFS_HNOTIFY -+ default AUFS_HFSNOTIFY -+config AUFS_HFSNOTIFY -+ bool "fsnotify" -+ select FSNOTIFY -+endchoice -+ -+config AUFS_EXPORT -+ bool "NFS-exportable aufs" -+ depends on EXPORTFS = y -+ help -+ If you want to export your mounted aufs via NFS, then enable this -+ option. There are several requirements for this configuration. -+ See detail in aufs.5. -+ -+config AUFS_INO_T_64 -+ bool -+ depends on AUFS_EXPORT -+ depends on 64BIT && !(ALPHA || S390) -+ default y -+ help -+ Automatic configuration for internal use. -+ /* typedef unsigned long/int __kernel_ino_t */ -+ /* alpha and s390x are int */ -+ -+config AUFS_XATTR -+ bool "support for XATTR/EA (including Security Labels)" -+ help -+ If your branch fs supports XATTR/EA and you want to make them -+ available in aufs too, then enable this opsion and specify the -+ branch attributes for EA. -+ See detail in aufs.5. -+ -+config AUFS_FHSM -+ bool "File-based Hierarchical Storage Management" -+ help -+ Hierarchical Storage Management (or HSM) is a well-known feature -+ in the storage world. Aufs provides this feature as file-based. -+ with multiple branches. -+ These multiple branches are prioritized, ie. the topmost one -+ should be the fastest drive and be used heavily. -+ -+config AUFS_RDU -+ bool "Readdir in userspace" -+ help -+ Aufs has two methods to provide a merged view for a directory, -+ by a user-space library and by kernel-space natively. The latter -+ is always enabled but sometimes large and slow. -+ If you enable this option, install the library in aufs2-util -+ package, and set some environment variables for your readdir(3), -+ then the work will be handled in user-space which generally -+ shows better performance in most cases. -+ See detail in aufs.5. -+ -+config AUFS_DIRREN -+ bool "Workaround for rename(2)-ing a directory" -+ help -+ By default, aufs returns EXDEV error in renameing a dir who has -+ his child on the lower branch, since it is a bad idea to issue -+ rename(2) internally for every lower branch. But user may not -+ accept this behaviour. So here is a workaround to allow such -+ rename(2) and store some extra infromation on the writable -+ branch. Obviously this costs high (and I don't like it). -+ To use this feature, you need to enable this configuration AND -+ to specify the mount option `dirren.' -+ See details in aufs.5 and the design documents. -+ -+config AUFS_SHWH -+ bool "Show whiteouts" -+ help -+ If you want to make the whiteouts in aufs visible, then enable -+ this option and specify 'shwh' mount option. Although it may -+ sounds like philosophy or something, but in technically it -+ simply shows the name of whiteout with keeping its behaviour. -+ -+config AUFS_BR_RAMFS -+ bool "Ramfs (initramfs/rootfs) as an aufs branch" -+ help -+ If you want to use ramfs as an aufs branch fs, then enable this -+ option. Generally tmpfs is recommended. -+ Aufs prohibited them to be a branch fs by default, because -+ initramfs becomes unusable after switch_root or something -+ generally. If you sets initramfs as an aufs branch and boot your -+ system by switch_root, you will meet a problem easily since the -+ files in initramfs may be inaccessible. -+ Unless you are going to use ramfs as an aufs branch fs without -+ switch_root or something, leave it N. -+ -+config AUFS_BR_FUSE -+ bool "Fuse fs as an aufs branch" -+ depends on FUSE_FS -+ select AUFS_POLL -+ help -+ If you want to use fuse-based userspace filesystem as an aufs -+ branch fs, then enable this option. -+ It implements the internal poll(2) operation which is -+ implemented by fuse only (curretnly). -+ -+config AUFS_POLL -+ bool -+ help -+ Automatic configuration for internal use. -+ -+config AUFS_BR_HFSPLUS -+ bool "Hfsplus as an aufs branch" -+ depends on HFSPLUS_FS -+ default y -+ help -+ If you want to use hfsplus fs as an aufs branch fs, then enable -+ this option. This option introduces a small overhead at -+ copying-up a file on hfsplus. -+ -+config AUFS_BDEV_LOOP -+ bool -+ depends on BLK_DEV_LOOP -+ default y -+ help -+ Automatic configuration for internal use. -+ Convert =[ym] into =y. -+ -+config AUFS_DEBUG -+ bool "Debug aufs" -+ help -+ Enable this to compile aufs internal debug code. -+ It will have a negative impact to the performance. -+ -+config AUFS_MAGIC_SYSRQ -+ bool -+ depends on AUFS_DEBUG && MAGIC_SYSRQ -+ default y -+ help -+ Automatic configuration for internal use. -+ When aufs supports Magic SysRq, enabled automatically. -+endif -diff -Nurp linux-5.10-rc6/fs/aufs/lcnt.h linux-5.10-rc6.aufs/fs/aufs/lcnt.h ---- linux-5.10-rc6/fs/aufs/lcnt.h 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/lcnt.h 2020-12-02 21:19:51.882036788 +0200 -@@ -0,0 +1,173 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2018-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * simple long counter wrapper -+ */ -+ -+#ifndef __AUFS_LCNT_H__ -+#define __AUFS_LCNT_H__ -+ -+#ifdef __KERNEL__ -+ -+#include "debug.h" -+ -+#define AuLCntATOMIC 1 -+#define AuLCntPCPUCNT 2 -+/* -+ * why does percpu_refcount require extra synchronize_rcu()s in -+ * au_br_do_free() -+ */ -+#define AuLCntPCPUREF 3 -+ -+/* #define AuLCntChosen AuLCntATOMIC */ -+#define AuLCntChosen AuLCntPCPUCNT -+/* #define AuLCntChosen AuLCntPCPUREF */ -+ -+#if AuLCntChosen == AuLCntATOMIC -+#include -+ -+typedef atomic_long_t au_lcnt_t; -+ -+static inline int au_lcnt_init(au_lcnt_t *cnt, void *release __maybe_unused) -+{ -+ atomic_long_set(cnt, 0); -+ return 0; -+} -+ -+static inline void au_lcnt_wait_for_fin(au_lcnt_t *cnt __maybe_unused) -+{ -+ /* empty */ -+} -+ -+static inline void au_lcnt_fin(au_lcnt_t *cnt __maybe_unused, -+ int do_sync __maybe_unused) -+{ -+ /* empty */ -+} -+ -+static inline void au_lcnt_inc(au_lcnt_t *cnt) -+{ -+ atomic_long_inc(cnt); -+} -+ -+static inline void au_lcnt_dec(au_lcnt_t *cnt) -+{ -+ atomic_long_dec(cnt); -+} -+ -+static inline long au_lcnt_read(au_lcnt_t *cnt, int do_rev __maybe_unused) -+{ -+ return atomic_long_read(cnt); -+} -+#endif -+ -+#if AuLCntChosen == AuLCntPCPUCNT -+#include -+ -+typedef struct percpu_counter au_lcnt_t; -+ -+static inline int au_lcnt_init(au_lcnt_t *cnt, void *release __maybe_unused) -+{ -+ return percpu_counter_init(cnt, 0, GFP_NOFS); -+} -+ -+static inline void au_lcnt_wait_for_fin(au_lcnt_t *cnt __maybe_unused) -+{ -+ /* empty */ -+} -+ -+static inline void au_lcnt_fin(au_lcnt_t *cnt, int do_sync __maybe_unused) -+{ -+ percpu_counter_destroy(cnt); -+} -+ -+static inline void au_lcnt_inc(au_lcnt_t *cnt) -+{ -+ percpu_counter_inc(cnt); -+} -+ -+static inline void au_lcnt_dec(au_lcnt_t *cnt) -+{ -+ percpu_counter_dec(cnt); -+} -+ -+static inline long au_lcnt_read(au_lcnt_t *cnt, int do_rev __maybe_unused) -+{ -+ s64 n; -+ -+ n = percpu_counter_sum(cnt); -+ BUG_ON(n < 0); -+ if (LONG_MAX != LLONG_MAX -+ && n > LONG_MAX) -+ AuWarn1("%s\n", "wrap-around"); -+ -+ return n; -+} -+#endif -+ -+#if AuLCntChosen == AuLCntPCPUREF -+#include -+ -+typedef struct percpu_ref au_lcnt_t; -+ -+static inline int au_lcnt_init(au_lcnt_t *cnt, percpu_ref_func_t *release) -+{ -+ if (!release) -+ release = percpu_ref_exit; -+ return percpu_ref_init(cnt, release, /*percpu mode*/0, GFP_NOFS); -+} -+ -+static inline void au_lcnt_wait_for_fin(au_lcnt_t *cnt __maybe_unused) -+{ -+ synchronize_rcu(); -+} -+ -+static inline void au_lcnt_fin(au_lcnt_t *cnt, int do_sync) -+{ -+ percpu_ref_kill(cnt); -+ if (do_sync) -+ au_lcnt_wait_for_fin(cnt); -+} -+ -+static inline void au_lcnt_inc(au_lcnt_t *cnt) -+{ -+ percpu_ref_get(cnt); -+} -+ -+static inline void au_lcnt_dec(au_lcnt_t *cnt) -+{ -+ percpu_ref_put(cnt); -+} -+ -+/* -+ * avoid calling this func as possible. -+ */ -+static inline long au_lcnt_read(au_lcnt_t *cnt, int do_rev) -+{ -+ long l; -+ -+ percpu_ref_switch_to_atomic_sync(cnt); -+ l = atomic_long_read(&cnt->count); -+ if (do_rev) -+ percpu_ref_switch_to_percpu(cnt); -+ -+ /* percpu_ref is initialized by 1 instead of 0 */ -+ return l - 1; -+} -+#endif -+ -+#ifdef CONFIG_AUFS_DEBUG -+#define AuLCntZero(val) do { \ -+ long l = val; \ -+ if (l) \ -+ AuDbg("%s = %ld\n", #val, l); \ -+} while (0) -+#else -+#define AuLCntZero(val) do {} while (0) -+#endif -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_LCNT_H__ */ -diff -Nurp linux-5.10-rc6/fs/aufs/loop.c linux-5.10-rc6.aufs/fs/aufs/loop.c ---- linux-5.10-rc6/fs/aufs/loop.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/loop.c 2020-12-02 21:19:51.882036788 +0200 -@@ -0,0 +1,135 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * support for loopback block device as a branch -+ */ -+ -+#include "aufs.h" -+ -+/* added into drivers/block/loop.c */ -+static struct file *(*backing_file_func)(struct super_block *sb); -+ -+/* -+ * test if two lower dentries have overlapping branches. -+ */ -+int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_adding) -+{ -+ struct super_block *h_sb; -+ struct file *backing_file; -+ -+ if (unlikely(!backing_file_func)) { -+ /* don't load "loop" module here */ -+ backing_file_func = symbol_get(loop_backing_file); -+ if (unlikely(!backing_file_func)) -+ /* "loop" module is not loaded */ -+ return 0; -+ } -+ -+ h_sb = h_adding->d_sb; -+ backing_file = backing_file_func(h_sb); -+ if (!backing_file) -+ return 0; -+ -+ h_adding = backing_file->f_path.dentry; -+ /* -+ * h_adding can be local NFS. -+ * in this case aufs cannot detect the loop. -+ */ -+ if (unlikely(h_adding->d_sb == sb)) -+ return 1; -+ return !!au_test_subdir(h_adding, sb->s_root); -+} -+ -+/* true if a kernel thread named 'loop[0-9].*' accesses a file */ -+int au_test_loopback_kthread(void) -+{ -+ int ret; -+ struct task_struct *tsk = current; -+ char c, comm[sizeof(tsk->comm)]; -+ -+ ret = 0; -+ if (tsk->flags & PF_KTHREAD) { -+ get_task_comm(comm, tsk); -+ c = comm[4]; -+ ret = ('0' <= c && c <= '9' -+ && !strncmp(comm, "loop", 4)); -+ } -+ -+ return ret; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+#define au_warn_loopback_step 16 -+static int au_warn_loopback_nelem = au_warn_loopback_step; -+static unsigned long *au_warn_loopback_array; -+ -+void au_warn_loopback(struct super_block *h_sb) -+{ -+ int i, new_nelem; -+ unsigned long *a, magic; -+ static DEFINE_SPINLOCK(spin); -+ -+ magic = h_sb->s_magic; -+ spin_lock(&spin); -+ a = au_warn_loopback_array; -+ for (i = 0; i < au_warn_loopback_nelem && *a; i++) -+ if (a[i] == magic) { -+ spin_unlock(&spin); -+ return; -+ } -+ -+ /* h_sb is new to us, print it */ -+ if (i < au_warn_loopback_nelem) { -+ a[i] = magic; -+ goto pr; -+ } -+ -+ /* expand the array */ -+ new_nelem = au_warn_loopback_nelem + au_warn_loopback_step; -+ a = au_kzrealloc(au_warn_loopback_array, -+ au_warn_loopback_nelem * sizeof(unsigned long), -+ new_nelem * sizeof(unsigned long), GFP_ATOMIC, -+ /*may_shrink*/0); -+ if (a) { -+ au_warn_loopback_nelem = new_nelem; -+ au_warn_loopback_array = a; -+ a[i] = magic; -+ goto pr; -+ } -+ -+ spin_unlock(&spin); -+ AuWarn1("realloc failed, ignored\n"); -+ return; -+ -+pr: -+ spin_unlock(&spin); -+ pr_warn("you may want to try another patch for loopback file " -+ "on %s(0x%lx) branch\n", au_sbtype(h_sb), magic); -+} -+ -+int au_loopback_init(void) -+{ -+ int err; -+ struct super_block *sb __maybe_unused; -+ -+ BUILD_BUG_ON(sizeof(sb->s_magic) != sizeof(*au_warn_loopback_array)); -+ -+ err = 0; -+ au_warn_loopback_array = kcalloc(au_warn_loopback_step, -+ sizeof(unsigned long), GFP_NOFS); -+ if (unlikely(!au_warn_loopback_array)) -+ err = -ENOMEM; -+ -+ return err; -+} -+ -+void au_loopback_fin(void) -+{ -+ if (backing_file_func) -+ symbol_put(loop_backing_file); -+ au_kfree_try_rcu(au_warn_loopback_array); -+} -diff -Nurp linux-5.10-rc6/fs/aufs/loop.h linux-5.10-rc6.aufs/fs/aufs/loop.h ---- linux-5.10-rc6/fs/aufs/loop.h 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/loop.h 2020-12-02 21:19:51.882036788 +0200 -@@ -0,0 +1,42 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * support for loopback mount as a branch -+ */ -+ -+#ifndef __AUFS_LOOP_H__ -+#define __AUFS_LOOP_H__ -+ -+#ifdef __KERNEL__ -+ -+struct dentry; -+struct super_block; -+ -+#ifdef CONFIG_AUFS_BDEV_LOOP -+/* drivers/block/loop.c */ -+struct file *loop_backing_file(struct super_block *sb); -+ -+/* loop.c */ -+int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_adding); -+int au_test_loopback_kthread(void); -+void au_warn_loopback(struct super_block *h_sb); -+ -+int au_loopback_init(void); -+void au_loopback_fin(void); -+#else -+AuStub(struct file *, loop_backing_file, return NULL, struct super_block *sb) -+ -+AuStubInt0(au_test_loopback_overlap, struct super_block *sb, -+ struct dentry *h_adding) -+AuStubInt0(au_test_loopback_kthread, void) -+AuStubVoid(au_warn_loopback, struct super_block *h_sb) -+ -+AuStubInt0(au_loopback_init, void) -+AuStubVoid(au_loopback_fin, void) -+#endif /* BLK_DEV_LOOP */ -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_LOOP_H__ */ -diff -Nurp linux-5.10-rc6/fs/aufs/magic.mk linux-5.10-rc6.aufs/fs/aufs/magic.mk ---- linux-5.10-rc6/fs/aufs/magic.mk 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/magic.mk 2020-12-02 21:19:51.882036788 +0200 -@@ -0,0 +1,31 @@ -+# SPDX-License-Identifier: GPL-2.0 -+ -+# defined in ${srctree}/fs/fuse/inode.c -+# tristate -+ifdef CONFIG_FUSE_FS -+ccflags-y += -DFUSE_SUPER_MAGIC=0x65735546 -+endif -+ -+# defined in ${srctree}/fs/xfs/xfs_sb.h -+# tristate -+ifdef CONFIG_XFS_FS -+ccflags-y += -DXFS_SB_MAGIC=0x58465342 -+endif -+ -+# defined in ${srctree}/fs/configfs/mount.c -+# tristate -+ifdef CONFIG_CONFIGFS_FS -+ccflags-y += -DCONFIGFS_MAGIC=0x62656570 -+endif -+ -+# defined in ${srctree}/fs/ubifs/ubifs.h -+# tristate -+ifdef CONFIG_UBIFS_FS -+ccflags-y += -DUBIFS_SUPER_MAGIC=0x24051905 -+endif -+ -+# defined in ${srctree}/fs/hfsplus/hfsplus_raw.h -+# tristate -+ifdef CONFIG_HFSPLUS_FS -+ccflags-y += -DHFSPLUS_SUPER_MAGIC=0x482b -+endif -diff -Nurp linux-5.10-rc6/fs/aufs/Makefile linux-5.10-rc6.aufs/fs/aufs/Makefile ---- linux-5.10-rc6/fs/aufs/Makefile 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/Makefile 2020-12-02 21:19:51.879036653 +0200 -@@ -0,0 +1,39 @@ -+# SPDX-License-Identifier: GPL-2.0 -+ -+include ${srctree}/${src}/magic.mk -+-include ${srctree}/${src}/priv_def.mk -+ -+# cf. include/linux/kernel.h -+# enable pr_debug -+ccflags-y += -DDEBUG -+# sparse requires the full pathname -+ccflags-y += -include ${srctree}/include/uapi/linux/aufs_type.h -+ -+obj-$(CONFIG_AUFS_FS) += aufs.o -+aufs-y := module.o sbinfo.o super.o branch.o xino.o sysaufs.o opts.o \ -+ wkq.o vfsub.o dcsub.o \ -+ cpup.o whout.o wbr_policy.o \ -+ dinfo.o dentry.o \ -+ dynop.o \ -+ finfo.o file.o f_op.o \ -+ dir.o vdir.o \ -+ iinfo.o inode.o i_op.o i_op_add.o i_op_del.o i_op_ren.o \ -+ mvdown.o ioctl.o -+ -+# all are boolean -+aufs-$(CONFIG_PROC_FS) += procfs.o plink.o -+aufs-$(CONFIG_SYSFS) += sysfs.o -+aufs-$(CONFIG_DEBUG_FS) += dbgaufs.o -+aufs-$(CONFIG_AUFS_BDEV_LOOP) += loop.o -+aufs-$(CONFIG_AUFS_HNOTIFY) += hnotify.o -+aufs-$(CONFIG_AUFS_HFSNOTIFY) += hfsnotify.o -+aufs-$(CONFIG_AUFS_EXPORT) += export.o -+aufs-$(CONFIG_AUFS_XATTR) += xattr.o -+aufs-$(CONFIG_FS_POSIX_ACL) += posix_acl.o -+aufs-$(CONFIG_AUFS_DIRREN) += dirren.o -+aufs-$(CONFIG_AUFS_FHSM) += fhsm.o -+aufs-$(CONFIG_AUFS_POLL) += poll.o -+aufs-$(CONFIG_AUFS_RDU) += rdu.o -+aufs-$(CONFIG_AUFS_BR_HFSPLUS) += hfsplus.o -+aufs-$(CONFIG_AUFS_DEBUG) += debug.o -+aufs-$(CONFIG_AUFS_MAGIC_SYSRQ) += sysrq.o -diff -Nurp linux-5.10-rc6/fs/aufs/module.c linux-5.10-rc6.aufs/fs/aufs/module.c ---- linux-5.10-rc6/fs/aufs/module.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/module.c 2020-12-02 21:19:51.882036788 +0200 -@@ -0,0 +1,259 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * module global variables and operations -+ */ -+ -+#include -+#include -+#include "aufs.h" -+ -+/* shrinkable realloc */ -+void *au_krealloc(void *p, unsigned int new_sz, gfp_t gfp, int may_shrink) -+{ -+ size_t sz; -+ int diff; -+ -+ sz = 0; -+ diff = -1; -+ if (p) { -+#if 0 /* unused */ -+ if (!new_sz) { -+ au_kfree_rcu(p); -+ p = NULL; -+ goto out; -+ } -+#else -+ AuDebugOn(!new_sz); -+#endif -+ sz = ksize(p); -+ diff = au_kmidx_sub(sz, new_sz); -+ } -+ if (sz && !diff) -+ goto out; -+ -+ if (sz < new_sz) -+ /* expand or SLOB */ -+ p = krealloc(p, new_sz, gfp); -+ else if (new_sz < sz && may_shrink) { -+ /* shrink */ -+ void *q; -+ -+ q = kmalloc(new_sz, gfp); -+ if (q) { -+ if (p) { -+ memcpy(q, p, new_sz); -+ au_kfree_try_rcu(p); -+ } -+ p = q; -+ } else -+ p = NULL; -+ } -+ -+out: -+ return p; -+} -+ -+void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp, -+ int may_shrink) -+{ -+ p = au_krealloc(p, new_sz, gfp, may_shrink); -+ if (p && new_sz > nused) -+ memset(p + nused, 0, new_sz - nused); -+ return p; -+} -+ -+/* ---------------------------------------------------------------------- */ -+/* -+ * aufs caches -+ */ -+struct kmem_cache *au_cache[AuCache_Last]; -+ -+static void au_cache_fin(void) -+{ -+ int i; -+ -+ /* -+ * Make sure all delayed rcu free inodes are flushed before we -+ * destroy cache. -+ */ -+ rcu_barrier(); -+ -+ /* excluding AuCache_HNOTIFY */ -+ BUILD_BUG_ON(AuCache_HNOTIFY + 1 != AuCache_Last); -+ for (i = 0; i < AuCache_HNOTIFY; i++) { -+ kmem_cache_destroy(au_cache[i]); -+ au_cache[i] = NULL; -+ } -+} -+ -+static int __init au_cache_init(void) -+{ -+ au_cache[AuCache_DINFO] = AuCacheCtor(au_dinfo, au_di_init_once); -+ if (au_cache[AuCache_DINFO]) -+ /* SLAB_DESTROY_BY_RCU */ -+ au_cache[AuCache_ICNTNR] = AuCacheCtor(au_icntnr, -+ au_icntnr_init_once); -+ if (au_cache[AuCache_ICNTNR]) -+ au_cache[AuCache_FINFO] = AuCacheCtor(au_finfo, -+ au_fi_init_once); -+ if (au_cache[AuCache_FINFO]) -+ au_cache[AuCache_VDIR] = AuCache(au_vdir); -+ if (au_cache[AuCache_VDIR]) -+ au_cache[AuCache_DEHSTR] = AuCache(au_vdir_dehstr); -+ if (au_cache[AuCache_DEHSTR]) -+ return 0; -+ -+ au_cache_fin(); -+ return -ENOMEM; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+int au_dir_roflags; -+ -+#ifdef CONFIG_AUFS_SBILIST -+/* -+ * iterate_supers_type() doesn't protect us from -+ * remounting (branch management) -+ */ -+struct hlist_bl_head au_sbilist; -+#endif -+ -+/* -+ * functions for module interface. -+ */ -+MODULE_LICENSE("GPL"); -+/* MODULE_LICENSE("GPL v2"); */ -+MODULE_AUTHOR("Junjiro R. Okajima "); -+MODULE_DESCRIPTION(AUFS_NAME -+ " -- Advanced multi layered unification filesystem"); -+MODULE_VERSION(AUFS_VERSION); -+ -+/* this module parameter has no meaning when SYSFS is disabled */ -+int sysaufs_brs = 1; -+MODULE_PARM_DESC(brs, "use /fs/aufs/si_*/brN"); -+module_param_named(brs, sysaufs_brs, int, 0444); -+ -+/* this module parameter has no meaning when USER_NS is disabled */ -+bool au_userns; -+MODULE_PARM_DESC(allow_userns, "allow unprivileged to mount under userns"); -+module_param_named(allow_userns, au_userns, bool, 0444); -+ -+/* ---------------------------------------------------------------------- */ -+ -+static char au_esc_chars[0x20 + 3]; /* 0x01-0x20, backslash, del, and NULL */ -+ -+int au_seq_path(struct seq_file *seq, struct path *path) -+{ -+ int err; -+ -+ err = seq_path(seq, path, au_esc_chars); -+ if (err >= 0) -+ err = 0; -+ else -+ err = -ENOMEM; -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int __init aufs_init(void) -+{ -+ int err, i; -+ char *p; -+ -+ p = au_esc_chars; -+ for (i = 1; i <= ' '; i++) -+ *p++ = i; -+ *p++ = '\\'; -+ *p++ = '\x7f'; -+ *p = 0; -+ -+ au_dir_roflags = au_file_roflags(O_DIRECTORY | O_LARGEFILE); -+ -+ memcpy(aufs_iop_nogetattr, aufs_iop, sizeof(aufs_iop)); -+ for (i = 0; i < AuIop_Last; i++) -+ aufs_iop_nogetattr[i].getattr = NULL; -+ -+ memset(au_cache, 0, sizeof(au_cache)); /* including hnotify */ -+ -+ au_sbilist_init(); -+ sysaufs_brs_init(); -+ au_debug_init(); -+ au_dy_init(); -+ err = sysaufs_init(); -+ if (unlikely(err)) -+ goto out; -+ err = dbgaufs_init(); -+ if (unlikely(err)) -+ goto out_sysaufs; -+ err = au_procfs_init(); -+ if (unlikely(err)) -+ goto out_dbgaufs; -+ err = au_wkq_init(); -+ if (unlikely(err)) -+ goto out_procfs; -+ err = au_loopback_init(); -+ if (unlikely(err)) -+ goto out_wkq; -+ err = au_hnotify_init(); -+ if (unlikely(err)) -+ goto out_loopback; -+ err = au_sysrq_init(); -+ if (unlikely(err)) -+ goto out_hin; -+ err = au_cache_init(); -+ if (unlikely(err)) -+ goto out_sysrq; -+ -+ aufs_fs_type.fs_flags |= au_userns ? FS_USERNS_MOUNT : 0; -+ err = register_filesystem(&aufs_fs_type); -+ if (unlikely(err)) -+ goto out_cache; -+ -+ /* since we define pr_fmt, call printk directly */ -+ printk(KERN_INFO AUFS_NAME " " AUFS_VERSION "\n"); -+ goto out; /* success */ -+ -+out_cache: -+ au_cache_fin(); -+out_sysrq: -+ au_sysrq_fin(); -+out_hin: -+ au_hnotify_fin(); -+out_loopback: -+ au_loopback_fin(); -+out_wkq: -+ au_wkq_fin(); -+out_procfs: -+ au_procfs_fin(); -+out_dbgaufs: -+ dbgaufs_fin(); -+out_sysaufs: -+ sysaufs_fin(); -+ au_dy_fin(); -+out: -+ return err; -+} -+ -+static void __exit aufs_exit(void) -+{ -+ unregister_filesystem(&aufs_fs_type); -+ au_cache_fin(); -+ au_sysrq_fin(); -+ au_hnotify_fin(); -+ au_loopback_fin(); -+ au_wkq_fin(); -+ au_procfs_fin(); -+ dbgaufs_fin(); -+ sysaufs_fin(); -+ au_dy_fin(); -+} -+ -+module_init(aufs_init); -+module_exit(aufs_exit); -diff -Nurp linux-5.10-rc6/fs/aufs/module.h linux-5.10-rc6.aufs/fs/aufs/module.h ---- linux-5.10-rc6/fs/aufs/module.h 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/module.h 2020-12-02 21:19:51.882036788 +0200 -@@ -0,0 +1,153 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * module initialization and module-global -+ */ -+ -+#ifndef __AUFS_MODULE_H__ -+#define __AUFS_MODULE_H__ -+ -+#ifdef __KERNEL__ -+ -+#include -+#include "debug.h" -+#include "dentry.h" -+#include "dir.h" -+#include "file.h" -+#include "inode.h" -+ -+struct path; -+struct seq_file; -+ -+/* module parameters */ -+extern int sysaufs_brs; -+extern bool au_userns; -+ -+/* ---------------------------------------------------------------------- */ -+ -+extern int au_dir_roflags; -+ -+void *au_krealloc(void *p, unsigned int new_sz, gfp_t gfp, int may_shrink); -+void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp, -+ int may_shrink); -+ -+/* -+ * Comparing the size of the object with sizeof(struct rcu_head) -+ * case 1: object is always larger -+ * --> au_kfree_rcu() or au_kfree_do_rcu() -+ * case 2: object is always smaller -+ * --> au_kfree_small() -+ * case 3: object can be any size -+ * --> au_kfree_try_rcu() -+ */ -+ -+static inline void au_kfree_do_rcu(const void *p) -+{ -+ struct { -+ struct rcu_head rcu; -+ } *a = (void *)p; -+ -+ kfree_rcu(a, rcu); -+} -+ -+#define au_kfree_rcu(_p) do { \ -+ typeof(_p) p = (_p); \ -+ BUILD_BUG_ON(sizeof(*p) < sizeof(struct rcu_head)); \ -+ if (p) \ -+ au_kfree_do_rcu(p); \ -+ } while (0) -+ -+#define au_kfree_do_sz_test(sz) (sz >= sizeof(struct rcu_head)) -+#define au_kfree_sz_test(p) (p && au_kfree_do_sz_test(ksize(p))) -+ -+static inline void au_kfree_try_rcu(const void *p) -+{ -+ if (!p) -+ return; -+ if (au_kfree_sz_test(p)) -+ au_kfree_do_rcu(p); -+ else -+ kfree(p); -+} -+ -+static inline void au_kfree_small(const void *p) -+{ -+ if (!p) -+ return; -+ AuDebugOn(au_kfree_sz_test(p)); -+ kfree(p); -+} -+ -+static inline int au_kmidx_sub(size_t sz, size_t new_sz) -+{ -+#ifndef CONFIG_SLOB -+ return kmalloc_index(sz) - kmalloc_index(new_sz); -+#else -+ return -1; /* SLOB is untested */ -+#endif -+} -+ -+int au_seq_path(struct seq_file *seq, struct path *path); -+ -+#ifdef CONFIG_PROC_FS -+/* procfs.c */ -+int __init au_procfs_init(void); -+void au_procfs_fin(void); -+#else -+AuStubInt0(au_procfs_init, void); -+AuStubVoid(au_procfs_fin, void); -+#endif -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* kmem cache */ -+enum { -+ AuCache_DINFO, -+ AuCache_ICNTNR, -+ AuCache_FINFO, -+ AuCache_VDIR, -+ AuCache_DEHSTR, -+ AuCache_HNOTIFY, /* must be last */ -+ AuCache_Last -+}; -+ -+extern struct kmem_cache *au_cache[AuCache_Last]; -+ -+#define AuCacheFlags (SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD) -+#define AuCache(type) KMEM_CACHE(type, AuCacheFlags) -+#define AuCacheCtor(type, ctor) \ -+ kmem_cache_create(#type, sizeof(struct type), \ -+ __alignof__(struct type), AuCacheFlags, ctor) -+ -+#define AuCacheFuncs(name, index) \ -+ static inline struct au_##name *au_cache_alloc_##name(void) \ -+ { return kmem_cache_alloc(au_cache[AuCache_##index], GFP_NOFS); } \ -+ static inline void au_cache_free_##name##_norcu(struct au_##name *p) \ -+ { kmem_cache_free(au_cache[AuCache_##index], p); } \ -+ \ -+ static inline void au_cache_free_##name##_rcu_cb(struct rcu_head *rcu) \ -+ { void *p = rcu; \ -+ p -= offsetof(struct au_##name, rcu); \ -+ kmem_cache_free(au_cache[AuCache_##index], p); } \ -+ static inline void au_cache_free_##name##_rcu(struct au_##name *p) \ -+ { BUILD_BUG_ON(sizeof(struct au_##name) < sizeof(struct rcu_head)); \ -+ call_rcu(&p->rcu, au_cache_free_##name##_rcu_cb); } \ -+ \ -+ static inline void au_cache_free_##name(struct au_##name *p) \ -+ { /* au_cache_free_##name##_norcu(p); */ \ -+ au_cache_free_##name##_rcu(p); } -+ -+AuCacheFuncs(dinfo, DINFO); -+AuCacheFuncs(icntnr, ICNTNR); -+AuCacheFuncs(finfo, FINFO); -+AuCacheFuncs(vdir, VDIR); -+AuCacheFuncs(vdir_dehstr, DEHSTR); -+#ifdef CONFIG_AUFS_HNOTIFY -+AuCacheFuncs(hnotify, HNOTIFY); -+#endif -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_MODULE_H__ */ -diff -Nurp linux-5.10-rc6/fs/aufs/mvdown.c linux-5.10-rc6.aufs/fs/aufs/mvdown.c ---- linux-5.10-rc6/fs/aufs/mvdown.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/mvdown.c 2020-12-02 21:19:51.883036833 +0200 -@@ -0,0 +1,693 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2011-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * move-down, opposite of copy-up -+ */ -+ -+#include "aufs.h" -+ -+struct au_mvd_args { -+ struct { -+ struct super_block *h_sb; -+ struct dentry *h_parent; -+ struct au_hinode *hdir; -+ struct inode *h_dir, *h_inode; -+ struct au_pin pin; -+ } info[AUFS_MVDOWN_NARRAY]; -+ -+ struct aufs_mvdown mvdown; -+ struct dentry *dentry, *parent; -+ struct inode *inode, *dir; -+ struct super_block *sb; -+ aufs_bindex_t bopq, bwh, bfound; -+ unsigned char rename_lock; -+}; -+ -+#define mvd_errno mvdown.au_errno -+#define mvd_bsrc mvdown.stbr[AUFS_MVDOWN_UPPER].bindex -+#define mvd_src_brid mvdown.stbr[AUFS_MVDOWN_UPPER].brid -+#define mvd_bdst mvdown.stbr[AUFS_MVDOWN_LOWER].bindex -+#define mvd_dst_brid mvdown.stbr[AUFS_MVDOWN_LOWER].brid -+ -+#define mvd_h_src_sb info[AUFS_MVDOWN_UPPER].h_sb -+#define mvd_h_src_parent info[AUFS_MVDOWN_UPPER].h_parent -+#define mvd_hdir_src info[AUFS_MVDOWN_UPPER].hdir -+#define mvd_h_src_dir info[AUFS_MVDOWN_UPPER].h_dir -+#define mvd_h_src_inode info[AUFS_MVDOWN_UPPER].h_inode -+#define mvd_pin_src info[AUFS_MVDOWN_UPPER].pin -+ -+#define mvd_h_dst_sb info[AUFS_MVDOWN_LOWER].h_sb -+#define mvd_h_dst_parent info[AUFS_MVDOWN_LOWER].h_parent -+#define mvd_hdir_dst info[AUFS_MVDOWN_LOWER].hdir -+#define mvd_h_dst_dir info[AUFS_MVDOWN_LOWER].h_dir -+#define mvd_h_dst_inode info[AUFS_MVDOWN_LOWER].h_inode -+#define mvd_pin_dst info[AUFS_MVDOWN_LOWER].pin -+ -+#define AU_MVD_PR(flag, ...) do { \ -+ if (flag) \ -+ pr_err(__VA_ARGS__); \ -+ } while (0) -+ -+static int find_lower_writable(struct au_mvd_args *a) -+{ -+ struct super_block *sb; -+ aufs_bindex_t bindex, bbot; -+ struct au_branch *br; -+ -+ sb = a->sb; -+ bindex = a->mvd_bsrc; -+ bbot = au_sbbot(sb); -+ if (a->mvdown.flags & AUFS_MVDOWN_FHSM_LOWER) -+ for (bindex++; bindex <= bbot; bindex++) { -+ br = au_sbr(sb, bindex); -+ if (au_br_fhsm(br->br_perm) -+ && !sb_rdonly(au_br_sb(br))) -+ return bindex; -+ } -+ else if (!(a->mvdown.flags & AUFS_MVDOWN_ROLOWER)) -+ for (bindex++; bindex <= bbot; bindex++) { -+ br = au_sbr(sb, bindex); -+ if (!au_br_rdonly(br)) -+ return bindex; -+ } -+ else -+ for (bindex++; bindex <= bbot; bindex++) { -+ br = au_sbr(sb, bindex); -+ if (!sb_rdonly(au_br_sb(br))) { -+ if (au_br_rdonly(br)) -+ a->mvdown.flags -+ |= AUFS_MVDOWN_ROLOWER_R; -+ return bindex; -+ } -+ } -+ -+ return -1; -+} -+ -+/* make the parent dir on bdst */ -+static int au_do_mkdir(const unsigned char dmsg, struct au_mvd_args *a) -+{ -+ int err; -+ -+ err = 0; -+ a->mvd_hdir_src = au_hi(a->dir, a->mvd_bsrc); -+ a->mvd_hdir_dst = au_hi(a->dir, a->mvd_bdst); -+ a->mvd_h_src_parent = au_h_dptr(a->parent, a->mvd_bsrc); -+ a->mvd_h_dst_parent = NULL; -+ if (au_dbbot(a->parent) >= a->mvd_bdst) -+ a->mvd_h_dst_parent = au_h_dptr(a->parent, a->mvd_bdst); -+ if (!a->mvd_h_dst_parent) { -+ err = au_cpdown_dirs(a->dentry, a->mvd_bdst); -+ if (unlikely(err)) { -+ AU_MVD_PR(dmsg, "cpdown_dirs failed\n"); -+ goto out; -+ } -+ a->mvd_h_dst_parent = au_h_dptr(a->parent, a->mvd_bdst); -+ } -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+/* lock them all */ -+static int au_do_lock(const unsigned char dmsg, struct au_mvd_args *a) -+{ -+ int err; -+ struct dentry *h_trap; -+ -+ a->mvd_h_src_sb = au_sbr_sb(a->sb, a->mvd_bsrc); -+ a->mvd_h_dst_sb = au_sbr_sb(a->sb, a->mvd_bdst); -+ err = au_pin(&a->mvd_pin_dst, a->dentry, a->mvd_bdst, -+ au_opt_udba(a->sb), -+ AuPin_MNT_WRITE | AuPin_DI_LOCKED); -+ AuTraceErr(err); -+ if (unlikely(err)) { -+ AU_MVD_PR(dmsg, "pin_dst failed\n"); -+ goto out; -+ } -+ -+ if (a->mvd_h_src_sb != a->mvd_h_dst_sb) { -+ a->rename_lock = 0; -+ au_pin_init(&a->mvd_pin_src, a->dentry, a->mvd_bsrc, -+ AuLsc_DI_PARENT, AuLsc_I_PARENT3, -+ au_opt_udba(a->sb), -+ AuPin_MNT_WRITE | AuPin_DI_LOCKED); -+ err = au_do_pin(&a->mvd_pin_src); -+ AuTraceErr(err); -+ a->mvd_h_src_dir = d_inode(a->mvd_h_src_parent); -+ if (unlikely(err)) { -+ AU_MVD_PR(dmsg, "pin_src failed\n"); -+ goto out_dst; -+ } -+ goto out; /* success */ -+ } -+ -+ a->rename_lock = 1; -+ au_pin_hdir_unlock(&a->mvd_pin_dst); -+ err = au_pin(&a->mvd_pin_src, a->dentry, a->mvd_bsrc, -+ au_opt_udba(a->sb), -+ AuPin_MNT_WRITE | AuPin_DI_LOCKED); -+ AuTraceErr(err); -+ a->mvd_h_src_dir = d_inode(a->mvd_h_src_parent); -+ if (unlikely(err)) { -+ AU_MVD_PR(dmsg, "pin_src failed\n"); -+ au_pin_hdir_lock(&a->mvd_pin_dst); -+ goto out_dst; -+ } -+ au_pin_hdir_unlock(&a->mvd_pin_src); -+ h_trap = vfsub_lock_rename(a->mvd_h_src_parent, a->mvd_hdir_src, -+ a->mvd_h_dst_parent, a->mvd_hdir_dst); -+ if (h_trap) { -+ err = (h_trap != a->mvd_h_src_parent); -+ if (err) -+ err = (h_trap != a->mvd_h_dst_parent); -+ } -+ BUG_ON(err); /* it should never happen */ -+ if (unlikely(a->mvd_h_src_dir != au_pinned_h_dir(&a->mvd_pin_src))) { -+ err = -EBUSY; -+ AuTraceErr(err); -+ vfsub_unlock_rename(a->mvd_h_src_parent, a->mvd_hdir_src, -+ a->mvd_h_dst_parent, a->mvd_hdir_dst); -+ au_pin_hdir_lock(&a->mvd_pin_src); -+ au_unpin(&a->mvd_pin_src); -+ au_pin_hdir_lock(&a->mvd_pin_dst); -+ goto out_dst; -+ } -+ goto out; /* success */ -+ -+out_dst: -+ au_unpin(&a->mvd_pin_dst); -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+static void au_do_unlock(const unsigned char dmsg, struct au_mvd_args *a) -+{ -+ if (!a->rename_lock) -+ au_unpin(&a->mvd_pin_src); -+ else { -+ vfsub_unlock_rename(a->mvd_h_src_parent, a->mvd_hdir_src, -+ a->mvd_h_dst_parent, a->mvd_hdir_dst); -+ au_pin_hdir_lock(&a->mvd_pin_src); -+ au_unpin(&a->mvd_pin_src); -+ au_pin_hdir_lock(&a->mvd_pin_dst); -+ } -+ au_unpin(&a->mvd_pin_dst); -+} -+ -+/* copy-down the file */ -+static int au_do_cpdown(const unsigned char dmsg, struct au_mvd_args *a) -+{ -+ int err; -+ struct au_cp_generic cpg = { -+ .dentry = a->dentry, -+ .bdst = a->mvd_bdst, -+ .bsrc = a->mvd_bsrc, -+ .len = -1, -+ .pin = &a->mvd_pin_dst, -+ .flags = AuCpup_DTIME | AuCpup_HOPEN -+ }; -+ -+ AuDbg("b%d, b%d\n", cpg.bsrc, cpg.bdst); -+ if (a->mvdown.flags & AUFS_MVDOWN_OWLOWER) -+ au_fset_cpup(cpg.flags, OVERWRITE); -+ if (a->mvdown.flags & AUFS_MVDOWN_ROLOWER) -+ au_fset_cpup(cpg.flags, RWDST); -+ err = au_sio_cpdown_simple(&cpg); -+ if (unlikely(err)) -+ AU_MVD_PR(dmsg, "cpdown failed\n"); -+ -+ AuTraceErr(err); -+ return err; -+} -+ -+/* -+ * unlink the whiteout on bdst if exist which may be created by UDBA while we -+ * were sleeping -+ */ -+static int au_do_unlink_wh(const unsigned char dmsg, struct au_mvd_args *a) -+{ -+ int err; -+ struct path h_path; -+ struct au_branch *br; -+ struct inode *delegated; -+ -+ br = au_sbr(a->sb, a->mvd_bdst); -+ h_path.dentry = au_wh_lkup(a->mvd_h_dst_parent, &a->dentry->d_name, br); -+ err = PTR_ERR(h_path.dentry); -+ if (IS_ERR(h_path.dentry)) { -+ AU_MVD_PR(dmsg, "wh_lkup failed\n"); -+ goto out; -+ } -+ -+ err = 0; -+ if (d_is_positive(h_path.dentry)) { -+ h_path.mnt = au_br_mnt(br); -+ delegated = NULL; -+ err = vfsub_unlink(d_inode(a->mvd_h_dst_parent), &h_path, -+ &delegated, /*force*/0); -+ if (unlikely(err == -EWOULDBLOCK)) { -+ pr_warn("cannot retry for NFSv4 delegation" -+ " for an internal unlink\n"); -+ iput(delegated); -+ } -+ if (unlikely(err)) -+ AU_MVD_PR(dmsg, "wh_unlink failed\n"); -+ } -+ dput(h_path.dentry); -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+/* -+ * unlink the topmost h_dentry -+ */ -+static int au_do_unlink(const unsigned char dmsg, struct au_mvd_args *a) -+{ -+ int err; -+ struct path h_path; -+ struct inode *delegated; -+ -+ h_path.mnt = au_sbr_mnt(a->sb, a->mvd_bsrc); -+ h_path.dentry = au_h_dptr(a->dentry, a->mvd_bsrc); -+ delegated = NULL; -+ err = vfsub_unlink(a->mvd_h_src_dir, &h_path, &delegated, /*force*/0); -+ if (unlikely(err == -EWOULDBLOCK)) { -+ pr_warn("cannot retry for NFSv4 delegation" -+ " for an internal unlink\n"); -+ iput(delegated); -+ } -+ if (unlikely(err)) -+ AU_MVD_PR(dmsg, "unlink failed\n"); -+ -+ AuTraceErr(err); -+ return err; -+} -+ -+/* Since mvdown succeeded, we ignore an error of this function */ -+static void au_do_stfs(const unsigned char dmsg, struct au_mvd_args *a) -+{ -+ int err; -+ struct au_branch *br; -+ -+ a->mvdown.flags |= AUFS_MVDOWN_STFS_FAILED; -+ br = au_sbr(a->sb, a->mvd_bsrc); -+ err = au_br_stfs(br, &a->mvdown.stbr[AUFS_MVDOWN_UPPER].stfs); -+ if (!err) { -+ br = au_sbr(a->sb, a->mvd_bdst); -+ a->mvdown.stbr[AUFS_MVDOWN_LOWER].brid = br->br_id; -+ err = au_br_stfs(br, &a->mvdown.stbr[AUFS_MVDOWN_LOWER].stfs); -+ } -+ if (!err) -+ a->mvdown.flags &= ~AUFS_MVDOWN_STFS_FAILED; -+ else -+ AU_MVD_PR(dmsg, "statfs failed (%d), ignored\n", err); -+} -+ -+/* -+ * copy-down the file and unlink the bsrc file. -+ * - unlink the bdst whout if exist -+ * - copy-down the file (with whtmp name and rename) -+ * - unlink the bsrc file -+ */ -+static int au_do_mvdown(const unsigned char dmsg, struct au_mvd_args *a) -+{ -+ int err; -+ -+ err = au_do_mkdir(dmsg, a); -+ if (!err) -+ err = au_do_lock(dmsg, a); -+ if (unlikely(err)) -+ goto out; -+ -+ /* -+ * do not revert the activities we made on bdst since they should be -+ * harmless in aufs. -+ */ -+ -+ err = au_do_cpdown(dmsg, a); -+ if (!err) -+ err = au_do_unlink_wh(dmsg, a); -+ if (!err && !(a->mvdown.flags & AUFS_MVDOWN_KUPPER)) -+ err = au_do_unlink(dmsg, a); -+ if (unlikely(err)) -+ goto out_unlock; -+ -+ AuDbg("%pd2, 0x%x, %d --> %d\n", -+ a->dentry, a->mvdown.flags, a->mvd_bsrc, a->mvd_bdst); -+ if (find_lower_writable(a) < 0) -+ a->mvdown.flags |= AUFS_MVDOWN_BOTTOM; -+ -+ if (a->mvdown.flags & AUFS_MVDOWN_STFS) -+ au_do_stfs(dmsg, a); -+ -+ /* maintain internal array */ -+ if (!(a->mvdown.flags & AUFS_MVDOWN_KUPPER)) { -+ au_set_h_dptr(a->dentry, a->mvd_bsrc, NULL); -+ au_set_dbtop(a->dentry, a->mvd_bdst); -+ au_set_h_iptr(a->inode, a->mvd_bsrc, NULL, /*flags*/0); -+ au_set_ibtop(a->inode, a->mvd_bdst); -+ } else { -+ /* hide the lower */ -+ au_set_h_dptr(a->dentry, a->mvd_bdst, NULL); -+ au_set_dbbot(a->dentry, a->mvd_bsrc); -+ au_set_h_iptr(a->inode, a->mvd_bdst, NULL, /*flags*/0); -+ au_set_ibbot(a->inode, a->mvd_bsrc); -+ } -+ if (au_dbbot(a->dentry) < a->mvd_bdst) -+ au_set_dbbot(a->dentry, a->mvd_bdst); -+ if (au_ibbot(a->inode) < a->mvd_bdst) -+ au_set_ibbot(a->inode, a->mvd_bdst); -+ -+out_unlock: -+ au_do_unlock(dmsg, a); -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* make sure the file is idle */ -+static int au_mvd_args_busy(const unsigned char dmsg, struct au_mvd_args *a) -+{ -+ int err, plinked; -+ -+ err = 0; -+ plinked = !!au_opt_test(au_mntflags(a->sb), PLINK); -+ if (au_dbtop(a->dentry) == a->mvd_bsrc -+ && au_dcount(a->dentry) == 1 -+ && atomic_read(&a->inode->i_count) == 1 -+ /* && a->mvd_h_src_inode->i_nlink == 1 */ -+ && (!plinked || !au_plink_test(a->inode)) -+ && a->inode->i_nlink == 1) -+ goto out; -+ -+ err = -EBUSY; -+ AU_MVD_PR(dmsg, -+ "b%d, d{b%d, c%d?}, i{c%d?, l%u}, hi{l%u}, p{%d, %d}\n", -+ a->mvd_bsrc, au_dbtop(a->dentry), au_dcount(a->dentry), -+ atomic_read(&a->inode->i_count), a->inode->i_nlink, -+ a->mvd_h_src_inode->i_nlink, -+ plinked, plinked ? au_plink_test(a->inode) : 0); -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+/* make sure the parent dir is fine */ -+static int au_mvd_args_parent(const unsigned char dmsg, -+ struct au_mvd_args *a) -+{ -+ int err; -+ aufs_bindex_t bindex; -+ -+ err = 0; -+ if (unlikely(au_alive_dir(a->parent))) { -+ err = -ENOENT; -+ AU_MVD_PR(dmsg, "parent dir is dead\n"); -+ goto out; -+ } -+ -+ a->bopq = au_dbdiropq(a->parent); -+ bindex = au_wbr_nonopq(a->dentry, a->mvd_bdst); -+ AuDbg("b%d\n", bindex); -+ if (unlikely((bindex >= 0 && bindex < a->mvd_bdst) -+ || (a->bopq != -1 && a->bopq < a->mvd_bdst))) { -+ err = -EINVAL; -+ a->mvd_errno = EAU_MVDOWN_OPAQUE; -+ AU_MVD_PR(dmsg, "ancestor is opaque b%d, b%d\n", -+ a->bopq, a->mvd_bdst); -+ } -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+static int au_mvd_args_intermediate(const unsigned char dmsg, -+ struct au_mvd_args *a) -+{ -+ int err; -+ struct au_dinfo *dinfo, *tmp; -+ -+ /* lookup the next lower positive entry */ -+ err = -ENOMEM; -+ tmp = au_di_alloc(a->sb, AuLsc_DI_TMP); -+ if (unlikely(!tmp)) -+ goto out; -+ -+ a->bfound = -1; -+ a->bwh = -1; -+ dinfo = au_di(a->dentry); -+ au_di_cp(tmp, dinfo); -+ au_di_swap(tmp, dinfo); -+ -+ /* returns the number of positive dentries */ -+ err = au_lkup_dentry(a->dentry, a->mvd_bsrc + 1, -+ /* AuLkup_IGNORE_PERM */ 0); -+ if (!err) -+ a->bwh = au_dbwh(a->dentry); -+ else if (err > 0) -+ a->bfound = au_dbtop(a->dentry); -+ -+ au_di_swap(tmp, dinfo); -+ au_rw_write_unlock(&tmp->di_rwsem); -+ au_di_free(tmp); -+ if (unlikely(err < 0)) -+ AU_MVD_PR(dmsg, "failed look-up lower\n"); -+ -+ /* -+ * here, we have these cases. -+ * bfound == -1 -+ * no positive dentry under bsrc. there are more sub-cases. -+ * bwh < 0 -+ * there no whiteout, we can safely move-down. -+ * bwh <= bsrc -+ * impossible -+ * bsrc < bwh && bwh < bdst -+ * there is a whiteout on RO branch. cannot proceed. -+ * bwh == bdst -+ * there is a whiteout on the RW target branch. it should -+ * be removed. -+ * bdst < bwh -+ * there is a whiteout somewhere unrelated branch. -+ * -1 < bfound && bfound <= bsrc -+ * impossible. -+ * bfound < bdst -+ * found, but it is on RO branch between bsrc and bdst. cannot -+ * proceed. -+ * bfound == bdst -+ * found, replace it if AUFS_MVDOWN_FORCE is set. otherwise return -+ * error. -+ * bdst < bfound -+ * found, after we create the file on bdst, it will be hidden. -+ */ -+ -+ AuDebugOn(a->bfound == -1 -+ && a->bwh != -1 -+ && a->bwh <= a->mvd_bsrc); -+ AuDebugOn(-1 < a->bfound -+ && a->bfound <= a->mvd_bsrc); -+ -+ err = -EINVAL; -+ if (a->bfound == -1 -+ && a->mvd_bsrc < a->bwh -+ && a->bwh != -1 -+ && a->bwh < a->mvd_bdst) { -+ a->mvd_errno = EAU_MVDOWN_WHITEOUT; -+ AU_MVD_PR(dmsg, "bsrc %d, bdst %d, bfound %d, bwh %d\n", -+ a->mvd_bsrc, a->mvd_bdst, a->bfound, a->bwh); -+ goto out; -+ } else if (a->bfound != -1 && a->bfound < a->mvd_bdst) { -+ a->mvd_errno = EAU_MVDOWN_UPPER; -+ AU_MVD_PR(dmsg, "bdst %d, bfound %d\n", -+ a->mvd_bdst, a->bfound); -+ goto out; -+ } -+ -+ err = 0; /* success */ -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+static int au_mvd_args_exist(const unsigned char dmsg, struct au_mvd_args *a) -+{ -+ int err; -+ -+ err = 0; -+ if (!(a->mvdown.flags & AUFS_MVDOWN_OWLOWER) -+ && a->bfound == a->mvd_bdst) -+ err = -EEXIST; -+ AuTraceErr(err); -+ return err; -+} -+ -+static int au_mvd_args(const unsigned char dmsg, struct au_mvd_args *a) -+{ -+ int err; -+ struct au_branch *br; -+ -+ err = -EISDIR; -+ if (unlikely(S_ISDIR(a->inode->i_mode))) -+ goto out; -+ -+ err = -EINVAL; -+ if (!(a->mvdown.flags & AUFS_MVDOWN_BRID_UPPER)) -+ a->mvd_bsrc = au_ibtop(a->inode); -+ else { -+ a->mvd_bsrc = au_br_index(a->sb, a->mvd_src_brid); -+ if (unlikely(a->mvd_bsrc < 0 -+ || (a->mvd_bsrc < au_dbtop(a->dentry) -+ || au_dbbot(a->dentry) < a->mvd_bsrc -+ || !au_h_dptr(a->dentry, a->mvd_bsrc)) -+ || (a->mvd_bsrc < au_ibtop(a->inode) -+ || au_ibbot(a->inode) < a->mvd_bsrc -+ || !au_h_iptr(a->inode, a->mvd_bsrc)))) { -+ a->mvd_errno = EAU_MVDOWN_NOUPPER; -+ AU_MVD_PR(dmsg, "no upper\n"); -+ goto out; -+ } -+ } -+ if (unlikely(a->mvd_bsrc == au_sbbot(a->sb))) { -+ a->mvd_errno = EAU_MVDOWN_BOTTOM; -+ AU_MVD_PR(dmsg, "on the bottom\n"); -+ goto out; -+ } -+ a->mvd_h_src_inode = au_h_iptr(a->inode, a->mvd_bsrc); -+ br = au_sbr(a->sb, a->mvd_bsrc); -+ err = au_br_rdonly(br); -+ if (!(a->mvdown.flags & AUFS_MVDOWN_ROUPPER)) { -+ if (unlikely(err)) -+ goto out; -+ } else if (!(vfsub_native_ro(a->mvd_h_src_inode) -+ || IS_APPEND(a->mvd_h_src_inode))) { -+ if (err) -+ a->mvdown.flags |= AUFS_MVDOWN_ROUPPER_R; -+ /* go on */ -+ } else -+ goto out; -+ -+ err = -EINVAL; -+ if (!(a->mvdown.flags & AUFS_MVDOWN_BRID_LOWER)) { -+ a->mvd_bdst = find_lower_writable(a); -+ if (unlikely(a->mvd_bdst < 0)) { -+ a->mvd_errno = EAU_MVDOWN_BOTTOM; -+ AU_MVD_PR(dmsg, "no writable lower branch\n"); -+ goto out; -+ } -+ } else { -+ a->mvd_bdst = au_br_index(a->sb, a->mvd_dst_brid); -+ if (unlikely(a->mvd_bdst < 0 -+ || au_sbbot(a->sb) < a->mvd_bdst)) { -+ a->mvd_errno = EAU_MVDOWN_NOLOWERBR; -+ AU_MVD_PR(dmsg, "no lower brid\n"); -+ goto out; -+ } -+ } -+ -+ err = au_mvd_args_busy(dmsg, a); -+ if (!err) -+ err = au_mvd_args_parent(dmsg, a); -+ if (!err) -+ err = au_mvd_args_intermediate(dmsg, a); -+ if (!err) -+ err = au_mvd_args_exist(dmsg, a); -+ if (!err) -+ AuDbg("b%d, b%d\n", a->mvd_bsrc, a->mvd_bdst); -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+int au_mvdown(struct dentry *dentry, struct aufs_mvdown __user *uarg) -+{ -+ int err, e; -+ unsigned char dmsg; -+ struct au_mvd_args *args; -+ struct inode *inode; -+ -+ inode = d_inode(dentry); -+ err = -EPERM; -+ if (unlikely(!capable(CAP_SYS_ADMIN))) -+ goto out; -+ -+ err = -ENOMEM; -+ args = kmalloc(sizeof(*args), GFP_NOFS); -+ if (unlikely(!args)) -+ goto out; -+ -+ err = copy_from_user(&args->mvdown, uarg, sizeof(args->mvdown)); -+ if (!err) -+ /* VERIFY_WRITE */ -+ err = !access_ok(uarg, sizeof(*uarg)); -+ if (unlikely(err)) { -+ err = -EFAULT; -+ AuTraceErr(err); -+ goto out_free; -+ } -+ AuDbg("flags 0x%x\n", args->mvdown.flags); -+ args->mvdown.flags &= ~(AUFS_MVDOWN_ROLOWER_R | AUFS_MVDOWN_ROUPPER_R); -+ args->mvdown.au_errno = 0; -+ args->dentry = dentry; -+ args->inode = inode; -+ args->sb = dentry->d_sb; -+ -+ err = -ENOENT; -+ dmsg = !!(args->mvdown.flags & AUFS_MVDOWN_DMSG); -+ args->parent = dget_parent(dentry); -+ args->dir = d_inode(args->parent); -+ inode_lock_nested(args->dir, I_MUTEX_PARENT); -+ dput(args->parent); -+ if (unlikely(args->parent != dentry->d_parent)) { -+ AU_MVD_PR(dmsg, "parent dir is moved\n"); -+ goto out_dir; -+ } -+ -+ inode_lock_nested(inode, I_MUTEX_CHILD); -+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH | AuLock_NOPLMW); -+ if (unlikely(err)) -+ goto out_inode; -+ -+ di_write_lock_parent(args->parent); -+ err = au_mvd_args(dmsg, args); -+ if (unlikely(err)) -+ goto out_parent; -+ -+ err = au_do_mvdown(dmsg, args); -+ if (unlikely(err)) -+ goto out_parent; -+ -+ au_cpup_attr_timesizes(args->dir); -+ au_cpup_attr_timesizes(inode); -+ if (!(args->mvdown.flags & AUFS_MVDOWN_KUPPER)) -+ au_cpup_igen(inode, au_h_iptr(inode, args->mvd_bdst)); -+ /* au_digen_dec(dentry); */ -+ -+out_parent: -+ di_write_unlock(args->parent); -+ aufs_read_unlock(dentry, AuLock_DW); -+out_inode: -+ inode_unlock(inode); -+out_dir: -+ inode_unlock(args->dir); -+out_free: -+ e = copy_to_user(uarg, &args->mvdown, sizeof(args->mvdown)); -+ if (unlikely(e)) -+ err = -EFAULT; -+ au_kfree_rcu(args); -+out: -+ AuTraceErr(err); -+ return err; -+} -diff -Nurp linux-5.10-rc6/fs/aufs/opts.c linux-5.10-rc6.aufs/fs/aufs/opts.c ---- linux-5.10-rc6/fs/aufs/opts.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/opts.c 2020-12-02 21:19:51.883036833 +0200 -@@ -0,0 +1,1867 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * mount options/flags -+ */ -+ -+#include -+#include /* a distribution requires */ -+#include -+#include "aufs.h" -+ -+/* ---------------------------------------------------------------------- */ -+ -+enum { -+ Opt_br, -+ Opt_add, Opt_del, Opt_mod, Opt_append, Opt_prepend, -+ Opt_idel, Opt_imod, -+ Opt_dirwh, Opt_rdcache, Opt_rdblk, Opt_rdhash, -+ Opt_rdblk_def, Opt_rdhash_def, -+ Opt_xino, Opt_noxino, -+ Opt_trunc_xino, Opt_trunc_xino_v, Opt_notrunc_xino, -+ Opt_trunc_xino_path, Opt_itrunc_xino, -+ Opt_trunc_xib, Opt_notrunc_xib, -+ Opt_shwh, Opt_noshwh, -+ Opt_plink, Opt_noplink, Opt_list_plink, -+ Opt_udba, -+ Opt_dio, Opt_nodio, -+ Opt_diropq_a, Opt_diropq_w, -+ Opt_warn_perm, Opt_nowarn_perm, -+ Opt_wbr_copyup, Opt_wbr_create, -+ Opt_fhsm_sec, -+ Opt_verbose, Opt_noverbose, -+ Opt_sum, Opt_nosum, Opt_wsum, -+ Opt_dirperm1, Opt_nodirperm1, -+ Opt_dirren, Opt_nodirren, -+ Opt_acl, Opt_noacl, -+ Opt_tail, Opt_ignore, Opt_ignore_silent, Opt_err -+}; -+ -+static match_table_t options = { -+ {Opt_br, "br=%s"}, -+ {Opt_br, "br:%s"}, -+ -+ {Opt_add, "add=%d:%s"}, -+ {Opt_add, "add:%d:%s"}, -+ {Opt_add, "ins=%d:%s"}, -+ {Opt_add, "ins:%d:%s"}, -+ {Opt_append, "append=%s"}, -+ {Opt_append, "append:%s"}, -+ {Opt_prepend, "prepend=%s"}, -+ {Opt_prepend, "prepend:%s"}, -+ -+ {Opt_del, "del=%s"}, -+ {Opt_del, "del:%s"}, -+ /* {Opt_idel, "idel:%d"}, */ -+ {Opt_mod, "mod=%s"}, -+ {Opt_mod, "mod:%s"}, -+ /* {Opt_imod, "imod:%d:%s"}, */ -+ -+ {Opt_dirwh, "dirwh=%d"}, -+ -+ {Opt_xino, "xino=%s"}, -+ {Opt_noxino, "noxino"}, -+ {Opt_trunc_xino, "trunc_xino"}, -+ {Opt_trunc_xino_v, "trunc_xino_v=%d:%d"}, -+ {Opt_notrunc_xino, "notrunc_xino"}, -+ {Opt_trunc_xino_path, "trunc_xino=%s"}, -+ {Opt_itrunc_xino, "itrunc_xino=%d"}, -+ /* {Opt_zxino, "zxino=%s"}, */ -+ {Opt_trunc_xib, "trunc_xib"}, -+ {Opt_notrunc_xib, "notrunc_xib"}, -+ -+#ifdef CONFIG_PROC_FS -+ {Opt_plink, "plink"}, -+#else -+ {Opt_ignore_silent, "plink"}, -+#endif -+ -+ {Opt_noplink, "noplink"}, -+ -+#ifdef CONFIG_AUFS_DEBUG -+ {Opt_list_plink, "list_plink"}, -+#endif -+ -+ {Opt_udba, "udba=%s"}, -+ -+ {Opt_dio, "dio"}, -+ {Opt_nodio, "nodio"}, -+ -+#ifdef CONFIG_AUFS_DIRREN -+ {Opt_dirren, "dirren"}, -+ {Opt_nodirren, "nodirren"}, -+#else -+ {Opt_ignore, "dirren"}, -+ {Opt_ignore_silent, "nodirren"}, -+#endif -+ -+#ifdef CONFIG_AUFS_FHSM -+ {Opt_fhsm_sec, "fhsm_sec=%d"}, -+#else -+ {Opt_ignore, "fhsm_sec=%d"}, -+#endif -+ -+ {Opt_diropq_a, "diropq=always"}, -+ {Opt_diropq_a, "diropq=a"}, -+ {Opt_diropq_w, "diropq=whiteouted"}, -+ {Opt_diropq_w, "diropq=w"}, -+ -+ {Opt_warn_perm, "warn_perm"}, -+ {Opt_nowarn_perm, "nowarn_perm"}, -+ -+ /* keep them temporary */ -+ {Opt_ignore_silent, "nodlgt"}, -+ {Opt_ignore, "clean_plink"}, -+ -+#ifdef CONFIG_AUFS_SHWH -+ {Opt_shwh, "shwh"}, -+#endif -+ {Opt_noshwh, "noshwh"}, -+ -+ {Opt_dirperm1, "dirperm1"}, -+ {Opt_nodirperm1, "nodirperm1"}, -+ -+ {Opt_verbose, "verbose"}, -+ {Opt_verbose, "v"}, -+ {Opt_noverbose, "noverbose"}, -+ {Opt_noverbose, "quiet"}, -+ {Opt_noverbose, "q"}, -+ {Opt_noverbose, "silent"}, -+ -+ {Opt_sum, "sum"}, -+ {Opt_nosum, "nosum"}, -+ {Opt_wsum, "wsum"}, -+ -+ {Opt_rdcache, "rdcache=%d"}, -+ {Opt_rdblk, "rdblk=%d"}, -+ {Opt_rdblk_def, "rdblk=def"}, -+ {Opt_rdhash, "rdhash=%d"}, -+ {Opt_rdhash_def, "rdhash=def"}, -+ -+ {Opt_wbr_create, "create=%s"}, -+ {Opt_wbr_create, "create_policy=%s"}, -+ {Opt_wbr_copyup, "cpup=%s"}, -+ {Opt_wbr_copyup, "copyup=%s"}, -+ {Opt_wbr_copyup, "copyup_policy=%s"}, -+ -+ /* generic VFS flag */ -+#ifdef CONFIG_FS_POSIX_ACL -+ {Opt_acl, "acl"}, -+ {Opt_noacl, "noacl"}, -+#else -+ {Opt_ignore, "acl"}, -+ {Opt_ignore_silent, "noacl"}, -+#endif -+ -+ /* internal use for the scripts */ -+ {Opt_ignore_silent, "si=%s"}, -+ -+ {Opt_br, "dirs=%s"}, -+ {Opt_ignore, "debug=%d"}, -+ {Opt_ignore, "delete=whiteout"}, -+ {Opt_ignore, "delete=all"}, -+ {Opt_ignore, "imap=%s"}, -+ -+ /* temporary workaround, due to old mount(8)? */ -+ {Opt_ignore_silent, "relatime"}, -+ -+ {Opt_err, NULL} -+}; -+ -+/* ---------------------------------------------------------------------- */ -+ -+static const char *au_parser_pattern(int val, match_table_t tbl) -+{ -+ struct match_token *p; -+ -+ p = tbl; -+ while (p->pattern) { -+ if (p->token == val) -+ return p->pattern; -+ p++; -+ } -+ BUG(); -+ return "??"; -+} -+ -+static const char *au_optstr(int *val, match_table_t tbl) -+{ -+ struct match_token *p; -+ int v; -+ -+ v = *val; -+ if (!v) -+ goto out; -+ p = tbl; -+ while (p->pattern) { -+ if (p->token -+ && (v & p->token) == p->token) { -+ *val &= ~p->token; -+ return p->pattern; -+ } -+ p++; -+ } -+ -+out: -+ return NULL; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static match_table_t brperm = { -+ {AuBrPerm_RO, AUFS_BRPERM_RO}, -+ {AuBrPerm_RR, AUFS_BRPERM_RR}, -+ {AuBrPerm_RW, AUFS_BRPERM_RW}, -+ {0, NULL} -+}; -+ -+static match_table_t brattr = { -+ /* general */ -+ {AuBrAttr_COO_REG, AUFS_BRATTR_COO_REG}, -+ {AuBrAttr_COO_ALL, AUFS_BRATTR_COO_ALL}, -+ /* 'unpin' attrib is meaningless since linux-3.18-rc1 */ -+ {AuBrAttr_UNPIN, AUFS_BRATTR_UNPIN}, -+#ifdef CONFIG_AUFS_FHSM -+ {AuBrAttr_FHSM, AUFS_BRATTR_FHSM}, -+#endif -+#ifdef CONFIG_AUFS_XATTR -+ {AuBrAttr_ICEX, AUFS_BRATTR_ICEX}, -+ {AuBrAttr_ICEX_SEC, AUFS_BRATTR_ICEX_SEC}, -+ {AuBrAttr_ICEX_SYS, AUFS_BRATTR_ICEX_SYS}, -+ {AuBrAttr_ICEX_TR, AUFS_BRATTR_ICEX_TR}, -+ {AuBrAttr_ICEX_USR, AUFS_BRATTR_ICEX_USR}, -+ {AuBrAttr_ICEX_OTH, AUFS_BRATTR_ICEX_OTH}, -+#endif -+ -+ /* ro/rr branch */ -+ {AuBrRAttr_WH, AUFS_BRRATTR_WH}, -+ -+ /* rw branch */ -+ {AuBrWAttr_MOO, AUFS_BRWATTR_MOO}, -+ {AuBrWAttr_NoLinkWH, AUFS_BRWATTR_NLWH}, -+ -+ {0, NULL} -+}; -+ -+static int br_attr_val(char *str, match_table_t table, substring_t args[]) -+{ -+ int attr, v; -+ char *p; -+ -+ attr = 0; -+ do { -+ p = strchr(str, '+'); -+ if (p) -+ *p = 0; -+ v = match_token(str, table, args); -+ if (v) { -+ if (v & AuBrAttr_CMOO_Mask) -+ attr &= ~AuBrAttr_CMOO_Mask; -+ attr |= v; -+ } else { -+ if (p) -+ *p = '+'; -+ pr_warn("ignored branch attribute %s\n", str); -+ break; -+ } -+ if (p) -+ str = p + 1; -+ } while (p); -+ -+ return attr; -+} -+ -+static int au_do_optstr_br_attr(au_br_perm_str_t *str, int perm) -+{ -+ int sz; -+ const char *p; -+ char *q; -+ -+ q = str->a; -+ *q = 0; -+ p = au_optstr(&perm, brattr); -+ if (p) { -+ sz = strlen(p); -+ memcpy(q, p, sz + 1); -+ q += sz; -+ } else -+ goto out; -+ -+ do { -+ p = au_optstr(&perm, brattr); -+ if (p) { -+ *q++ = '+'; -+ sz = strlen(p); -+ memcpy(q, p, sz + 1); -+ q += sz; -+ } -+ } while (p); -+ -+out: -+ return q - str->a; -+} -+ -+static int noinline_for_stack br_perm_val(char *perm) -+{ -+ int val, bad, sz; -+ char *p; -+ substring_t args[MAX_OPT_ARGS]; -+ au_br_perm_str_t attr; -+ -+ p = strchr(perm, '+'); -+ if (p) -+ *p = 0; -+ val = match_token(perm, brperm, args); -+ if (!val) { -+ if (p) -+ *p = '+'; -+ pr_warn("ignored branch permission %s\n", perm); -+ val = AuBrPerm_RO; -+ goto out; -+ } -+ if (!p) -+ goto out; -+ -+ val |= br_attr_val(p + 1, brattr, args); -+ -+ bad = 0; -+ switch (val & AuBrPerm_Mask) { -+ case AuBrPerm_RO: -+ case AuBrPerm_RR: -+ bad = val & AuBrWAttr_Mask; -+ val &= ~AuBrWAttr_Mask; -+ break; -+ case AuBrPerm_RW: -+ bad = val & AuBrRAttr_Mask; -+ val &= ~AuBrRAttr_Mask; -+ break; -+ } -+ -+ /* -+ * 'unpin' attrib becomes meaningless since linux-3.18-rc1, but aufs -+ * does not treat it as an error, just warning. -+ * this is a tiny guard for the user operation. -+ */ -+ if (val & AuBrAttr_UNPIN) { -+ bad |= AuBrAttr_UNPIN; -+ val &= ~AuBrAttr_UNPIN; -+ } -+ -+ if (unlikely(bad)) { -+ sz = au_do_optstr_br_attr(&attr, bad); -+ AuDebugOn(!sz); -+ pr_warn("ignored branch attribute %s\n", attr.a); -+ } -+ -+out: -+ return val; -+} -+ -+void au_optstr_br_perm(au_br_perm_str_t *str, int perm) -+{ -+ au_br_perm_str_t attr; -+ const char *p; -+ char *q; -+ int sz; -+ -+ q = str->a; -+ p = au_optstr(&perm, brperm); -+ AuDebugOn(!p || !*p); -+ sz = strlen(p); -+ memcpy(q, p, sz + 1); -+ q += sz; -+ -+ sz = au_do_optstr_br_attr(&attr, perm); -+ if (sz) { -+ *q++ = '+'; -+ memcpy(q, attr.a, sz + 1); -+ } -+ -+ AuDebugOn(strlen(str->a) >= sizeof(str->a)); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static match_table_t udbalevel = { -+ {AuOpt_UDBA_REVAL, "reval"}, -+ {AuOpt_UDBA_NONE, "none"}, -+#ifdef CONFIG_AUFS_HNOTIFY -+ {AuOpt_UDBA_HNOTIFY, "notify"}, /* abstraction */ -+#ifdef CONFIG_AUFS_HFSNOTIFY -+ {AuOpt_UDBA_HNOTIFY, "fsnotify"}, -+#endif -+#endif -+ {-1, NULL} -+}; -+ -+static int noinline_for_stack udba_val(char *str) -+{ -+ substring_t args[MAX_OPT_ARGS]; -+ -+ return match_token(str, udbalevel, args); -+} -+ -+const char *au_optstr_udba(int udba) -+{ -+ return au_parser_pattern(udba, udbalevel); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static match_table_t au_wbr_create_policy = { -+ {AuWbrCreate_TDP, "tdp"}, -+ {AuWbrCreate_TDP, "top-down-parent"}, -+ {AuWbrCreate_RR, "rr"}, -+ {AuWbrCreate_RR, "round-robin"}, -+ {AuWbrCreate_MFS, "mfs"}, -+ {AuWbrCreate_MFS, "most-free-space"}, -+ {AuWbrCreate_MFSV, "mfs:%d"}, -+ {AuWbrCreate_MFSV, "most-free-space:%d"}, -+ -+ /* top-down regardless the parent, and then mfs */ -+ {AuWbrCreate_TDMFS, "tdmfs:%d"}, -+ {AuWbrCreate_TDMFSV, "tdmfs:%d:%d"}, -+ -+ {AuWbrCreate_MFSRR, "mfsrr:%d"}, -+ {AuWbrCreate_MFSRRV, "mfsrr:%d:%d"}, -+ {AuWbrCreate_PMFS, "pmfs"}, -+ {AuWbrCreate_PMFSV, "pmfs:%d"}, -+ {AuWbrCreate_PMFSRR, "pmfsrr:%d"}, -+ {AuWbrCreate_PMFSRRV, "pmfsrr:%d:%d"}, -+ -+ {-1, NULL} -+}; -+ -+static int au_wbr_mfs_wmark(substring_t *arg, char *str, -+ struct au_opt_wbr_create *create) -+{ -+ int err; -+ unsigned long long ull; -+ -+ err = 0; -+ if (!match_u64(arg, &ull)) -+ create->mfsrr_watermark = ull; -+ else { -+ pr_err("bad integer in %s\n", str); -+ err = -EINVAL; -+ } -+ -+ return err; -+} -+ -+static int au_wbr_mfs_sec(substring_t *arg, char *str, -+ struct au_opt_wbr_create *create) -+{ -+ int n, err; -+ -+ err = 0; -+ if (!match_int(arg, &n) && 0 <= n && n <= AUFS_MFS_MAX_SEC) -+ create->mfs_second = n; -+ else { -+ pr_err("bad integer in %s\n", str); -+ err = -EINVAL; -+ } -+ -+ return err; -+} -+ -+static int noinline_for_stack -+au_wbr_create_val(char *str, struct au_opt_wbr_create *create) -+{ -+ int err, e; -+ substring_t args[MAX_OPT_ARGS]; -+ -+ err = match_token(str, au_wbr_create_policy, args); -+ create->wbr_create = err; -+ switch (err) { -+ case AuWbrCreate_MFSRRV: -+ case AuWbrCreate_TDMFSV: -+ case AuWbrCreate_PMFSRRV: -+ e = au_wbr_mfs_wmark(&args[0], str, create); -+ if (!e) -+ e = au_wbr_mfs_sec(&args[1], str, create); -+ if (unlikely(e)) -+ err = e; -+ break; -+ case AuWbrCreate_MFSRR: -+ case AuWbrCreate_TDMFS: -+ case AuWbrCreate_PMFSRR: -+ e = au_wbr_mfs_wmark(&args[0], str, create); -+ if (unlikely(e)) { -+ err = e; -+ break; -+ } -+ /*FALLTHROUGH*/ -+ case AuWbrCreate_MFS: -+ case AuWbrCreate_PMFS: -+ create->mfs_second = AUFS_MFS_DEF_SEC; -+ break; -+ case AuWbrCreate_MFSV: -+ case AuWbrCreate_PMFSV: -+ e = au_wbr_mfs_sec(&args[0], str, create); -+ if (unlikely(e)) -+ err = e; -+ break; -+ } -+ -+ return err; -+} -+ -+const char *au_optstr_wbr_create(int wbr_create) -+{ -+ return au_parser_pattern(wbr_create, au_wbr_create_policy); -+} -+ -+static match_table_t au_wbr_copyup_policy = { -+ {AuWbrCopyup_TDP, "tdp"}, -+ {AuWbrCopyup_TDP, "top-down-parent"}, -+ {AuWbrCopyup_BUP, "bup"}, -+ {AuWbrCopyup_BUP, "bottom-up-parent"}, -+ {AuWbrCopyup_BU, "bu"}, -+ {AuWbrCopyup_BU, "bottom-up"}, -+ {-1, NULL} -+}; -+ -+static int noinline_for_stack au_wbr_copyup_val(char *str) -+{ -+ substring_t args[MAX_OPT_ARGS]; -+ -+ return match_token(str, au_wbr_copyup_policy, args); -+} -+ -+const char *au_optstr_wbr_copyup(int wbr_copyup) -+{ -+ return au_parser_pattern(wbr_copyup, au_wbr_copyup_policy); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static const int lkup_dirflags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY; -+ -+static void dump_opts(struct au_opts *opts) -+{ -+#ifdef CONFIG_AUFS_DEBUG -+ /* reduce stack space */ -+ union { -+ struct au_opt_add *add; -+ struct au_opt_del *del; -+ struct au_opt_mod *mod; -+ struct au_opt_xino *xino; -+ struct au_opt_xino_itrunc *xino_itrunc; -+ struct au_opt_wbr_create *create; -+ } u; -+ struct au_opt *opt; -+ -+ opt = opts->opt; -+ while (opt->type != Opt_tail) { -+ switch (opt->type) { -+ case Opt_add: -+ u.add = &opt->add; -+ AuDbg("add {b%d, %s, 0x%x, %p}\n", -+ u.add->bindex, u.add->pathname, u.add->perm, -+ u.add->path.dentry); -+ break; -+ case Opt_del: -+ case Opt_idel: -+ u.del = &opt->del; -+ AuDbg("del {%s, %p}\n", -+ u.del->pathname, u.del->h_path.dentry); -+ break; -+ case Opt_mod: -+ case Opt_imod: -+ u.mod = &opt->mod; -+ AuDbg("mod {%s, 0x%x, %p}\n", -+ u.mod->path, u.mod->perm, u.mod->h_root); -+ break; -+ case Opt_append: -+ u.add = &opt->add; -+ AuDbg("append {b%d, %s, 0x%x, %p}\n", -+ u.add->bindex, u.add->pathname, u.add->perm, -+ u.add->path.dentry); -+ break; -+ case Opt_prepend: -+ u.add = &opt->add; -+ AuDbg("prepend {b%d, %s, 0x%x, %p}\n", -+ u.add->bindex, u.add->pathname, u.add->perm, -+ u.add->path.dentry); -+ break; -+ case Opt_dirwh: -+ AuDbg("dirwh %d\n", opt->dirwh); -+ break; -+ case Opt_rdcache: -+ AuDbg("rdcache %d\n", opt->rdcache); -+ break; -+ case Opt_rdblk: -+ AuDbg("rdblk %u\n", opt->rdblk); -+ break; -+ case Opt_rdblk_def: -+ AuDbg("rdblk_def\n"); -+ break; -+ case Opt_rdhash: -+ AuDbg("rdhash %u\n", opt->rdhash); -+ break; -+ case Opt_rdhash_def: -+ AuDbg("rdhash_def\n"); -+ break; -+ case Opt_xino: -+ u.xino = &opt->xino; -+ AuDbg("xino {%s %pD}\n", u.xino->path, u.xino->file); -+ break; -+ case Opt_trunc_xino: -+ AuLabel(trunc_xino); -+ break; -+ case Opt_notrunc_xino: -+ AuLabel(notrunc_xino); -+ break; -+ case Opt_trunc_xino_path: -+ case Opt_itrunc_xino: -+ u.xino_itrunc = &opt->xino_itrunc; -+ AuDbg("trunc_xino %d\n", u.xino_itrunc->bindex); -+ break; -+ case Opt_noxino: -+ AuLabel(noxino); -+ break; -+ case Opt_trunc_xib: -+ AuLabel(trunc_xib); -+ break; -+ case Opt_notrunc_xib: -+ AuLabel(notrunc_xib); -+ break; -+ case Opt_shwh: -+ AuLabel(shwh); -+ break; -+ case Opt_noshwh: -+ AuLabel(noshwh); -+ break; -+ case Opt_dirperm1: -+ AuLabel(dirperm1); -+ break; -+ case Opt_nodirperm1: -+ AuLabel(nodirperm1); -+ break; -+ case Opt_plink: -+ AuLabel(plink); -+ break; -+ case Opt_noplink: -+ AuLabel(noplink); -+ break; -+ case Opt_list_plink: -+ AuLabel(list_plink); -+ break; -+ case Opt_udba: -+ AuDbg("udba %d, %s\n", -+ opt->udba, au_optstr_udba(opt->udba)); -+ break; -+ case Opt_dio: -+ AuLabel(dio); -+ break; -+ case Opt_nodio: -+ AuLabel(nodio); -+ break; -+ case Opt_diropq_a: -+ AuLabel(diropq_a); -+ break; -+ case Opt_diropq_w: -+ AuLabel(diropq_w); -+ break; -+ case Opt_warn_perm: -+ AuLabel(warn_perm); -+ break; -+ case Opt_nowarn_perm: -+ AuLabel(nowarn_perm); -+ break; -+ case Opt_verbose: -+ AuLabel(verbose); -+ break; -+ case Opt_noverbose: -+ AuLabel(noverbose); -+ break; -+ case Opt_sum: -+ AuLabel(sum); -+ break; -+ case Opt_nosum: -+ AuLabel(nosum); -+ break; -+ case Opt_wsum: -+ AuLabel(wsum); -+ break; -+ case Opt_wbr_create: -+ u.create = &opt->wbr_create; -+ AuDbg("create %d, %s\n", u.create->wbr_create, -+ au_optstr_wbr_create(u.create->wbr_create)); -+ switch (u.create->wbr_create) { -+ case AuWbrCreate_MFSV: -+ case AuWbrCreate_PMFSV: -+ AuDbg("%d sec\n", u.create->mfs_second); -+ break; -+ case AuWbrCreate_MFSRR: -+ case AuWbrCreate_TDMFS: -+ AuDbg("%llu watermark\n", -+ u.create->mfsrr_watermark); -+ break; -+ case AuWbrCreate_MFSRRV: -+ case AuWbrCreate_TDMFSV: -+ case AuWbrCreate_PMFSRRV: -+ AuDbg("%llu watermark, %d sec\n", -+ u.create->mfsrr_watermark, -+ u.create->mfs_second); -+ break; -+ } -+ break; -+ case Opt_wbr_copyup: -+ AuDbg("copyup %d, %s\n", opt->wbr_copyup, -+ au_optstr_wbr_copyup(opt->wbr_copyup)); -+ break; -+ case Opt_fhsm_sec: -+ AuDbg("fhsm_sec %u\n", opt->fhsm_second); -+ break; -+ case Opt_dirren: -+ AuLabel(dirren); -+ break; -+ case Opt_nodirren: -+ AuLabel(nodirren); -+ break; -+ case Opt_acl: -+ AuLabel(acl); -+ break; -+ case Opt_noacl: -+ AuLabel(noacl); -+ break; -+ default: -+ BUG(); -+ } -+ opt++; -+ } -+#endif -+} -+ -+void au_opts_free(struct au_opts *opts) -+{ -+ struct au_opt *opt; -+ -+ opt = opts->opt; -+ while (opt->type != Opt_tail) { -+ switch (opt->type) { -+ case Opt_add: -+ case Opt_append: -+ case Opt_prepend: -+ path_put(&opt->add.path); -+ break; -+ case Opt_del: -+ case Opt_idel: -+ path_put(&opt->del.h_path); -+ break; -+ case Opt_mod: -+ case Opt_imod: -+ dput(opt->mod.h_root); -+ break; -+ case Opt_xino: -+ fput(opt->xino.file); -+ break; -+ } -+ opt++; -+ } -+} -+ -+static int opt_add(struct au_opt *opt, char *opt_str, unsigned long sb_flags, -+ aufs_bindex_t bindex) -+{ -+ int err; -+ struct au_opt_add *add = &opt->add; -+ char *p; -+ -+ add->bindex = bindex; -+ add->perm = AuBrPerm_RO; -+ add->pathname = opt_str; -+ p = strchr(opt_str, '='); -+ if (p) { -+ *p++ = 0; -+ if (*p) -+ add->perm = br_perm_val(p); -+ } -+ -+ err = vfsub_kern_path(add->pathname, lkup_dirflags, &add->path); -+ if (!err) { -+ if (!p) { -+ add->perm = AuBrPerm_RO; -+ if (au_test_fs_rr(add->path.dentry->d_sb)) -+ add->perm = AuBrPerm_RR; -+ else if (!bindex && !(sb_flags & SB_RDONLY)) -+ add->perm = AuBrPerm_RW; -+ } -+ opt->type = Opt_add; -+ goto out; -+ } -+ pr_err("lookup failed %s (%d)\n", add->pathname, err); -+ err = -EINVAL; -+ -+out: -+ return err; -+} -+ -+static int au_opts_parse_del(struct au_opt_del *del, substring_t args[]) -+{ -+ int err; -+ -+ del->pathname = args[0].from; -+ AuDbg("del path %s\n", del->pathname); -+ -+ err = vfsub_kern_path(del->pathname, lkup_dirflags, &del->h_path); -+ if (unlikely(err)) -+ pr_err("lookup failed %s (%d)\n", del->pathname, err); -+ -+ return err; -+} -+ -+#if 0 /* reserved for future use */ -+static int au_opts_parse_idel(struct super_block *sb, aufs_bindex_t bindex, -+ struct au_opt_del *del, substring_t args[]) -+{ -+ int err; -+ struct dentry *root; -+ -+ err = -EINVAL; -+ root = sb->s_root; -+ aufs_read_lock(root, AuLock_FLUSH); -+ if (bindex < 0 || au_sbbot(sb) < bindex) { -+ pr_err("out of bounds, %d\n", bindex); -+ goto out; -+ } -+ -+ err = 0; -+ del->h_path.dentry = dget(au_h_dptr(root, bindex)); -+ del->h_path.mnt = mntget(au_sbr_mnt(sb, bindex)); -+ -+out: -+ aufs_read_unlock(root, !AuLock_IR); -+ return err; -+} -+#endif -+ -+static int noinline_for_stack -+au_opts_parse_mod(struct au_opt_mod *mod, substring_t args[]) -+{ -+ int err; -+ struct path path; -+ char *p; -+ -+ err = -EINVAL; -+ mod->path = args[0].from; -+ p = strchr(mod->path, '='); -+ if (unlikely(!p)) { -+ pr_err("no permission %s\n", args[0].from); -+ goto out; -+ } -+ -+ *p++ = 0; -+ err = vfsub_kern_path(mod->path, lkup_dirflags, &path); -+ if (unlikely(err)) { -+ pr_err("lookup failed %s (%d)\n", mod->path, err); -+ goto out; -+ } -+ -+ mod->perm = br_perm_val(p); -+ AuDbg("mod path %s, perm 0x%x, %s\n", mod->path, mod->perm, p); -+ mod->h_root = dget(path.dentry); -+ path_put(&path); -+ -+out: -+ return err; -+} -+ -+#if 0 /* reserved for future use */ -+static int au_opts_parse_imod(struct super_block *sb, aufs_bindex_t bindex, -+ struct au_opt_mod *mod, substring_t args[]) -+{ -+ int err; -+ struct dentry *root; -+ -+ err = -EINVAL; -+ root = sb->s_root; -+ aufs_read_lock(root, AuLock_FLUSH); -+ if (bindex < 0 || au_sbbot(sb) < bindex) { -+ pr_err("out of bounds, %d\n", bindex); -+ goto out; -+ } -+ -+ err = 0; -+ mod->perm = br_perm_val(args[1].from); -+ AuDbg("mod path %s, perm 0x%x, %s\n", -+ mod->path, mod->perm, args[1].from); -+ mod->h_root = dget(au_h_dptr(root, bindex)); -+ -+out: -+ aufs_read_unlock(root, !AuLock_IR); -+ return err; -+} -+#endif -+ -+static int au_opts_parse_xino(struct super_block *sb, struct au_opt_xino *xino, -+ substring_t args[]) -+{ -+ int err; -+ struct file *file; -+ -+ file = au_xino_create(sb, args[0].from, /*silent*/0, /*wbrtop*/0); -+ err = PTR_ERR(file); -+ if (IS_ERR(file)) -+ goto out; -+ -+ err = -EINVAL; -+ if (unlikely(file->f_path.dentry->d_sb == sb)) { -+ fput(file); -+ pr_err("%s must be outside\n", args[0].from); -+ goto out; -+ } -+ -+ err = 0; -+ xino->file = file; -+ xino->path = args[0].from; -+ -+out: -+ return err; -+} -+ -+static int noinline_for_stack -+au_opts_parse_xino_itrunc_path(struct super_block *sb, -+ struct au_opt_xino_itrunc *xino_itrunc, -+ substring_t args[]) -+{ -+ int err; -+ aufs_bindex_t bbot, bindex; -+ struct path path; -+ struct dentry *root; -+ -+ err = vfsub_kern_path(args[0].from, lkup_dirflags, &path); -+ if (unlikely(err)) { -+ pr_err("lookup failed %s (%d)\n", args[0].from, err); -+ goto out; -+ } -+ -+ xino_itrunc->bindex = -1; -+ root = sb->s_root; -+ aufs_read_lock(root, AuLock_FLUSH); -+ bbot = au_sbbot(sb); -+ for (bindex = 0; bindex <= bbot; bindex++) { -+ if (au_h_dptr(root, bindex) == path.dentry) { -+ xino_itrunc->bindex = bindex; -+ break; -+ } -+ } -+ aufs_read_unlock(root, !AuLock_IR); -+ path_put(&path); -+ -+ if (unlikely(xino_itrunc->bindex < 0)) { -+ pr_err("no such branch %s\n", args[0].from); -+ err = -EINVAL; -+ } -+ -+out: -+ return err; -+} -+ -+/* called without aufs lock */ -+int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts) -+{ -+ int err, n, token; -+ aufs_bindex_t bindex; -+ unsigned char skipped; -+ struct dentry *root; -+ struct au_opt *opt, *opt_tail; -+ char *opt_str; -+ /* reduce the stack space */ -+ union { -+ struct au_opt_xino_itrunc *xino_itrunc; -+ struct au_opt_wbr_create *create; -+ } u; -+ struct { -+ substring_t args[MAX_OPT_ARGS]; -+ } *a; -+ -+ err = -ENOMEM; -+ a = kmalloc(sizeof(*a), GFP_NOFS); -+ if (unlikely(!a)) -+ goto out; -+ -+ root = sb->s_root; -+ err = 0; -+ bindex = 0; -+ opt = opts->opt; -+ opt_tail = opt + opts->max_opt - 1; -+ opt->type = Opt_tail; -+ while (!err && (opt_str = strsep(&str, ",")) && *opt_str) { -+ err = -EINVAL; -+ skipped = 0; -+ token = match_token(opt_str, options, a->args); -+ switch (token) { -+ case Opt_br: -+ err = 0; -+ while (!err && (opt_str = strsep(&a->args[0].from, ":")) -+ && *opt_str) { -+ err = opt_add(opt, opt_str, opts->sb_flags, -+ bindex++); -+ if (unlikely(!err && ++opt > opt_tail)) { -+ err = -E2BIG; -+ break; -+ } -+ opt->type = Opt_tail; -+ skipped = 1; -+ } -+ break; -+ case Opt_add: -+ if (unlikely(match_int(&a->args[0], &n))) { -+ pr_err("bad integer in %s\n", opt_str); -+ break; -+ } -+ bindex = n; -+ err = opt_add(opt, a->args[1].from, opts->sb_flags, -+ bindex); -+ if (!err) -+ opt->type = token; -+ break; -+ case Opt_append: -+ err = opt_add(opt, a->args[0].from, opts->sb_flags, -+ /*dummy bindex*/1); -+ if (!err) -+ opt->type = token; -+ break; -+ case Opt_prepend: -+ err = opt_add(opt, a->args[0].from, opts->sb_flags, -+ /*bindex*/0); -+ if (!err) -+ opt->type = token; -+ break; -+ case Opt_del: -+ err = au_opts_parse_del(&opt->del, a->args); -+ if (!err) -+ opt->type = token; -+ break; -+#if 0 /* reserved for future use */ -+ case Opt_idel: -+ del->pathname = "(indexed)"; -+ if (unlikely(match_int(&args[0], &n))) { -+ pr_err("bad integer in %s\n", opt_str); -+ break; -+ } -+ err = au_opts_parse_idel(sb, n, &opt->del, a->args); -+ if (!err) -+ opt->type = token; -+ break; -+#endif -+ case Opt_mod: -+ err = au_opts_parse_mod(&opt->mod, a->args); -+ if (!err) -+ opt->type = token; -+ break; -+#ifdef IMOD /* reserved for future use */ -+ case Opt_imod: -+ u.mod->path = "(indexed)"; -+ if (unlikely(match_int(&a->args[0], &n))) { -+ pr_err("bad integer in %s\n", opt_str); -+ break; -+ } -+ err = au_opts_parse_imod(sb, n, &opt->mod, a->args); -+ if (!err) -+ opt->type = token; -+ break; -+#endif -+ case Opt_xino: -+ err = au_opts_parse_xino(sb, &opt->xino, a->args); -+ if (!err) -+ opt->type = token; -+ break; -+ -+ case Opt_trunc_xino_path: -+ err = au_opts_parse_xino_itrunc_path -+ (sb, &opt->xino_itrunc, a->args); -+ if (!err) -+ opt->type = token; -+ break; -+ -+ case Opt_itrunc_xino: -+ u.xino_itrunc = &opt->xino_itrunc; -+ if (unlikely(match_int(&a->args[0], &n))) { -+ pr_err("bad integer in %s\n", opt_str); -+ break; -+ } -+ u.xino_itrunc->bindex = n; -+ aufs_read_lock(root, AuLock_FLUSH); -+ if (n < 0 || au_sbbot(sb) < n) { -+ pr_err("out of bounds, %d\n", n); -+ aufs_read_unlock(root, !AuLock_IR); -+ break; -+ } -+ aufs_read_unlock(root, !AuLock_IR); -+ err = 0; -+ opt->type = token; -+ break; -+ -+ case Opt_dirwh: -+ if (unlikely(match_int(&a->args[0], &opt->dirwh))) -+ break; -+ err = 0; -+ opt->type = token; -+ break; -+ -+ case Opt_rdcache: -+ if (unlikely(match_int(&a->args[0], &n))) { -+ pr_err("bad integer in %s\n", opt_str); -+ break; -+ } -+ if (unlikely(n > AUFS_RDCACHE_MAX)) { -+ pr_err("rdcache must be smaller than %d\n", -+ AUFS_RDCACHE_MAX); -+ break; -+ } -+ opt->rdcache = n; -+ err = 0; -+ opt->type = token; -+ break; -+ case Opt_rdblk: -+ if (unlikely(match_int(&a->args[0], &n) -+ || n < 0 -+ || n > KMALLOC_MAX_SIZE)) { -+ pr_err("bad integer in %s\n", opt_str); -+ break; -+ } -+ if (unlikely(n && n < NAME_MAX)) { -+ pr_err("rdblk must be larger than %d\n", -+ NAME_MAX); -+ break; -+ } -+ opt->rdblk = n; -+ err = 0; -+ opt->type = token; -+ break; -+ case Opt_rdhash: -+ if (unlikely(match_int(&a->args[0], &n) -+ || n < 0 -+ || n * sizeof(struct hlist_head) -+ > KMALLOC_MAX_SIZE)) { -+ pr_err("bad integer in %s\n", opt_str); -+ break; -+ } -+ opt->rdhash = n; -+ err = 0; -+ opt->type = token; -+ break; -+ -+ case Opt_trunc_xino: -+ case Opt_notrunc_xino: -+ case Opt_noxino: -+ case Opt_trunc_xib: -+ case Opt_notrunc_xib: -+ case Opt_shwh: -+ case Opt_noshwh: -+ case Opt_dirperm1: -+ case Opt_nodirperm1: -+ case Opt_plink: -+ case Opt_noplink: -+ case Opt_list_plink: -+ case Opt_dio: -+ case Opt_nodio: -+ case Opt_diropq_a: -+ case Opt_diropq_w: -+ case Opt_warn_perm: -+ case Opt_nowarn_perm: -+ case Opt_verbose: -+ case Opt_noverbose: -+ case Opt_sum: -+ case Opt_nosum: -+ case Opt_wsum: -+ case Opt_rdblk_def: -+ case Opt_rdhash_def: -+ case Opt_dirren: -+ case Opt_nodirren: -+ case Opt_acl: -+ case Opt_noacl: -+ err = 0; -+ opt->type = token; -+ break; -+ -+ case Opt_udba: -+ opt->udba = udba_val(a->args[0].from); -+ if (opt->udba >= 0) { -+ err = 0; -+ opt->type = token; -+ } else -+ pr_err("wrong value, %s\n", opt_str); -+ break; -+ -+ case Opt_wbr_create: -+ u.create = &opt->wbr_create; -+ u.create->wbr_create -+ = au_wbr_create_val(a->args[0].from, u.create); -+ if (u.create->wbr_create >= 0) { -+ err = 0; -+ opt->type = token; -+ } else -+ pr_err("wrong value, %s\n", opt_str); -+ break; -+ case Opt_wbr_copyup: -+ opt->wbr_copyup = au_wbr_copyup_val(a->args[0].from); -+ if (opt->wbr_copyup >= 0) { -+ err = 0; -+ opt->type = token; -+ } else -+ pr_err("wrong value, %s\n", opt_str); -+ break; -+ -+ case Opt_fhsm_sec: -+ if (unlikely(match_int(&a->args[0], &n) -+ || n < 0)) { -+ pr_err("bad integer in %s\n", opt_str); -+ break; -+ } -+ if (sysaufs_brs) { -+ opt->fhsm_second = n; -+ opt->type = token; -+ } else -+ pr_warn("ignored %s\n", opt_str); -+ err = 0; -+ break; -+ -+ case Opt_ignore: -+ pr_warn("ignored %s\n", opt_str); -+ /*FALLTHROUGH*/ -+ case Opt_ignore_silent: -+ skipped = 1; -+ err = 0; -+ break; -+ case Opt_err: -+ pr_err("unknown option %s\n", opt_str); -+ break; -+ } -+ -+ if (!err && !skipped) { -+ if (unlikely(++opt > opt_tail)) { -+ err = -E2BIG; -+ opt--; -+ opt->type = Opt_tail; -+ break; -+ } -+ opt->type = Opt_tail; -+ } -+ } -+ -+ au_kfree_rcu(a); -+ dump_opts(opts); -+ if (unlikely(err)) -+ au_opts_free(opts); -+ -+out: -+ return err; -+} -+ -+static int au_opt_wbr_create(struct super_block *sb, -+ struct au_opt_wbr_create *create) -+{ -+ int err; -+ struct au_sbinfo *sbinfo; -+ -+ SiMustWriteLock(sb); -+ -+ err = 1; /* handled */ -+ sbinfo = au_sbi(sb); -+ if (sbinfo->si_wbr_create_ops->fin) { -+ err = sbinfo->si_wbr_create_ops->fin(sb); -+ if (!err) -+ err = 1; -+ } -+ -+ sbinfo->si_wbr_create = create->wbr_create; -+ sbinfo->si_wbr_create_ops = au_wbr_create_ops + create->wbr_create; -+ switch (create->wbr_create) { -+ case AuWbrCreate_MFSRRV: -+ case AuWbrCreate_MFSRR: -+ case AuWbrCreate_TDMFS: -+ case AuWbrCreate_TDMFSV: -+ case AuWbrCreate_PMFSRR: -+ case AuWbrCreate_PMFSRRV: -+ sbinfo->si_wbr_mfs.mfsrr_watermark = create->mfsrr_watermark; -+ /*FALLTHROUGH*/ -+ case AuWbrCreate_MFS: -+ case AuWbrCreate_MFSV: -+ case AuWbrCreate_PMFS: -+ case AuWbrCreate_PMFSV: -+ sbinfo->si_wbr_mfs.mfs_expire -+ = msecs_to_jiffies(create->mfs_second * MSEC_PER_SEC); -+ break; -+ } -+ -+ if (sbinfo->si_wbr_create_ops->init) -+ sbinfo->si_wbr_create_ops->init(sb); /* ignore */ -+ -+ return err; -+} -+ -+/* -+ * returns, -+ * plus: processed without an error -+ * zero: unprocessed -+ */ -+static int au_opt_simple(struct super_block *sb, struct au_opt *opt, -+ struct au_opts *opts) -+{ -+ int err; -+ struct au_sbinfo *sbinfo; -+ -+ SiMustWriteLock(sb); -+ -+ err = 1; /* handled */ -+ sbinfo = au_sbi(sb); -+ switch (opt->type) { -+ case Opt_udba: -+ sbinfo->si_mntflags &= ~AuOptMask_UDBA; -+ sbinfo->si_mntflags |= opt->udba; -+ opts->given_udba |= opt->udba; -+ break; -+ -+ case Opt_plink: -+ au_opt_set(sbinfo->si_mntflags, PLINK); -+ break; -+ case Opt_noplink: -+ if (au_opt_test(sbinfo->si_mntflags, PLINK)) -+ au_plink_put(sb, /*verbose*/1); -+ au_opt_clr(sbinfo->si_mntflags, PLINK); -+ break; -+ case Opt_list_plink: -+ if (au_opt_test(sbinfo->si_mntflags, PLINK)) -+ au_plink_list(sb); -+ break; -+ -+ case Opt_dio: -+ au_opt_set(sbinfo->si_mntflags, DIO); -+ au_fset_opts(opts->flags, REFRESH_DYAOP); -+ break; -+ case Opt_nodio: -+ au_opt_clr(sbinfo->si_mntflags, DIO); -+ au_fset_opts(opts->flags, REFRESH_DYAOP); -+ break; -+ -+ case Opt_fhsm_sec: -+ au_fhsm_set(sbinfo, opt->fhsm_second); -+ break; -+ -+ case Opt_diropq_a: -+ au_opt_set(sbinfo->si_mntflags, ALWAYS_DIROPQ); -+ break; -+ case Opt_diropq_w: -+ au_opt_clr(sbinfo->si_mntflags, ALWAYS_DIROPQ); -+ break; -+ -+ case Opt_warn_perm: -+ au_opt_set(sbinfo->si_mntflags, WARN_PERM); -+ break; -+ case Opt_nowarn_perm: -+ au_opt_clr(sbinfo->si_mntflags, WARN_PERM); -+ break; -+ -+ case Opt_verbose: -+ au_opt_set(sbinfo->si_mntflags, VERBOSE); -+ break; -+ case Opt_noverbose: -+ au_opt_clr(sbinfo->si_mntflags, VERBOSE); -+ break; -+ -+ case Opt_sum: -+ au_opt_set(sbinfo->si_mntflags, SUM); -+ break; -+ case Opt_wsum: -+ au_opt_clr(sbinfo->si_mntflags, SUM); -+ au_opt_set(sbinfo->si_mntflags, SUM_W); -+ break; -+ case Opt_nosum: -+ au_opt_clr(sbinfo->si_mntflags, SUM); -+ au_opt_clr(sbinfo->si_mntflags, SUM_W); -+ break; -+ -+ case Opt_wbr_create: -+ err = au_opt_wbr_create(sb, &opt->wbr_create); -+ break; -+ case Opt_wbr_copyup: -+ sbinfo->si_wbr_copyup = opt->wbr_copyup; -+ sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + opt->wbr_copyup; -+ break; -+ -+ case Opt_dirwh: -+ sbinfo->si_dirwh = opt->dirwh; -+ break; -+ -+ case Opt_rdcache: -+ sbinfo->si_rdcache -+ = msecs_to_jiffies(opt->rdcache * MSEC_PER_SEC); -+ break; -+ case Opt_rdblk: -+ sbinfo->si_rdblk = opt->rdblk; -+ break; -+ case Opt_rdblk_def: -+ sbinfo->si_rdblk = AUFS_RDBLK_DEF; -+ break; -+ case Opt_rdhash: -+ sbinfo->si_rdhash = opt->rdhash; -+ break; -+ case Opt_rdhash_def: -+ sbinfo->si_rdhash = AUFS_RDHASH_DEF; -+ break; -+ -+ case Opt_shwh: -+ au_opt_set(sbinfo->si_mntflags, SHWH); -+ break; -+ case Opt_noshwh: -+ au_opt_clr(sbinfo->si_mntflags, SHWH); -+ break; -+ -+ case Opt_dirperm1: -+ au_opt_set(sbinfo->si_mntflags, DIRPERM1); -+ break; -+ case Opt_nodirperm1: -+ au_opt_clr(sbinfo->si_mntflags, DIRPERM1); -+ break; -+ -+ case Opt_trunc_xino: -+ au_opt_set(sbinfo->si_mntflags, TRUNC_XINO); -+ break; -+ case Opt_notrunc_xino: -+ au_opt_clr(sbinfo->si_mntflags, TRUNC_XINO); -+ break; -+ -+ case Opt_trunc_xino_path: -+ case Opt_itrunc_xino: -+ err = au_xino_trunc(sb, opt->xino_itrunc.bindex, -+ /*idx_begin*/0); -+ if (!err) -+ err = 1; -+ break; -+ -+ case Opt_trunc_xib: -+ au_fset_opts(opts->flags, TRUNC_XIB); -+ break; -+ case Opt_notrunc_xib: -+ au_fclr_opts(opts->flags, TRUNC_XIB); -+ break; -+ -+ case Opt_dirren: -+ err = 1; -+ if (!au_opt_test(sbinfo->si_mntflags, DIRREN)) { -+ err = au_dr_opt_set(sb); -+ if (!err) -+ err = 1; -+ } -+ if (err == 1) -+ au_opt_set(sbinfo->si_mntflags, DIRREN); -+ break; -+ case Opt_nodirren: -+ err = 1; -+ if (au_opt_test(sbinfo->si_mntflags, DIRREN)) { -+ err = au_dr_opt_clr(sb, au_ftest_opts(opts->flags, -+ DR_FLUSHED)); -+ if (!err) -+ err = 1; -+ } -+ if (err == 1) -+ au_opt_clr(sbinfo->si_mntflags, DIRREN); -+ break; -+ -+ case Opt_acl: -+ sb->s_flags |= SB_POSIXACL; -+ break; -+ case Opt_noacl: -+ sb->s_flags &= ~SB_POSIXACL; -+ break; -+ -+ default: -+ err = 0; -+ break; -+ } -+ -+ return err; -+} -+ -+/* -+ * returns tri-state. -+ * plus: processed without an error -+ * zero: unprocessed -+ * minus: error -+ */ -+static int au_opt_br(struct super_block *sb, struct au_opt *opt, -+ struct au_opts *opts) -+{ -+ int err, do_refresh; -+ -+ err = 0; -+ switch (opt->type) { -+ case Opt_append: -+ opt->add.bindex = au_sbbot(sb) + 1; -+ if (opt->add.bindex < 0) -+ opt->add.bindex = 0; -+ goto add; -+ /* Always goto add, not fallthrough */ -+ case Opt_prepend: -+ opt->add.bindex = 0; -+ /* fallthrough */ -+ add: /* indented label */ -+ case Opt_add: -+ err = au_br_add(sb, &opt->add, -+ au_ftest_opts(opts->flags, REMOUNT)); -+ if (!err) { -+ err = 1; -+ au_fset_opts(opts->flags, REFRESH); -+ } -+ break; -+ -+ case Opt_del: -+ case Opt_idel: -+ err = au_br_del(sb, &opt->del, -+ au_ftest_opts(opts->flags, REMOUNT)); -+ if (!err) { -+ err = 1; -+ au_fset_opts(opts->flags, TRUNC_XIB); -+ au_fset_opts(opts->flags, REFRESH); -+ } -+ break; -+ -+ case Opt_mod: -+ case Opt_imod: -+ err = au_br_mod(sb, &opt->mod, -+ au_ftest_opts(opts->flags, REMOUNT), -+ &do_refresh); -+ if (!err) { -+ err = 1; -+ if (do_refresh) -+ au_fset_opts(opts->flags, REFRESH); -+ } -+ break; -+ } -+ return err; -+} -+ -+static int au_opt_xino(struct super_block *sb, struct au_opt *opt, -+ struct au_opt_xino **opt_xino, -+ struct au_opts *opts) -+{ -+ int err; -+ -+ err = 0; -+ switch (opt->type) { -+ case Opt_xino: -+ err = au_xino_set(sb, &opt->xino, -+ !!au_ftest_opts(opts->flags, REMOUNT)); -+ if (unlikely(err)) -+ break; -+ -+ *opt_xino = &opt->xino; -+ break; -+ -+ case Opt_noxino: -+ au_xino_clr(sb); -+ *opt_xino = (void *)-1; -+ break; -+ } -+ -+ return err; -+} -+ -+int au_opts_verify(struct super_block *sb, unsigned long sb_flags, -+ unsigned int pending) -+{ -+ int err, fhsm; -+ aufs_bindex_t bindex, bbot; -+ unsigned char do_plink, skip, do_free, can_no_dreval; -+ struct au_branch *br; -+ struct au_wbr *wbr; -+ struct dentry *root, *dentry; -+ struct inode *dir, *h_dir; -+ struct au_sbinfo *sbinfo; -+ struct au_hinode *hdir; -+ -+ SiMustAnyLock(sb); -+ -+ sbinfo = au_sbi(sb); -+ AuDebugOn(!(sbinfo->si_mntflags & AuOptMask_UDBA)); -+ -+ if (!(sb_flags & SB_RDONLY)) { -+ if (unlikely(!au_br_writable(au_sbr_perm(sb, 0)))) -+ pr_warn("first branch should be rw\n"); -+ if (unlikely(au_opt_test(sbinfo->si_mntflags, SHWH))) -+ pr_warn_once("shwh should be used with ro\n"); -+ } -+ -+ if (au_opt_test((sbinfo->si_mntflags | pending), UDBA_HNOTIFY) -+ && !au_opt_test(sbinfo->si_mntflags, XINO)) -+ pr_warn_once("udba=*notify requires xino\n"); -+ -+ if (au_opt_test(sbinfo->si_mntflags, DIRPERM1)) -+ pr_warn_once("dirperm1 breaks the protection" -+ " by the permission bits on the lower branch\n"); -+ -+ err = 0; -+ fhsm = 0; -+ root = sb->s_root; -+ dir = d_inode(root); -+ do_plink = !!au_opt_test(sbinfo->si_mntflags, PLINK); -+ can_no_dreval = !!au_opt_test((sbinfo->si_mntflags | pending), -+ UDBA_NONE); -+ bbot = au_sbbot(sb); -+ for (bindex = 0; !err && bindex <= bbot; bindex++) { -+ skip = 0; -+ h_dir = au_h_iptr(dir, bindex); -+ br = au_sbr(sb, bindex); -+ -+ if ((br->br_perm & AuBrAttr_ICEX) -+ && !h_dir->i_op->listxattr) -+ br->br_perm &= ~AuBrAttr_ICEX; -+#if 0 /* untested */ -+ if ((br->br_perm & AuBrAttr_ICEX_SEC) -+ && (au_br_sb(br)->s_flags & SB_NOSEC)) -+ br->br_perm &= ~AuBrAttr_ICEX_SEC; -+#endif -+ -+ do_free = 0; -+ wbr = br->br_wbr; -+ if (wbr) -+ wbr_wh_read_lock(wbr); -+ -+ if (!au_br_writable(br->br_perm)) { -+ do_free = !!wbr; -+ skip = (!wbr -+ || (!wbr->wbr_whbase -+ && !wbr->wbr_plink -+ && !wbr->wbr_orph)); -+ } else if (!au_br_wh_linkable(br->br_perm)) { -+ /* skip = (!br->br_whbase && !br->br_orph); */ -+ skip = (!wbr || !wbr->wbr_whbase); -+ if (skip && wbr) { -+ if (do_plink) -+ skip = !!wbr->wbr_plink; -+ else -+ skip = !wbr->wbr_plink; -+ } -+ } else { -+ /* skip = (br->br_whbase && br->br_ohph); */ -+ skip = (wbr && wbr->wbr_whbase); -+ if (skip) { -+ if (do_plink) -+ skip = !!wbr->wbr_plink; -+ else -+ skip = !wbr->wbr_plink; -+ } -+ } -+ if (wbr) -+ wbr_wh_read_unlock(wbr); -+ -+ if (can_no_dreval) { -+ dentry = br->br_path.dentry; -+ spin_lock(&dentry->d_lock); -+ if (dentry->d_flags & -+ (DCACHE_OP_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE)) -+ can_no_dreval = 0; -+ spin_unlock(&dentry->d_lock); -+ } -+ -+ if (au_br_fhsm(br->br_perm)) { -+ fhsm++; -+ AuDebugOn(!br->br_fhsm); -+ } -+ -+ if (skip) -+ continue; -+ -+ hdir = au_hi(dir, bindex); -+ au_hn_inode_lock_nested(hdir, AuLsc_I_PARENT); -+ if (wbr) -+ wbr_wh_write_lock(wbr); -+ err = au_wh_init(br, sb); -+ if (wbr) -+ wbr_wh_write_unlock(wbr); -+ au_hn_inode_unlock(hdir); -+ -+ if (!err && do_free) { -+ au_kfree_rcu(wbr); -+ br->br_wbr = NULL; -+ } -+ } -+ -+ if (can_no_dreval) -+ au_fset_si(sbinfo, NO_DREVAL); -+ else -+ au_fclr_si(sbinfo, NO_DREVAL); -+ -+ if (fhsm >= 2) { -+ au_fset_si(sbinfo, FHSM); -+ for (bindex = bbot; bindex >= 0; bindex--) { -+ br = au_sbr(sb, bindex); -+ if (au_br_fhsm(br->br_perm)) { -+ au_fhsm_set_bottom(sb, bindex); -+ break; -+ } -+ } -+ } else { -+ au_fclr_si(sbinfo, FHSM); -+ au_fhsm_set_bottom(sb, -1); -+ } -+ -+ return err; -+} -+ -+int au_opts_mount(struct super_block *sb, struct au_opts *opts) -+{ -+ int err; -+ unsigned int tmp; -+ aufs_bindex_t bindex, bbot; -+ struct au_opt *opt; -+ struct au_opt_xino *opt_xino, xino; -+ struct au_sbinfo *sbinfo; -+ struct au_branch *br; -+ struct inode *dir; -+ -+ SiMustWriteLock(sb); -+ -+ err = 0; -+ opt_xino = NULL; -+ opt = opts->opt; -+ while (err >= 0 && opt->type != Opt_tail) -+ err = au_opt_simple(sb, opt++, opts); -+ if (err > 0) -+ err = 0; -+ else if (unlikely(err < 0)) -+ goto out; -+ -+ /* disable xino and udba temporary */ -+ sbinfo = au_sbi(sb); -+ tmp = sbinfo->si_mntflags; -+ au_opt_clr(sbinfo->si_mntflags, XINO); -+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_REVAL); -+ -+ opt = opts->opt; -+ while (err >= 0 && opt->type != Opt_tail) -+ err = au_opt_br(sb, opt++, opts); -+ if (err > 0) -+ err = 0; -+ else if (unlikely(err < 0)) -+ goto out; -+ -+ bbot = au_sbbot(sb); -+ if (unlikely(bbot < 0)) { -+ err = -EINVAL; -+ pr_err("no branches\n"); -+ goto out; -+ } -+ -+ if (au_opt_test(tmp, XINO)) -+ au_opt_set(sbinfo->si_mntflags, XINO); -+ opt = opts->opt; -+ while (!err && opt->type != Opt_tail) -+ err = au_opt_xino(sb, opt++, &opt_xino, opts); -+ if (unlikely(err)) -+ goto out; -+ -+ err = au_opts_verify(sb, sb->s_flags, tmp); -+ if (unlikely(err)) -+ goto out; -+ -+ /* restore xino */ -+ if (au_opt_test(tmp, XINO) && !opt_xino) { -+ xino.file = au_xino_def(sb); -+ err = PTR_ERR(xino.file); -+ if (IS_ERR(xino.file)) -+ goto out; -+ -+ err = au_xino_set(sb, &xino, /*remount*/0); -+ fput(xino.file); -+ if (unlikely(err)) -+ goto out; -+ } -+ -+ /* restore udba */ -+ tmp &= AuOptMask_UDBA; -+ sbinfo->si_mntflags &= ~AuOptMask_UDBA; -+ sbinfo->si_mntflags |= tmp; -+ bbot = au_sbbot(sb); -+ for (bindex = 0; bindex <= bbot; bindex++) { -+ br = au_sbr(sb, bindex); -+ err = au_hnotify_reset_br(tmp, br, br->br_perm); -+ if (unlikely(err)) -+ AuIOErr("hnotify failed on br %d, %d, ignored\n", -+ bindex, err); -+ /* go on even if err */ -+ } -+ if (au_opt_test(tmp, UDBA_HNOTIFY)) { -+ dir = d_inode(sb->s_root); -+ au_hn_reset(dir, au_hi_flags(dir, /*isdir*/1) & ~AuHi_XINO); -+ } -+ -+out: -+ return err; -+} -+ -+int au_opts_remount(struct super_block *sb, struct au_opts *opts) -+{ -+ int err, rerr; -+ unsigned char no_dreval; -+ struct inode *dir; -+ struct au_opt_xino *opt_xino; -+ struct au_opt *opt; -+ struct au_sbinfo *sbinfo; -+ -+ SiMustWriteLock(sb); -+ -+ err = au_dr_opt_flush(sb); -+ if (unlikely(err)) -+ goto out; -+ au_fset_opts(opts->flags, DR_FLUSHED); -+ -+ dir = d_inode(sb->s_root); -+ sbinfo = au_sbi(sb); -+ opt_xino = NULL; -+ opt = opts->opt; -+ while (err >= 0 && opt->type != Opt_tail) { -+ err = au_opt_simple(sb, opt, opts); -+ if (!err) -+ err = au_opt_br(sb, opt, opts); -+ if (!err) -+ err = au_opt_xino(sb, opt, &opt_xino, opts); -+ opt++; -+ } -+ if (err > 0) -+ err = 0; -+ AuTraceErr(err); -+ /* go on even err */ -+ -+ no_dreval = !!au_ftest_si(sbinfo, NO_DREVAL); -+ rerr = au_opts_verify(sb, opts->sb_flags, /*pending*/0); -+ if (unlikely(rerr && !err)) -+ err = rerr; -+ -+ if (no_dreval != !!au_ftest_si(sbinfo, NO_DREVAL)) -+ au_fset_opts(opts->flags, REFRESH_IDOP); -+ -+ if (au_ftest_opts(opts->flags, TRUNC_XIB)) { -+ rerr = au_xib_trunc(sb); -+ if (unlikely(rerr && !err)) -+ err = rerr; -+ } -+ -+ /* will be handled by the caller */ -+ if (!au_ftest_opts(opts->flags, REFRESH) -+ && (opts->given_udba -+ || au_opt_test(sbinfo->si_mntflags, XINO) -+ || au_ftest_opts(opts->flags, REFRESH_IDOP) -+ )) -+ au_fset_opts(opts->flags, REFRESH); -+ -+ AuDbg("status 0x%x\n", opts->flags); -+ -+out: -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+unsigned int au_opt_udba(struct super_block *sb) -+{ -+ return au_mntflags(sb) & AuOptMask_UDBA; -+} -diff -Nurp linux-5.10-rc6/fs/aufs/opts.h linux-5.10-rc6.aufs/fs/aufs/opts.h ---- linux-5.10-rc6/fs/aufs/opts.h 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/opts.h 2020-12-02 21:19:51.883036833 +0200 -@@ -0,0 +1,212 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * mount options/flags -+ */ -+ -+#ifndef __AUFS_OPTS_H__ -+#define __AUFS_OPTS_H__ -+ -+#ifdef __KERNEL__ -+ -+#include -+ -+struct file; -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* mount flags */ -+#define AuOpt_XINO 1 /* external inode number bitmap -+ and translation table */ -+#define AuOpt_TRUNC_XINO (1 << 1) /* truncate xino files */ -+#define AuOpt_UDBA_NONE (1 << 2) /* users direct branch access */ -+#define AuOpt_UDBA_REVAL (1 << 3) -+#define AuOpt_UDBA_HNOTIFY (1 << 4) -+#define AuOpt_SHWH (1 << 5) /* show whiteout */ -+#define AuOpt_PLINK (1 << 6) /* pseudo-link */ -+#define AuOpt_DIRPERM1 (1 << 7) /* ignore the lower dir's perm -+ bits */ -+#define AuOpt_ALWAYS_DIROPQ (1 << 9) /* policy to creating diropq */ -+#define AuOpt_SUM (1 << 10) /* summation for statfs(2) */ -+#define AuOpt_SUM_W (1 << 11) /* unimplemented */ -+#define AuOpt_WARN_PERM (1 << 12) /* warn when add-branch */ -+#define AuOpt_VERBOSE (1 << 13) /* print the cause of error */ -+#define AuOpt_DIO (1 << 14) /* direct io */ -+#define AuOpt_DIRREN (1 << 15) /* directory rename */ -+ -+#ifndef CONFIG_AUFS_HNOTIFY -+#undef AuOpt_UDBA_HNOTIFY -+#define AuOpt_UDBA_HNOTIFY 0 -+#endif -+#ifndef CONFIG_AUFS_DIRREN -+#undef AuOpt_DIRREN -+#define AuOpt_DIRREN 0 -+#endif -+#ifndef CONFIG_AUFS_SHWH -+#undef AuOpt_SHWH -+#define AuOpt_SHWH 0 -+#endif -+ -+#define AuOpt_Def (AuOpt_XINO \ -+ | AuOpt_UDBA_REVAL \ -+ | AuOpt_PLINK \ -+ /* | AuOpt_DIRPERM1 */ \ -+ | AuOpt_WARN_PERM) -+#define AuOptMask_UDBA (AuOpt_UDBA_NONE \ -+ | AuOpt_UDBA_REVAL \ -+ | AuOpt_UDBA_HNOTIFY) -+ -+#define au_opt_test(flags, name) (flags & AuOpt_##name) -+#define au_opt_set(flags, name) do { \ -+ BUILD_BUG_ON(AuOpt_##name & AuOptMask_UDBA); \ -+ ((flags) |= AuOpt_##name); \ -+} while (0) -+#define au_opt_set_udba(flags, name) do { \ -+ (flags) &= ~AuOptMask_UDBA; \ -+ ((flags) |= AuOpt_##name); \ -+} while (0) -+#define au_opt_clr(flags, name) do { \ -+ ((flags) &= ~AuOpt_##name); \ -+} while (0) -+ -+static inline unsigned int au_opts_plink(unsigned int mntflags) -+{ -+#ifdef CONFIG_PROC_FS -+ return mntflags; -+#else -+ return mntflags & ~AuOpt_PLINK; -+#endif -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* policies to select one among multiple writable branches */ -+enum { -+ AuWbrCreate_TDP, /* top down parent */ -+ AuWbrCreate_RR, /* round robin */ -+ AuWbrCreate_MFS, /* most free space */ -+ AuWbrCreate_MFSV, /* mfs with seconds */ -+ AuWbrCreate_MFSRR, /* mfs then rr */ -+ AuWbrCreate_MFSRRV, /* mfs then rr with seconds */ -+ AuWbrCreate_TDMFS, /* top down regardless parent and mfs */ -+ AuWbrCreate_TDMFSV, /* top down regardless parent and mfs */ -+ AuWbrCreate_PMFS, /* parent and mfs */ -+ AuWbrCreate_PMFSV, /* parent and mfs with seconds */ -+ AuWbrCreate_PMFSRR, /* parent, mfs and round-robin */ -+ AuWbrCreate_PMFSRRV, /* plus seconds */ -+ -+ AuWbrCreate_Def = AuWbrCreate_TDP -+}; -+ -+enum { -+ AuWbrCopyup_TDP, /* top down parent */ -+ AuWbrCopyup_BUP, /* bottom up parent */ -+ AuWbrCopyup_BU, /* bottom up */ -+ -+ AuWbrCopyup_Def = AuWbrCopyup_TDP -+}; -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct au_opt_add { -+ aufs_bindex_t bindex; -+ char *pathname; -+ int perm; -+ struct path path; -+}; -+ -+struct au_opt_del { -+ char *pathname; -+ struct path h_path; -+}; -+ -+struct au_opt_mod { -+ char *path; -+ int perm; -+ struct dentry *h_root; -+}; -+ -+struct au_opt_xino { -+ char *path; -+ struct file *file; -+}; -+ -+struct au_opt_xino_itrunc { -+ aufs_bindex_t bindex; -+}; -+ -+struct au_opt_wbr_create { -+ int wbr_create; -+ int mfs_second; -+ unsigned long long mfsrr_watermark; -+}; -+ -+struct au_opt { -+ int type; -+ union { -+ struct au_opt_xino xino; -+ struct au_opt_xino_itrunc xino_itrunc; -+ struct au_opt_add add; -+ struct au_opt_del del; -+ struct au_opt_mod mod; -+ int dirwh; -+ int rdcache; -+ unsigned int rdblk; -+ unsigned int rdhash; -+ int udba; -+ struct au_opt_wbr_create wbr_create; -+ int wbr_copyup; -+ unsigned int fhsm_second; -+ }; -+}; -+ -+/* opts flags */ -+#define AuOpts_REMOUNT 1 -+#define AuOpts_REFRESH (1 << 1) -+#define AuOpts_TRUNC_XIB (1 << 2) -+#define AuOpts_REFRESH_DYAOP (1 << 3) -+#define AuOpts_REFRESH_IDOP (1 << 4) -+#define AuOpts_DR_FLUSHED (1 << 5) -+#define au_ftest_opts(flags, name) ((flags) & AuOpts_##name) -+#define au_fset_opts(flags, name) \ -+ do { (flags) |= AuOpts_##name; } while (0) -+#define au_fclr_opts(flags, name) \ -+ do { (flags) &= ~AuOpts_##name; } while (0) -+ -+#ifndef CONFIG_AUFS_DIRREN -+#undef AuOpts_DR_FLUSHED -+#define AuOpts_DR_FLUSHED 0 -+#endif -+ -+struct au_opts { -+ struct au_opt *opt; -+ int max_opt; -+ -+ unsigned int given_udba; -+ unsigned int flags; -+ unsigned long sb_flags; -+}; -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* opts.c */ -+void au_optstr_br_perm(au_br_perm_str_t *str, int perm); -+const char *au_optstr_udba(int udba); -+const char *au_optstr_wbr_copyup(int wbr_copyup); -+const char *au_optstr_wbr_create(int wbr_create); -+ -+void au_opts_free(struct au_opts *opts); -+struct super_block; -+int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts); -+int au_opts_verify(struct super_block *sb, unsigned long sb_flags, -+ unsigned int pending); -+int au_opts_mount(struct super_block *sb, struct au_opts *opts); -+int au_opts_remount(struct super_block *sb, struct au_opts *opts); -+ -+unsigned int au_opt_udba(struct super_block *sb); -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_OPTS_H__ */ -diff -Nurp linux-5.10-rc6/fs/aufs/plink.c linux-5.10-rc6.aufs/fs/aufs/plink.c ---- linux-5.10-rc6/fs/aufs/plink.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/plink.c 2020-12-02 21:19:51.883036833 +0200 -@@ -0,0 +1,503 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * pseudo-link -+ */ -+ -+#include "aufs.h" -+ -+/* -+ * the pseudo-link maintenance mode. -+ * during a user process maintains the pseudo-links, -+ * prohibit adding a new plink and branch manipulation. -+ * -+ * Flags -+ * NOPLM: -+ * For entry functions which will handle plink, and i_mutex is already held -+ * in VFS. -+ * They cannot wait and should return an error at once. -+ * Callers has to check the error. -+ * NOPLMW: -+ * For entry functions which will handle plink, but i_mutex is not held -+ * in VFS. -+ * They can wait the plink maintenance mode to finish. -+ * -+ * They behave like F_SETLK and F_SETLKW. -+ * If the caller never handle plink, then both flags are unnecessary. -+ */ -+ -+int au_plink_maint(struct super_block *sb, int flags) -+{ -+ int err; -+ pid_t pid, ppid; -+ struct task_struct *parent, *prev; -+ struct au_sbinfo *sbi; -+ -+ SiMustAnyLock(sb); -+ -+ err = 0; -+ if (!au_opt_test(au_mntflags(sb), PLINK)) -+ goto out; -+ -+ sbi = au_sbi(sb); -+ pid = sbi->si_plink_maint_pid; -+ if (!pid || pid == current->pid) -+ goto out; -+ -+ /* todo: it highly depends upon /sbin/mount.aufs */ -+ prev = NULL; -+ parent = current; -+ ppid = 0; -+ rcu_read_lock(); -+ while (1) { -+ parent = rcu_dereference(parent->real_parent); -+ if (parent == prev) -+ break; -+ ppid = task_pid_vnr(parent); -+ if (pid == ppid) { -+ rcu_read_unlock(); -+ goto out; -+ } -+ prev = parent; -+ } -+ rcu_read_unlock(); -+ -+ if (au_ftest_lock(flags, NOPLMW)) { -+ /* if there is no i_mutex lock in VFS, we don't need to wait */ -+ /* AuDebugOn(!lockdep_depth(current)); */ -+ while (sbi->si_plink_maint_pid) { -+ si_read_unlock(sb); -+ /* gave up wake_up_bit() */ -+ wait_event(sbi->si_plink_wq, !sbi->si_plink_maint_pid); -+ -+ if (au_ftest_lock(flags, FLUSH)) -+ au_nwt_flush(&sbi->si_nowait); -+ si_noflush_read_lock(sb); -+ } -+ } else if (au_ftest_lock(flags, NOPLM)) { -+ AuDbg("ppid %d, pid %d\n", ppid, pid); -+ err = -EAGAIN; -+ } -+ -+out: -+ return err; -+} -+ -+void au_plink_maint_leave(struct au_sbinfo *sbinfo) -+{ -+ spin_lock(&sbinfo->si_plink_maint_lock); -+ sbinfo->si_plink_maint_pid = 0; -+ spin_unlock(&sbinfo->si_plink_maint_lock); -+ wake_up_all(&sbinfo->si_plink_wq); -+} -+ -+int au_plink_maint_enter(struct super_block *sb) -+{ -+ int err; -+ struct au_sbinfo *sbinfo; -+ -+ err = 0; -+ sbinfo = au_sbi(sb); -+ /* make sure i am the only one in this fs */ -+ si_write_lock(sb, AuLock_FLUSH); -+ if (au_opt_test(au_mntflags(sb), PLINK)) { -+ spin_lock(&sbinfo->si_plink_maint_lock); -+ if (!sbinfo->si_plink_maint_pid) -+ sbinfo->si_plink_maint_pid = current->pid; -+ else -+ err = -EBUSY; -+ spin_unlock(&sbinfo->si_plink_maint_lock); -+ } -+ si_write_unlock(sb); -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+#ifdef CONFIG_AUFS_DEBUG -+void au_plink_list(struct super_block *sb) -+{ -+ int i; -+ struct au_sbinfo *sbinfo; -+ struct hlist_bl_head *hbl; -+ struct hlist_bl_node *pos; -+ struct au_icntnr *icntnr; -+ -+ SiMustAnyLock(sb); -+ -+ sbinfo = au_sbi(sb); -+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK)); -+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM)); -+ -+ for (i = 0; i < AuPlink_NHASH; i++) { -+ hbl = sbinfo->si_plink + i; -+ hlist_bl_lock(hbl); -+ hlist_bl_for_each_entry(icntnr, pos, hbl, plink) -+ AuDbg("%lu\n", icntnr->vfs_inode.i_ino); -+ hlist_bl_unlock(hbl); -+ } -+} -+#endif -+ -+/* is the inode pseudo-linked? */ -+int au_plink_test(struct inode *inode) -+{ -+ int found, i; -+ struct au_sbinfo *sbinfo; -+ struct hlist_bl_head *hbl; -+ struct hlist_bl_node *pos; -+ struct au_icntnr *icntnr; -+ -+ sbinfo = au_sbi(inode->i_sb); -+ AuRwMustAnyLock(&sbinfo->si_rwsem); -+ AuDebugOn(!au_opt_test(au_mntflags(inode->i_sb), PLINK)); -+ AuDebugOn(au_plink_maint(inode->i_sb, AuLock_NOPLM)); -+ -+ found = 0; -+ i = au_plink_hash(inode->i_ino); -+ hbl = sbinfo->si_plink + i; -+ hlist_bl_lock(hbl); -+ hlist_bl_for_each_entry(icntnr, pos, hbl, plink) -+ if (&icntnr->vfs_inode == inode) { -+ found = 1; -+ break; -+ } -+ hlist_bl_unlock(hbl); -+ return found; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * generate a name for plink. -+ * the file will be stored under AUFS_WH_PLINKDIR. -+ */ -+/* 20 is max digits length of ulong 64 */ -+#define PLINK_NAME_LEN ((20 + 1) * 2) -+ -+static int plink_name(char *name, int len, struct inode *inode, -+ aufs_bindex_t bindex) -+{ -+ int rlen; -+ struct inode *h_inode; -+ -+ h_inode = au_h_iptr(inode, bindex); -+ rlen = snprintf(name, len, "%lu.%lu", inode->i_ino, h_inode->i_ino); -+ return rlen; -+} -+ -+struct au_do_plink_lkup_args { -+ struct dentry **errp; -+ struct qstr *tgtname; -+ struct dentry *h_parent; -+ struct au_branch *br; -+}; -+ -+static struct dentry *au_do_plink_lkup(struct qstr *tgtname, -+ struct dentry *h_parent, -+ struct au_branch *br) -+{ -+ struct dentry *h_dentry; -+ struct inode *h_inode; -+ -+ h_inode = d_inode(h_parent); -+ inode_lock_shared_nested(h_inode, AuLsc_I_CHILD2); -+ h_dentry = vfsub_lkup_one(tgtname, h_parent); -+ inode_unlock_shared(h_inode); -+ return h_dentry; -+} -+ -+static void au_call_do_plink_lkup(void *args) -+{ -+ struct au_do_plink_lkup_args *a = args; -+ *a->errp = au_do_plink_lkup(a->tgtname, a->h_parent, a->br); -+} -+ -+/* lookup the plink-ed @inode under the branch at @bindex */ -+struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex) -+{ -+ struct dentry *h_dentry, *h_parent; -+ struct au_branch *br; -+ int wkq_err; -+ char a[PLINK_NAME_LEN]; -+ struct qstr tgtname = QSTR_INIT(a, 0); -+ -+ AuDebugOn(au_plink_maint(inode->i_sb, AuLock_NOPLM)); -+ -+ br = au_sbr(inode->i_sb, bindex); -+ h_parent = br->br_wbr->wbr_plink; -+ tgtname.len = plink_name(a, sizeof(a), inode, bindex); -+ -+ if (!uid_eq(current_fsuid(), GLOBAL_ROOT_UID)) { -+ struct au_do_plink_lkup_args args = { -+ .errp = &h_dentry, -+ .tgtname = &tgtname, -+ .h_parent = h_parent, -+ .br = br -+ }; -+ -+ wkq_err = au_wkq_wait(au_call_do_plink_lkup, &args); -+ if (unlikely(wkq_err)) -+ h_dentry = ERR_PTR(wkq_err); -+ } else -+ h_dentry = au_do_plink_lkup(&tgtname, h_parent, br); -+ -+ return h_dentry; -+} -+ -+/* create a pseudo-link */ -+static int do_whplink(struct qstr *tgt, struct dentry *h_parent, -+ struct dentry *h_dentry, struct au_branch *br) -+{ -+ int err; -+ struct path h_path = { -+ .mnt = au_br_mnt(br) -+ }; -+ struct inode *h_dir, *delegated; -+ -+ h_dir = d_inode(h_parent); -+ inode_lock_nested(h_dir, AuLsc_I_CHILD2); -+again: -+ h_path.dentry = vfsub_lkup_one(tgt, h_parent); -+ err = PTR_ERR(h_path.dentry); -+ if (IS_ERR(h_path.dentry)) -+ goto out; -+ -+ err = 0; -+ /* wh.plink dir is not monitored */ -+ /* todo: is it really safe? */ -+ if (d_is_positive(h_path.dentry) -+ && d_inode(h_path.dentry) != d_inode(h_dentry)) { -+ delegated = NULL; -+ err = vfsub_unlink(h_dir, &h_path, &delegated, /*force*/0); -+ if (unlikely(err == -EWOULDBLOCK)) { -+ pr_warn("cannot retry for NFSv4 delegation" -+ " for an internal unlink\n"); -+ iput(delegated); -+ } -+ dput(h_path.dentry); -+ h_path.dentry = NULL; -+ if (!err) -+ goto again; -+ } -+ if (!err && d_is_negative(h_path.dentry)) { -+ delegated = NULL; -+ err = vfsub_link(h_dentry, h_dir, &h_path, &delegated); -+ if (unlikely(err == -EWOULDBLOCK)) { -+ pr_warn("cannot retry for NFSv4 delegation" -+ " for an internal link\n"); -+ iput(delegated); -+ } -+ } -+ dput(h_path.dentry); -+ -+out: -+ inode_unlock(h_dir); -+ return err; -+} -+ -+struct do_whplink_args { -+ int *errp; -+ struct qstr *tgt; -+ struct dentry *h_parent; -+ struct dentry *h_dentry; -+ struct au_branch *br; -+}; -+ -+static void call_do_whplink(void *args) -+{ -+ struct do_whplink_args *a = args; -+ *a->errp = do_whplink(a->tgt, a->h_parent, a->h_dentry, a->br); -+} -+ -+static int whplink(struct dentry *h_dentry, struct inode *inode, -+ aufs_bindex_t bindex, struct au_branch *br) -+{ -+ int err, wkq_err; -+ struct au_wbr *wbr; -+ struct dentry *h_parent; -+ char a[PLINK_NAME_LEN]; -+ struct qstr tgtname = QSTR_INIT(a, 0); -+ -+ wbr = au_sbr(inode->i_sb, bindex)->br_wbr; -+ h_parent = wbr->wbr_plink; -+ tgtname.len = plink_name(a, sizeof(a), inode, bindex); -+ -+ /* always superio. */ -+ if (!uid_eq(current_fsuid(), GLOBAL_ROOT_UID)) { -+ struct do_whplink_args args = { -+ .errp = &err, -+ .tgt = &tgtname, -+ .h_parent = h_parent, -+ .h_dentry = h_dentry, -+ .br = br -+ }; -+ wkq_err = au_wkq_wait(call_do_whplink, &args); -+ if (unlikely(wkq_err)) -+ err = wkq_err; -+ } else -+ err = do_whplink(&tgtname, h_parent, h_dentry, br); -+ -+ return err; -+} -+ -+/* -+ * create a new pseudo-link for @h_dentry on @bindex. -+ * the linked inode is held in aufs @inode. -+ */ -+void au_plink_append(struct inode *inode, aufs_bindex_t bindex, -+ struct dentry *h_dentry) -+{ -+ struct super_block *sb; -+ struct au_sbinfo *sbinfo; -+ struct hlist_bl_head *hbl; -+ struct hlist_bl_node *pos; -+ struct au_icntnr *icntnr; -+ int found, err, cnt, i; -+ -+ sb = inode->i_sb; -+ sbinfo = au_sbi(sb); -+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK)); -+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM)); -+ -+ found = au_plink_test(inode); -+ if (found) -+ return; -+ -+ i = au_plink_hash(inode->i_ino); -+ hbl = sbinfo->si_plink + i; -+ au_igrab(inode); -+ -+ hlist_bl_lock(hbl); -+ hlist_bl_for_each_entry(icntnr, pos, hbl, plink) { -+ if (&icntnr->vfs_inode == inode) { -+ found = 1; -+ break; -+ } -+ } -+ if (!found) { -+ icntnr = container_of(inode, struct au_icntnr, vfs_inode); -+ hlist_bl_add_head(&icntnr->plink, hbl); -+ } -+ hlist_bl_unlock(hbl); -+ if (!found) { -+ cnt = au_hbl_count(hbl); -+#define msg "unexpectedly unbalanced or too many pseudo-links" -+ if (cnt > AUFS_PLINK_WARN) -+ AuWarn1(msg ", %d\n", cnt); -+#undef msg -+ err = whplink(h_dentry, inode, bindex, au_sbr(sb, bindex)); -+ if (unlikely(err)) { -+ pr_warn("err %d, damaged pseudo link.\n", err); -+ au_hbl_del(&icntnr->plink, hbl); -+ iput(&icntnr->vfs_inode); -+ } -+ } else -+ iput(&icntnr->vfs_inode); -+} -+ -+/* free all plinks */ -+void au_plink_put(struct super_block *sb, int verbose) -+{ -+ int i, warned; -+ struct au_sbinfo *sbinfo; -+ struct hlist_bl_head *hbl; -+ struct hlist_bl_node *pos, *tmp; -+ struct au_icntnr *icntnr; -+ -+ SiMustWriteLock(sb); -+ -+ sbinfo = au_sbi(sb); -+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK)); -+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM)); -+ -+ /* no spin_lock since sbinfo is write-locked */ -+ warned = 0; -+ for (i = 0; i < AuPlink_NHASH; i++) { -+ hbl = sbinfo->si_plink + i; -+ if (!warned && verbose && !hlist_bl_empty(hbl)) { -+ pr_warn("pseudo-link is not flushed"); -+ warned = 1; -+ } -+ hlist_bl_for_each_entry_safe(icntnr, pos, tmp, hbl, plink) -+ iput(&icntnr->vfs_inode); -+ INIT_HLIST_BL_HEAD(hbl); -+ } -+} -+ -+void au_plink_clean(struct super_block *sb, int verbose) -+{ -+ struct dentry *root; -+ -+ root = sb->s_root; -+ aufs_write_lock(root); -+ if (au_opt_test(au_mntflags(sb), PLINK)) -+ au_plink_put(sb, verbose); -+ aufs_write_unlock(root); -+} -+ -+static int au_plink_do_half_refresh(struct inode *inode, aufs_bindex_t br_id) -+{ -+ int do_put; -+ aufs_bindex_t btop, bbot, bindex; -+ -+ do_put = 0; -+ btop = au_ibtop(inode); -+ bbot = au_ibbot(inode); -+ if (btop >= 0) { -+ for (bindex = btop; bindex <= bbot; bindex++) { -+ if (!au_h_iptr(inode, bindex) -+ || au_ii_br_id(inode, bindex) != br_id) -+ continue; -+ au_set_h_iptr(inode, bindex, NULL, 0); -+ do_put = 1; -+ break; -+ } -+ if (do_put) -+ for (bindex = btop; bindex <= bbot; bindex++) -+ if (au_h_iptr(inode, bindex)) { -+ do_put = 0; -+ break; -+ } -+ } else -+ do_put = 1; -+ -+ return do_put; -+} -+ -+/* free the plinks on a branch specified by @br_id */ -+void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id) -+{ -+ struct au_sbinfo *sbinfo; -+ struct hlist_bl_head *hbl; -+ struct hlist_bl_node *pos, *tmp; -+ struct au_icntnr *icntnr; -+ struct inode *inode; -+ int i, do_put; -+ -+ SiMustWriteLock(sb); -+ -+ sbinfo = au_sbi(sb); -+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK)); -+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM)); -+ -+ /* no bit_lock since sbinfo is write-locked */ -+ for (i = 0; i < AuPlink_NHASH; i++) { -+ hbl = sbinfo->si_plink + i; -+ hlist_bl_for_each_entry_safe(icntnr, pos, tmp, hbl, plink) { -+ inode = au_igrab(&icntnr->vfs_inode); -+ ii_write_lock_child(inode); -+ do_put = au_plink_do_half_refresh(inode, br_id); -+ if (do_put) { -+ hlist_bl_del(&icntnr->plink); -+ iput(inode); -+ } -+ ii_write_unlock(inode); -+ iput(inode); -+ } -+ } -+} -diff -Nurp linux-5.10-rc6/fs/aufs/poll.c linux-5.10-rc6.aufs/fs/aufs/poll.c ---- linux-5.10-rc6/fs/aufs/poll.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/poll.c 2020-12-02 21:19:51.883036833 +0200 -@@ -0,0 +1,38 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * poll operation -+ * There is only one filesystem which implements ->poll operation, currently. -+ */ -+ -+#include "aufs.h" -+ -+__poll_t aufs_poll(struct file *file, struct poll_table_struct *pt) -+{ -+ __poll_t mask; -+ struct file *h_file; -+ struct super_block *sb; -+ -+ /* We should pretend an error happened. */ -+ mask = EPOLLERR /* | EPOLLIN | EPOLLOUT */; -+ sb = file->f_path.dentry->d_sb; -+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW); -+ -+ h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0); -+ if (IS_ERR(h_file)) { -+ AuDbg("h_file %ld\n", PTR_ERR(h_file)); -+ goto out; -+ } -+ -+ mask = vfs_poll(h_file, pt); -+ fput(h_file); /* instead of au_read_post() */ -+ -+out: -+ si_read_unlock(sb); -+ if (mask & EPOLLERR) -+ AuDbg("mask 0x%x\n", mask); -+ return mask; -+} -diff -Nurp linux-5.10-rc6/fs/aufs/posix_acl.c linux-5.10-rc6.aufs/fs/aufs/posix_acl.c ---- linux-5.10-rc6/fs/aufs/posix_acl.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/posix_acl.c 2020-12-02 21:19:51.883036833 +0200 -@@ -0,0 +1,92 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2014-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * posix acl operations -+ */ -+ -+#include -+#include "aufs.h" -+ -+struct posix_acl *aufs_get_acl(struct inode *inode, int type) -+{ -+ struct posix_acl *acl; -+ int err; -+ aufs_bindex_t bindex; -+ struct inode *h_inode; -+ struct super_block *sb; -+ -+ acl = NULL; -+ sb = inode->i_sb; -+ si_read_lock(sb, AuLock_FLUSH); -+ ii_read_lock_child(inode); -+ if (!(sb->s_flags & SB_POSIXACL)) -+ goto out; -+ -+ bindex = au_ibtop(inode); -+ h_inode = au_h_iptr(inode, bindex); -+ if (unlikely(!h_inode -+ || ((h_inode->i_mode & S_IFMT) -+ != (inode->i_mode & S_IFMT)))) { -+ err = au_busy_or_stale(); -+ acl = ERR_PTR(err); -+ goto out; -+ } -+ -+ /* always topmost only */ -+ acl = get_acl(h_inode, type); -+ if (IS_ERR(acl)) -+ forget_cached_acl(inode, type); -+ else -+ set_cached_acl(inode, type, acl); -+ -+out: -+ ii_read_unlock(inode); -+ si_read_unlock(sb); -+ -+ AuTraceErrPtr(acl); -+ return acl; -+} -+ -+int aufs_set_acl(struct inode *inode, struct posix_acl *acl, int type) -+{ -+ int err; -+ ssize_t ssz; -+ struct dentry *dentry; -+ struct au_sxattr arg = { -+ .type = AU_ACL_SET, -+ .u.acl_set = { -+ .acl = acl, -+ .type = type -+ }, -+ }; -+ -+ IMustLock(inode); -+ -+ if (inode->i_ino == AUFS_ROOT_INO) -+ dentry = dget(inode->i_sb->s_root); -+ else { -+ dentry = d_find_alias(inode); -+ if (!dentry) -+ dentry = d_find_any_alias(inode); -+ if (!dentry) { -+ pr_warn("cannot handle this inode, " -+ "please report to aufs-users ML\n"); -+ err = -ENOENT; -+ goto out; -+ } -+ } -+ -+ ssz = au_sxattr(dentry, inode, &arg); -+ /* forget even it if succeeds since the branch might set differently */ -+ forget_cached_acl(inode, type); -+ dput(dentry); -+ err = ssz; -+ if (ssz >= 0) -+ err = 0; -+ -+out: -+ return err; -+} -diff -Nurp linux-5.10-rc6/fs/aufs/procfs.c linux-5.10-rc6.aufs/fs/aufs/procfs.c ---- linux-5.10-rc6/fs/aufs/procfs.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/procfs.c 2020-12-02 21:19:51.883036833 +0200 -@@ -0,0 +1,157 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2010-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * procfs interfaces -+ */ -+ -+#include -+#include "aufs.h" -+ -+static int au_procfs_plm_release(struct inode *inode, struct file *file) -+{ -+ struct au_sbinfo *sbinfo; -+ -+ sbinfo = file->private_data; -+ if (sbinfo) { -+ au_plink_maint_leave(sbinfo); -+ kobject_put(&sbinfo->si_kobj); -+ } -+ -+ return 0; -+} -+ -+static void au_procfs_plm_write_clean(struct file *file) -+{ -+ struct au_sbinfo *sbinfo; -+ -+ sbinfo = file->private_data; -+ if (sbinfo) -+ au_plink_clean(sbinfo->si_sb, /*verbose*/0); -+} -+ -+static int au_procfs_plm_write_si(struct file *file, unsigned long id) -+{ -+ int err; -+ struct super_block *sb; -+ struct au_sbinfo *sbinfo; -+ struct hlist_bl_node *pos; -+ -+ err = -EBUSY; -+ if (unlikely(file->private_data)) -+ goto out; -+ -+ sb = NULL; -+ /* don't use au_sbilist_lock() here */ -+ hlist_bl_lock(&au_sbilist); -+ hlist_bl_for_each_entry(sbinfo, pos, &au_sbilist, si_list) -+ if (id == sysaufs_si_id(sbinfo)) { -+ if (kobject_get_unless_zero(&sbinfo->si_kobj)) -+ sb = sbinfo->si_sb; -+ break; -+ } -+ hlist_bl_unlock(&au_sbilist); -+ -+ err = -EINVAL; -+ if (unlikely(!sb)) -+ goto out; -+ -+ err = au_plink_maint_enter(sb); -+ if (!err) -+ /* keep kobject_get() */ -+ file->private_data = sbinfo; -+ else -+ kobject_put(&sbinfo->si_kobj); -+out: -+ return err; -+} -+ -+/* -+ * Accept a valid "si=xxxx" only. -+ * Once it is accepted successfully, accept "clean" too. -+ */ -+static ssize_t au_procfs_plm_write(struct file *file, const char __user *ubuf, -+ size_t count, loff_t *ppos) -+{ -+ ssize_t err; -+ unsigned long id; -+ /* last newline is allowed */ -+ char buf[3 + sizeof(unsigned long) * 2 + 1]; -+ -+ err = -EACCES; -+ if (unlikely(!capable(CAP_SYS_ADMIN))) -+ goto out; -+ -+ err = -EINVAL; -+ if (unlikely(count > sizeof(buf))) -+ goto out; -+ -+ err = copy_from_user(buf, ubuf, count); -+ if (unlikely(err)) { -+ err = -EFAULT; -+ goto out; -+ } -+ buf[count] = 0; -+ -+ err = -EINVAL; -+ if (!strcmp("clean", buf)) { -+ au_procfs_plm_write_clean(file); -+ goto out_success; -+ } else if (unlikely(strncmp("si=", buf, 3))) -+ goto out; -+ -+ err = kstrtoul(buf + 3, 16, &id); -+ if (unlikely(err)) -+ goto out; -+ -+ err = au_procfs_plm_write_si(file, id); -+ if (unlikely(err)) -+ goto out; -+ -+out_success: -+ err = count; /* success */ -+out: -+ return err; -+} -+ -+static const struct proc_ops au_procfs_plm_op = { -+ .proc_write = au_procfs_plm_write, -+ .proc_release = au_procfs_plm_release -+}; -+ -+/* ---------------------------------------------------------------------- */ -+ -+static struct proc_dir_entry *au_procfs_dir; -+ -+void au_procfs_fin(void) -+{ -+ remove_proc_entry(AUFS_PLINK_MAINT_NAME, au_procfs_dir); -+ remove_proc_entry(AUFS_PLINK_MAINT_DIR, NULL); -+} -+ -+int __init au_procfs_init(void) -+{ -+ int err; -+ struct proc_dir_entry *entry; -+ -+ err = -ENOMEM; -+ au_procfs_dir = proc_mkdir(AUFS_PLINK_MAINT_DIR, NULL); -+ if (unlikely(!au_procfs_dir)) -+ goto out; -+ -+ entry = proc_create(AUFS_PLINK_MAINT_NAME, S_IFREG | 0200, -+ au_procfs_dir, &au_procfs_plm_op); -+ if (unlikely(!entry)) -+ goto out_dir; -+ -+ err = 0; -+ goto out; /* success */ -+ -+ -+out_dir: -+ remove_proc_entry(AUFS_PLINK_MAINT_DIR, NULL); -+out: -+ return err; -+} -diff -Nurp linux-5.10-rc6/fs/aufs/rdu.c linux-5.10-rc6.aufs/fs/aufs/rdu.c ---- linux-5.10-rc6/fs/aufs/rdu.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/rdu.c 2020-12-02 21:19:51.883036833 +0200 -@@ -0,0 +1,371 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * readdir in userspace. -+ */ -+ -+#include -+#include -+#include -+#include "aufs.h" -+ -+/* bits for struct aufs_rdu.flags */ -+#define AuRdu_CALLED 1 -+#define AuRdu_CONT (1 << 1) -+#define AuRdu_FULL (1 << 2) -+#define au_ftest_rdu(flags, name) ((flags) & AuRdu_##name) -+#define au_fset_rdu(flags, name) \ -+ do { (flags) |= AuRdu_##name; } while (0) -+#define au_fclr_rdu(flags, name) \ -+ do { (flags) &= ~AuRdu_##name; } while (0) -+ -+struct au_rdu_arg { -+ struct dir_context ctx; -+ struct aufs_rdu *rdu; -+ union au_rdu_ent_ul ent; -+ unsigned long end; -+ -+ struct super_block *sb; -+ int err; -+}; -+ -+static int au_rdu_fill(struct dir_context *ctx, const char *name, int nlen, -+ loff_t offset, u64 h_ino, unsigned int d_type) -+{ -+ int err, len; -+ struct au_rdu_arg *arg = container_of(ctx, struct au_rdu_arg, ctx); -+ struct aufs_rdu *rdu = arg->rdu; -+ struct au_rdu_ent ent; -+ -+ err = 0; -+ arg->err = 0; -+ au_fset_rdu(rdu->cookie.flags, CALLED); -+ len = au_rdu_len(nlen); -+ if (arg->ent.ul + len < arg->end) { -+ ent.ino = h_ino; -+ ent.bindex = rdu->cookie.bindex; -+ ent.type = d_type; -+ ent.nlen = nlen; -+ if (unlikely(nlen > AUFS_MAX_NAMELEN)) -+ ent.type = DT_UNKNOWN; -+ -+ /* unnecessary to support mmap_sem since this is a dir */ -+ err = -EFAULT; -+ if (copy_to_user(arg->ent.e, &ent, sizeof(ent))) -+ goto out; -+ if (copy_to_user(arg->ent.e->name, name, nlen)) -+ goto out; -+ /* the terminating NULL */ -+ if (__put_user(0, arg->ent.e->name + nlen)) -+ goto out; -+ err = 0; -+ /* AuDbg("%p, %.*s\n", arg->ent.p, nlen, name); */ -+ arg->ent.ul += len; -+ rdu->rent++; -+ } else { -+ err = -EFAULT; -+ au_fset_rdu(rdu->cookie.flags, FULL); -+ rdu->full = 1; -+ rdu->tail = arg->ent; -+ } -+ -+out: -+ /* AuTraceErr(err); */ -+ return err; -+} -+ -+static int au_rdu_do(struct file *h_file, struct au_rdu_arg *arg) -+{ -+ int err; -+ loff_t offset; -+ struct au_rdu_cookie *cookie = &arg->rdu->cookie; -+ -+ /* we don't have to care (FMODE_32BITHASH | FMODE_64BITHASH) for ext4 */ -+ offset = vfsub_llseek(h_file, cookie->h_pos, SEEK_SET); -+ err = offset; -+ if (unlikely(offset != cookie->h_pos)) -+ goto out; -+ -+ err = 0; -+ do { -+ arg->err = 0; -+ au_fclr_rdu(cookie->flags, CALLED); -+ /* smp_mb(); */ -+ err = vfsub_iterate_dir(h_file, &arg->ctx); -+ if (err >= 0) -+ err = arg->err; -+ } while (!err -+ && au_ftest_rdu(cookie->flags, CALLED) -+ && !au_ftest_rdu(cookie->flags, FULL)); -+ cookie->h_pos = h_file->f_pos; -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+static int au_rdu(struct file *file, struct aufs_rdu *rdu) -+{ -+ int err; -+ aufs_bindex_t bbot; -+ struct au_rdu_arg arg = { -+ .ctx = { -+ .actor = au_rdu_fill -+ } -+ }; -+ struct dentry *dentry; -+ struct inode *inode; -+ struct file *h_file; -+ struct au_rdu_cookie *cookie = &rdu->cookie; -+ -+ /* VERIFY_WRITE */ -+ err = !access_ok(rdu->ent.e, rdu->sz); -+ if (unlikely(err)) { -+ err = -EFAULT; -+ AuTraceErr(err); -+ goto out; -+ } -+ rdu->rent = 0; -+ rdu->tail = rdu->ent; -+ rdu->full = 0; -+ arg.rdu = rdu; -+ arg.ent = rdu->ent; -+ arg.end = arg.ent.ul; -+ arg.end += rdu->sz; -+ -+ err = -ENOTDIR; -+ if (unlikely(!file->f_op->iterate && !file->f_op->iterate_shared)) -+ goto out; -+ -+ err = security_file_permission(file, MAY_READ); -+ AuTraceErr(err); -+ if (unlikely(err)) -+ goto out; -+ -+ dentry = file->f_path.dentry; -+ inode = d_inode(dentry); -+ inode_lock_shared(inode); -+ -+ arg.sb = inode->i_sb; -+ err = si_read_lock(arg.sb, AuLock_FLUSH | AuLock_NOPLM); -+ if (unlikely(err)) -+ goto out_mtx; -+ err = au_alive_dir(dentry); -+ if (unlikely(err)) -+ goto out_si; -+ /* todo: reval? */ -+ fi_read_lock(file); -+ -+ err = -EAGAIN; -+ if (unlikely(au_ftest_rdu(cookie->flags, CONT) -+ && cookie->generation != au_figen(file))) -+ goto out_unlock; -+ -+ err = 0; -+ if (!rdu->blk) { -+ rdu->blk = au_sbi(arg.sb)->si_rdblk; -+ if (!rdu->blk) -+ rdu->blk = au_dir_size(file, /*dentry*/NULL); -+ } -+ bbot = au_fbtop(file); -+ if (cookie->bindex < bbot) -+ cookie->bindex = bbot; -+ bbot = au_fbbot_dir(file); -+ /* AuDbg("b%d, b%d\n", cookie->bindex, bbot); */ -+ for (; !err && cookie->bindex <= bbot; -+ cookie->bindex++, cookie->h_pos = 0) { -+ h_file = au_hf_dir(file, cookie->bindex); -+ if (!h_file) -+ continue; -+ -+ au_fclr_rdu(cookie->flags, FULL); -+ err = au_rdu_do(h_file, &arg); -+ AuTraceErr(err); -+ if (unlikely(au_ftest_rdu(cookie->flags, FULL) || err)) -+ break; -+ } -+ AuDbg("rent %llu\n", rdu->rent); -+ -+ if (!err && !au_ftest_rdu(cookie->flags, CONT)) { -+ rdu->shwh = !!au_opt_test(au_sbi(arg.sb)->si_mntflags, SHWH); -+ au_fset_rdu(cookie->flags, CONT); -+ cookie->generation = au_figen(file); -+ } -+ -+ ii_read_lock_child(inode); -+ fsstack_copy_attr_atime(inode, au_h_iptr(inode, au_ibtop(inode))); -+ ii_read_unlock(inode); -+ -+out_unlock: -+ fi_read_unlock(file); -+out_si: -+ si_read_unlock(arg.sb); -+out_mtx: -+ inode_unlock_shared(inode); -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+static int au_rdu_ino(struct file *file, struct aufs_rdu *rdu) -+{ -+ int err; -+ ino_t ino; -+ unsigned long long nent; -+ union au_rdu_ent_ul *u; -+ struct au_rdu_ent ent; -+ struct super_block *sb; -+ -+ err = 0; -+ nent = rdu->nent; -+ u = &rdu->ent; -+ sb = file->f_path.dentry->d_sb; -+ si_read_lock(sb, AuLock_FLUSH); -+ while (nent-- > 0) { -+ /* unnecessary to support mmap_sem since this is a dir */ -+ err = copy_from_user(&ent, u->e, sizeof(ent)); -+ if (!err) -+ /* VERIFY_WRITE */ -+ err = !access_ok(&u->e->ino, sizeof(ino)); -+ if (unlikely(err)) { -+ err = -EFAULT; -+ AuTraceErr(err); -+ break; -+ } -+ -+ /* AuDbg("b%d, i%llu\n", ent.bindex, ent.ino); */ -+ if (!ent.wh) -+ err = au_ino(sb, ent.bindex, ent.ino, ent.type, &ino); -+ else -+ err = au_wh_ino(sb, ent.bindex, ent.ino, ent.type, -+ &ino); -+ if (unlikely(err)) { -+ AuTraceErr(err); -+ break; -+ } -+ -+ err = __put_user(ino, &u->e->ino); -+ if (unlikely(err)) { -+ err = -EFAULT; -+ AuTraceErr(err); -+ break; -+ } -+ u->ul += au_rdu_len(ent.nlen); -+ } -+ si_read_unlock(sb); -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int au_rdu_verify(struct aufs_rdu *rdu) -+{ -+ AuDbg("rdu{%llu, %p, %u | %u | %llu, %u, %u | " -+ "%llu, b%d, 0x%x, g%u}\n", -+ rdu->sz, rdu->ent.e, rdu->verify[AufsCtlRduV_SZ], -+ rdu->blk, -+ rdu->rent, rdu->shwh, rdu->full, -+ rdu->cookie.h_pos, rdu->cookie.bindex, rdu->cookie.flags, -+ rdu->cookie.generation); -+ -+ if (rdu->verify[AufsCtlRduV_SZ] == sizeof(*rdu)) -+ return 0; -+ -+ AuDbg("%u:%u\n", -+ rdu->verify[AufsCtlRduV_SZ], (unsigned int)sizeof(*rdu)); -+ return -EINVAL; -+} -+ -+long au_rdu_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -+{ -+ long err, e; -+ struct aufs_rdu rdu; -+ void __user *p = (void __user *)arg; -+ -+ err = copy_from_user(&rdu, p, sizeof(rdu)); -+ if (unlikely(err)) { -+ err = -EFAULT; -+ AuTraceErr(err); -+ goto out; -+ } -+ err = au_rdu_verify(&rdu); -+ if (unlikely(err)) -+ goto out; -+ -+ switch (cmd) { -+ case AUFS_CTL_RDU: -+ err = au_rdu(file, &rdu); -+ if (unlikely(err)) -+ break; -+ -+ e = copy_to_user(p, &rdu, sizeof(rdu)); -+ if (unlikely(e)) { -+ err = -EFAULT; -+ AuTraceErr(err); -+ } -+ break; -+ case AUFS_CTL_RDU_INO: -+ err = au_rdu_ino(file, &rdu); -+ break; -+ -+ default: -+ /* err = -ENOTTY; */ -+ err = -EINVAL; -+ } -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+#ifdef CONFIG_COMPAT -+long au_rdu_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -+{ -+ long err, e; -+ struct aufs_rdu rdu; -+ void __user *p = compat_ptr(arg); -+ -+ /* todo: get_user()? */ -+ err = copy_from_user(&rdu, p, sizeof(rdu)); -+ if (unlikely(err)) { -+ err = -EFAULT; -+ AuTraceErr(err); -+ goto out; -+ } -+ rdu.ent.e = compat_ptr(rdu.ent.ul); -+ err = au_rdu_verify(&rdu); -+ if (unlikely(err)) -+ goto out; -+ -+ switch (cmd) { -+ case AUFS_CTL_RDU: -+ err = au_rdu(file, &rdu); -+ if (unlikely(err)) -+ break; -+ -+ rdu.ent.ul = ptr_to_compat(rdu.ent.e); -+ rdu.tail.ul = ptr_to_compat(rdu.tail.e); -+ e = copy_to_user(p, &rdu, sizeof(rdu)); -+ if (unlikely(e)) { -+ err = -EFAULT; -+ AuTraceErr(err); -+ } -+ break; -+ case AUFS_CTL_RDU_INO: -+ err = au_rdu_ino(file, &rdu); -+ break; -+ -+ default: -+ /* err = -ENOTTY; */ -+ err = -EINVAL; -+ } -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+#endif -diff -Nurp linux-5.10-rc6/fs/aufs/rwsem.h linux-5.10-rc6.aufs/fs/aufs/rwsem.h ---- linux-5.10-rc6/fs/aufs/rwsem.h 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/rwsem.h 2020-12-02 21:19:51.883036833 +0200 -@@ -0,0 +1,60 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * simple read-write semaphore wrappers -+ */ -+ -+#ifndef __AUFS_RWSEM_H__ -+#define __AUFS_RWSEM_H__ -+ -+#ifdef __KERNEL__ -+ -+#include "debug.h" -+ -+/* in the future, the name 'au_rwsem' will be totally gone */ -+#define au_rwsem rw_semaphore -+ -+/* to debug easier, do not make them inlined functions */ -+#define AuRwMustNoWaiters(rw) AuDebugOn(rwsem_is_contended(rw)) -+/* rwsem_is_locked() is unusable */ -+#define AuRwMustReadLock(rw) AuDebugOn(!lockdep_recursing(current) \ -+ && debug_locks \ -+ && !lockdep_is_held_type(rw, 1)) -+#define AuRwMustWriteLock(rw) AuDebugOn(!lockdep_recursing(current) \ -+ && debug_locks \ -+ && !lockdep_is_held_type(rw, 0)) -+#define AuRwMustAnyLock(rw) AuDebugOn(!lockdep_recursing(current) \ -+ && debug_locks \ -+ && !lockdep_is_held(rw)) -+#define AuRwDestroy(rw) AuDebugOn(!lockdep_recursing(current) \ -+ && debug_locks \ -+ && lockdep_is_held(rw)) -+ -+#define au_rw_init(rw) init_rwsem(rw) -+ -+#define au_rw_init_wlock(rw) do { \ -+ au_rw_init(rw); \ -+ down_write(rw); \ -+ } while (0) -+ -+#define au_rw_init_wlock_nested(rw, lsc) do { \ -+ au_rw_init(rw); \ -+ down_write_nested(rw, lsc); \ -+ } while (0) -+ -+#define au_rw_read_lock(rw) down_read(rw) -+#define au_rw_read_lock_nested(rw, lsc) down_read_nested(rw, lsc) -+#define au_rw_read_unlock(rw) up_read(rw) -+#define au_rw_dgrade_lock(rw) downgrade_write(rw) -+#define au_rw_write_lock(rw) down_write(rw) -+#define au_rw_write_lock_nested(rw, lsc) down_write_nested(rw, lsc) -+#define au_rw_write_unlock(rw) up_write(rw) -+/* why is not _nested version defined? */ -+#define au_rw_read_trylock(rw) down_read_trylock(rw) -+#define au_rw_write_trylock(rw) down_write_trylock(rw) -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_RWSEM_H__ */ -diff -Nurp linux-5.10-rc6/fs/aufs/sbinfo.c linux-5.10-rc6.aufs/fs/aufs/sbinfo.c ---- linux-5.10-rc6/fs/aufs/sbinfo.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/sbinfo.c 2020-12-02 21:19:51.883036833 +0200 -@@ -0,0 +1,301 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * superblock private data -+ */ -+ -+#include -+#include "aufs.h" -+ -+/* -+ * they are necessary regardless sysfs is disabled. -+ */ -+void au_si_free(struct kobject *kobj) -+{ -+ int i; -+ struct au_sbinfo *sbinfo; -+ char *locked __maybe_unused; /* debug only */ -+ -+ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj); -+ for (i = 0; i < AuPlink_NHASH; i++) -+ AuDebugOn(!hlist_bl_empty(sbinfo->si_plink + i)); -+ AuDebugOn(atomic_read(&sbinfo->si_nowait.nw_len)); -+ -+ AuLCntZero(au_lcnt_read(&sbinfo->si_ninodes, /*do_rev*/0)); -+ au_lcnt_fin(&sbinfo->si_ninodes, /*do_sync*/0); -+ AuLCntZero(au_lcnt_read(&sbinfo->si_nfiles, /*do_rev*/0)); -+ au_lcnt_fin(&sbinfo->si_nfiles, /*do_sync*/0); -+ -+ dbgaufs_si_fin(sbinfo); -+ au_rw_write_lock(&sbinfo->si_rwsem); -+ au_br_free(sbinfo); -+ au_rw_write_unlock(&sbinfo->si_rwsem); -+ -+ au_kfree_try_rcu(sbinfo->si_branch); -+ mutex_destroy(&sbinfo->si_xib_mtx); -+ AuRwDestroy(&sbinfo->si_rwsem); -+ -+ au_lcnt_wait_for_fin(&sbinfo->si_ninodes); -+ /* si_nfiles is waited too */ -+ au_kfree_rcu(sbinfo); -+} -+ -+int au_si_alloc(struct super_block *sb) -+{ -+ int err, i; -+ struct au_sbinfo *sbinfo; -+ -+ err = -ENOMEM; -+ sbinfo = kzalloc(sizeof(*sbinfo), GFP_NOFS); -+ if (unlikely(!sbinfo)) -+ goto out; -+ -+ /* will be reallocated separately */ -+ sbinfo->si_branch = kzalloc(sizeof(*sbinfo->si_branch), GFP_NOFS); -+ if (unlikely(!sbinfo->si_branch)) -+ goto out_sbinfo; -+ -+ err = sysaufs_si_init(sbinfo); -+ if (!err) { -+ dbgaufs_si_null(sbinfo); -+ err = dbgaufs_si_init(sbinfo); -+ if (unlikely(err)) -+ kobject_put(&sbinfo->si_kobj); -+ } -+ if (unlikely(err)) -+ goto out_br; -+ -+ au_nwt_init(&sbinfo->si_nowait); -+ au_rw_init_wlock(&sbinfo->si_rwsem); -+ -+ au_lcnt_init(&sbinfo->si_ninodes, /*release*/NULL); -+ au_lcnt_init(&sbinfo->si_nfiles, /*release*/NULL); -+ -+ sbinfo->si_bbot = -1; -+ sbinfo->si_last_br_id = AUFS_BRANCH_MAX / 2; -+ -+ sbinfo->si_wbr_copyup = AuWbrCopyup_Def; -+ sbinfo->si_wbr_create = AuWbrCreate_Def; -+ sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + sbinfo->si_wbr_copyup; -+ sbinfo->si_wbr_create_ops = au_wbr_create_ops + sbinfo->si_wbr_create; -+ -+ au_fhsm_init(sbinfo); -+ -+ sbinfo->si_mntflags = au_opts_plink(AuOpt_Def); -+ -+ sbinfo->si_xino_jiffy = jiffies; -+ sbinfo->si_xino_expire -+ = msecs_to_jiffies(AUFS_XINO_DEF_SEC * MSEC_PER_SEC); -+ mutex_init(&sbinfo->si_xib_mtx); -+ /* leave si_xib_last_pindex and si_xib_next_bit */ -+ -+ INIT_HLIST_BL_HEAD(&sbinfo->si_aopen); -+ -+ sbinfo->si_rdcache = msecs_to_jiffies(AUFS_RDCACHE_DEF * MSEC_PER_SEC); -+ sbinfo->si_rdblk = AUFS_RDBLK_DEF; -+ sbinfo->si_rdhash = AUFS_RDHASH_DEF; -+ sbinfo->si_dirwh = AUFS_DIRWH_DEF; -+ -+ for (i = 0; i < AuPlink_NHASH; i++) -+ INIT_HLIST_BL_HEAD(sbinfo->si_plink + i); -+ init_waitqueue_head(&sbinfo->si_plink_wq); -+ spin_lock_init(&sbinfo->si_plink_maint_lock); -+ -+ INIT_HLIST_BL_HEAD(&sbinfo->si_files); -+ -+ /* with getattr by default */ -+ sbinfo->si_iop_array = aufs_iop; -+ -+ /* leave other members for sysaufs and si_mnt. */ -+ sbinfo->si_sb = sb; -+ sb->s_fs_info = sbinfo; -+ si_pid_set(sb); -+ return 0; /* success */ -+ -+out_br: -+ au_kfree_try_rcu(sbinfo->si_branch); -+out_sbinfo: -+ au_kfree_rcu(sbinfo); -+out: -+ return err; -+} -+ -+int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr, int may_shrink) -+{ -+ int err, sz; -+ struct au_branch **brp; -+ -+ AuRwMustWriteLock(&sbinfo->si_rwsem); -+ -+ err = -ENOMEM; -+ sz = sizeof(*brp) * (sbinfo->si_bbot + 1); -+ if (unlikely(!sz)) -+ sz = sizeof(*brp); -+ brp = au_kzrealloc(sbinfo->si_branch, sz, sizeof(*brp) * nbr, GFP_NOFS, -+ may_shrink); -+ if (brp) { -+ sbinfo->si_branch = brp; -+ err = 0; -+ } -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+unsigned int au_sigen_inc(struct super_block *sb) -+{ -+ unsigned int gen; -+ struct inode *inode; -+ -+ SiMustWriteLock(sb); -+ -+ gen = ++au_sbi(sb)->si_generation; -+ au_update_digen(sb->s_root); -+ inode = d_inode(sb->s_root); -+ au_update_iigen(inode, /*half*/0); -+ inode_inc_iversion(inode); -+ return gen; -+} -+ -+aufs_bindex_t au_new_br_id(struct super_block *sb) -+{ -+ aufs_bindex_t br_id; -+ int i; -+ struct au_sbinfo *sbinfo; -+ -+ SiMustWriteLock(sb); -+ -+ sbinfo = au_sbi(sb); -+ for (i = 0; i <= AUFS_BRANCH_MAX; i++) { -+ br_id = ++sbinfo->si_last_br_id; -+ AuDebugOn(br_id < 0); -+ if (br_id && au_br_index(sb, br_id) < 0) -+ return br_id; -+ } -+ -+ return -1; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* it is ok that new 'nwt' tasks are appended while we are sleeping */ -+int si_read_lock(struct super_block *sb, int flags) -+{ -+ int err; -+ -+ err = 0; -+ if (au_ftest_lock(flags, FLUSH)) -+ au_nwt_flush(&au_sbi(sb)->si_nowait); -+ -+ si_noflush_read_lock(sb); -+ err = au_plink_maint(sb, flags); -+ if (unlikely(err)) -+ si_read_unlock(sb); -+ -+ return err; -+} -+ -+int si_write_lock(struct super_block *sb, int flags) -+{ -+ int err; -+ -+ if (au_ftest_lock(flags, FLUSH)) -+ au_nwt_flush(&au_sbi(sb)->si_nowait); -+ -+ si_noflush_write_lock(sb); -+ err = au_plink_maint(sb, flags); -+ if (unlikely(err)) -+ si_write_unlock(sb); -+ -+ return err; -+} -+ -+/* dentry and super_block lock. call at entry point */ -+int aufs_read_lock(struct dentry *dentry, int flags) -+{ -+ int err; -+ struct super_block *sb; -+ -+ sb = dentry->d_sb; -+ err = si_read_lock(sb, flags); -+ if (unlikely(err)) -+ goto out; -+ -+ if (au_ftest_lock(flags, DW)) -+ di_write_lock_child(dentry); -+ else -+ di_read_lock_child(dentry, flags); -+ -+ if (au_ftest_lock(flags, GEN)) { -+ err = au_digen_test(dentry, au_sigen(sb)); -+ if (!au_opt_test(au_mntflags(sb), UDBA_NONE)) -+ AuDebugOn(!err && au_dbrange_test(dentry)); -+ else if (!err) -+ err = au_dbrange_test(dentry); -+ if (unlikely(err)) -+ aufs_read_unlock(dentry, flags); -+ } -+ -+out: -+ return err; -+} -+ -+void aufs_read_unlock(struct dentry *dentry, int flags) -+{ -+ if (au_ftest_lock(flags, DW)) -+ di_write_unlock(dentry); -+ else -+ di_read_unlock(dentry, flags); -+ si_read_unlock(dentry->d_sb); -+} -+ -+void aufs_write_lock(struct dentry *dentry) -+{ -+ si_write_lock(dentry->d_sb, AuLock_FLUSH | AuLock_NOPLMW); -+ di_write_lock_child(dentry); -+} -+ -+void aufs_write_unlock(struct dentry *dentry) -+{ -+ di_write_unlock(dentry); -+ si_write_unlock(dentry->d_sb); -+} -+ -+int aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags) -+{ -+ int err; -+ unsigned int sigen; -+ struct super_block *sb; -+ -+ sb = d1->d_sb; -+ err = si_read_lock(sb, flags); -+ if (unlikely(err)) -+ goto out; -+ -+ di_write_lock2_child(d1, d2, au_ftest_lock(flags, DIRS)); -+ -+ if (au_ftest_lock(flags, GEN)) { -+ sigen = au_sigen(sb); -+ err = au_digen_test(d1, sigen); -+ AuDebugOn(!err && au_dbrange_test(d1)); -+ if (!err) { -+ err = au_digen_test(d2, sigen); -+ AuDebugOn(!err && au_dbrange_test(d2)); -+ } -+ if (unlikely(err)) -+ aufs_read_and_write_unlock2(d1, d2); -+ } -+ -+out: -+ return err; -+} -+ -+void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2) -+{ -+ di_write_unlock2(d1, d2); -+ si_read_unlock(d1->d_sb); -+} -diff -Nurp linux-5.10-rc6/fs/aufs/super.c linux-5.10-rc6.aufs/fs/aufs/super.c ---- linux-5.10-rc6/fs/aufs/super.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/super.c 2020-12-02 21:19:51.883036833 +0200 -@@ -0,0 +1,1034 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * mount and super_block operations -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include "aufs.h" -+ -+/* -+ * super_operations -+ */ -+static struct inode *aufs_alloc_inode(struct super_block *sb __maybe_unused) -+{ -+ struct au_icntnr *c; -+ -+ c = au_cache_alloc_icntnr(); -+ if (c) { -+ au_icntnr_init(c); -+ inode_set_iversion(&c->vfs_inode, 1); /* sigen(sb); */ -+ c->iinfo.ii_hinode = NULL; -+ return &c->vfs_inode; -+ } -+ return NULL; -+} -+ -+static void aufs_destroy_inode(struct inode *inode) -+{ -+ if (!au_is_bad_inode(inode)) -+ au_iinfo_fin(inode); -+} -+ -+static void aufs_free_inode(struct inode *inode) -+{ -+ au_cache_free_icntnr(container_of(inode, struct au_icntnr, vfs_inode)); -+} -+ -+struct inode *au_iget_locked(struct super_block *sb, ino_t ino) -+{ -+ struct inode *inode; -+ int err; -+ -+ inode = iget_locked(sb, ino); -+ if (unlikely(!inode)) { -+ inode = ERR_PTR(-ENOMEM); -+ goto out; -+ } -+ if (!(inode->i_state & I_NEW)) -+ goto out; -+ -+ err = au_xigen_new(inode); -+ if (!err) -+ err = au_iinfo_init(inode); -+ if (!err) -+ inode_inc_iversion(inode); -+ else { -+ iget_failed(inode); -+ inode = ERR_PTR(err); -+ } -+ -+out: -+ /* never return NULL */ -+ AuDebugOn(!inode); -+ AuTraceErrPtr(inode); -+ return inode; -+} -+ -+/* lock free root dinfo */ -+static int au_show_brs(struct seq_file *seq, struct super_block *sb) -+{ -+ int err; -+ aufs_bindex_t bindex, bbot; -+ struct path path; -+ struct au_hdentry *hdp; -+ struct au_branch *br; -+ au_br_perm_str_t perm; -+ -+ err = 0; -+ bbot = au_sbbot(sb); -+ bindex = 0; -+ hdp = au_hdentry(au_di(sb->s_root), bindex); -+ for (; !err && bindex <= bbot; bindex++, hdp++) { -+ br = au_sbr(sb, bindex); -+ path.mnt = au_br_mnt(br); -+ path.dentry = hdp->hd_dentry; -+ err = au_seq_path(seq, &path); -+ if (!err) { -+ au_optstr_br_perm(&perm, br->br_perm); -+ seq_printf(seq, "=%s", perm.a); -+ if (bindex != bbot) -+ seq_putc(seq, ':'); -+ } -+ } -+ if (unlikely(err || seq_has_overflowed(seq))) -+ err = -E2BIG; -+ -+ return err; -+} -+ -+static void au_gen_fmt(char *fmt, int len __maybe_unused, const char *pat, -+ const char *append) -+{ -+ char *p; -+ -+ p = fmt; -+ while (*pat != ':') -+ *p++ = *pat++; -+ *p++ = *pat++; -+ strcpy(p, append); -+ AuDebugOn(strlen(fmt) >= len); -+} -+ -+static void au_show_wbr_create(struct seq_file *m, int v, -+ struct au_sbinfo *sbinfo) -+{ -+ const char *pat; -+ char fmt[32]; -+ struct au_wbr_mfs *mfs; -+ -+ AuRwMustAnyLock(&sbinfo->si_rwsem); -+ -+ seq_puts(m, ",create="); -+ pat = au_optstr_wbr_create(v); -+ mfs = &sbinfo->si_wbr_mfs; -+ switch (v) { -+ case AuWbrCreate_TDP: -+ case AuWbrCreate_RR: -+ case AuWbrCreate_MFS: -+ case AuWbrCreate_PMFS: -+ seq_puts(m, pat); -+ break; -+ case AuWbrCreate_MFSRR: -+ case AuWbrCreate_TDMFS: -+ case AuWbrCreate_PMFSRR: -+ au_gen_fmt(fmt, sizeof(fmt), pat, "%llu"); -+ seq_printf(m, fmt, mfs->mfsrr_watermark); -+ break; -+ case AuWbrCreate_MFSV: -+ case AuWbrCreate_PMFSV: -+ au_gen_fmt(fmt, sizeof(fmt), pat, "%lu"); -+ seq_printf(m, fmt, -+ jiffies_to_msecs(mfs->mfs_expire) -+ / MSEC_PER_SEC); -+ break; -+ case AuWbrCreate_MFSRRV: -+ case AuWbrCreate_TDMFSV: -+ case AuWbrCreate_PMFSRRV: -+ au_gen_fmt(fmt, sizeof(fmt), pat, "%llu:%lu"); -+ seq_printf(m, fmt, mfs->mfsrr_watermark, -+ jiffies_to_msecs(mfs->mfs_expire) / MSEC_PER_SEC); -+ break; -+ default: -+ BUG(); -+ } -+} -+ -+static int au_show_xino(struct seq_file *seq, struct super_block *sb) -+{ -+#ifdef CONFIG_SYSFS -+ return 0; -+#else -+ int err; -+ const int len = sizeof(AUFS_XINO_FNAME) - 1; -+ aufs_bindex_t bindex, brid; -+ struct qstr *name; -+ struct file *f; -+ struct dentry *d, *h_root; -+ struct au_branch *br; -+ -+ AuRwMustAnyLock(&sbinfo->si_rwsem); -+ -+ err = 0; -+ f = au_sbi(sb)->si_xib; -+ if (!f) -+ goto out; -+ -+ /* stop printing the default xino path on the first writable branch */ -+ h_root = NULL; -+ bindex = au_xi_root(sb, f->f_path.dentry); -+ if (bindex >= 0) { -+ br = au_sbr_sb(sb, bindex); -+ h_root = au_br_dentry(br); -+ } -+ -+ d = f->f_path.dentry; -+ name = &d->d_name; -+ /* safe ->d_parent because the file is unlinked */ -+ if (d->d_parent == h_root -+ && name->len == len -+ && !memcmp(name->name, AUFS_XINO_FNAME, len)) -+ goto out; -+ -+ seq_puts(seq, ",xino="); -+ err = au_xino_path(seq, f); -+ -+out: -+ return err; -+#endif -+} -+ -+/* seq_file will re-call me in case of too long string */ -+static int aufs_show_options(struct seq_file *m, struct dentry *dentry) -+{ -+ int err; -+ unsigned int mnt_flags, v; -+ struct super_block *sb; -+ struct au_sbinfo *sbinfo; -+ -+#define AuBool(name, str) do { \ -+ v = au_opt_test(mnt_flags, name); \ -+ if (v != au_opt_test(AuOpt_Def, name)) \ -+ seq_printf(m, ",%s" #str, v ? "" : "no"); \ -+} while (0) -+ -+#define AuStr(name, str) do { \ -+ v = mnt_flags & AuOptMask_##name; \ -+ if (v != (AuOpt_Def & AuOptMask_##name)) \ -+ seq_printf(m, "," #str "=%s", au_optstr_##str(v)); \ -+} while (0) -+ -+#define AuUInt(name, str, val) do { \ -+ if (val != AUFS_##name##_DEF) \ -+ seq_printf(m, "," #str "=%u", val); \ -+} while (0) -+ -+ sb = dentry->d_sb; -+ if (sb->s_flags & SB_POSIXACL) -+ seq_puts(m, ",acl"); -+#if 0 /* reserved for future use */ -+ if (sb->s_flags & SB_I_VERSION) -+ seq_puts(m, ",i_version"); -+#endif -+ -+ /* lock free root dinfo */ -+ si_noflush_read_lock(sb); -+ sbinfo = au_sbi(sb); -+ seq_printf(m, ",si=%lx", sysaufs_si_id(sbinfo)); -+ -+ mnt_flags = au_mntflags(sb); -+ if (au_opt_test(mnt_flags, XINO)) { -+ err = au_show_xino(m, sb); -+ if (unlikely(err)) -+ goto out; -+ } else -+ seq_puts(m, ",noxino"); -+ -+ AuBool(TRUNC_XINO, trunc_xino); -+ AuStr(UDBA, udba); -+ AuBool(SHWH, shwh); -+ AuBool(PLINK, plink); -+ AuBool(DIO, dio); -+ AuBool(DIRPERM1, dirperm1); -+ -+ v = sbinfo->si_wbr_create; -+ if (v != AuWbrCreate_Def) -+ au_show_wbr_create(m, v, sbinfo); -+ -+ v = sbinfo->si_wbr_copyup; -+ if (v != AuWbrCopyup_Def) -+ seq_printf(m, ",cpup=%s", au_optstr_wbr_copyup(v)); -+ -+ v = au_opt_test(mnt_flags, ALWAYS_DIROPQ); -+ if (v != au_opt_test(AuOpt_Def, ALWAYS_DIROPQ)) -+ seq_printf(m, ",diropq=%c", v ? 'a' : 'w'); -+ -+ AuUInt(DIRWH, dirwh, sbinfo->si_dirwh); -+ -+ v = jiffies_to_msecs(sbinfo->si_rdcache) / MSEC_PER_SEC; -+ AuUInt(RDCACHE, rdcache, v); -+ -+ AuUInt(RDBLK, rdblk, sbinfo->si_rdblk); -+ AuUInt(RDHASH, rdhash, sbinfo->si_rdhash); -+ -+ au_fhsm_show(m, sbinfo); -+ -+ AuBool(DIRREN, dirren); -+ AuBool(SUM, sum); -+ /* AuBool(SUM_W, wsum); */ -+ AuBool(WARN_PERM, warn_perm); -+ AuBool(VERBOSE, verbose); -+ -+out: -+ /* be sure to print "br:" last */ -+ if (!sysaufs_brs) { -+ seq_puts(m, ",br:"); -+ au_show_brs(m, sb); -+ } -+ si_read_unlock(sb); -+ return 0; -+ -+#undef AuBool -+#undef AuStr -+#undef AuUInt -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* sum mode which returns the summation for statfs(2) */ -+ -+static u64 au_add_till_max(u64 a, u64 b) -+{ -+ u64 old; -+ -+ old = a; -+ a += b; -+ if (old <= a) -+ return a; -+ return ULLONG_MAX; -+} -+ -+static u64 au_mul_till_max(u64 a, long mul) -+{ -+ u64 old; -+ -+ old = a; -+ a *= mul; -+ if (old <= a) -+ return a; -+ return ULLONG_MAX; -+} -+ -+static int au_statfs_sum(struct super_block *sb, struct kstatfs *buf) -+{ -+ int err; -+ long bsize, factor; -+ u64 blocks, bfree, bavail, files, ffree; -+ aufs_bindex_t bbot, bindex, i; -+ unsigned char shared; -+ struct path h_path; -+ struct super_block *h_sb; -+ -+ err = 0; -+ bsize = LONG_MAX; -+ files = 0; -+ ffree = 0; -+ blocks = 0; -+ bfree = 0; -+ bavail = 0; -+ bbot = au_sbbot(sb); -+ for (bindex = 0; bindex <= bbot; bindex++) { -+ h_path.mnt = au_sbr_mnt(sb, bindex); -+ h_sb = h_path.mnt->mnt_sb; -+ shared = 0; -+ for (i = 0; !shared && i < bindex; i++) -+ shared = (au_sbr_sb(sb, i) == h_sb); -+ if (shared) -+ continue; -+ -+ /* sb->s_root for NFS is unreliable */ -+ h_path.dentry = h_path.mnt->mnt_root; -+ err = vfs_statfs(&h_path, buf); -+ if (unlikely(err)) -+ goto out; -+ -+ if (bsize > buf->f_bsize) { -+ /* -+ * we will reduce bsize, so we have to expand blocks -+ * etc. to match them again -+ */ -+ factor = (bsize / buf->f_bsize); -+ blocks = au_mul_till_max(blocks, factor); -+ bfree = au_mul_till_max(bfree, factor); -+ bavail = au_mul_till_max(bavail, factor); -+ bsize = buf->f_bsize; -+ } -+ -+ factor = (buf->f_bsize / bsize); -+ blocks = au_add_till_max(blocks, -+ au_mul_till_max(buf->f_blocks, factor)); -+ bfree = au_add_till_max(bfree, -+ au_mul_till_max(buf->f_bfree, factor)); -+ bavail = au_add_till_max(bavail, -+ au_mul_till_max(buf->f_bavail, factor)); -+ files = au_add_till_max(files, buf->f_files); -+ ffree = au_add_till_max(ffree, buf->f_ffree); -+ } -+ -+ buf->f_bsize = bsize; -+ buf->f_blocks = blocks; -+ buf->f_bfree = bfree; -+ buf->f_bavail = bavail; -+ buf->f_files = files; -+ buf->f_ffree = ffree; -+ buf->f_frsize = 0; -+ -+out: -+ return err; -+} -+ -+static int aufs_statfs(struct dentry *dentry, struct kstatfs *buf) -+{ -+ int err; -+ struct path h_path; -+ struct super_block *sb; -+ -+ /* lock free root dinfo */ -+ sb = dentry->d_sb; -+ si_noflush_read_lock(sb); -+ if (!au_opt_test(au_mntflags(sb), SUM)) { -+ /* sb->s_root for NFS is unreliable */ -+ h_path.mnt = au_sbr_mnt(sb, 0); -+ h_path.dentry = h_path.mnt->mnt_root; -+ err = vfs_statfs(&h_path, buf); -+ } else -+ err = au_statfs_sum(sb, buf); -+ si_read_unlock(sb); -+ -+ if (!err) { -+ buf->f_type = AUFS_SUPER_MAGIC; -+ buf->f_namelen = AUFS_MAX_NAMELEN; -+ memset(&buf->f_fsid, 0, sizeof(buf->f_fsid)); -+ } -+ /* buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1; */ -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int aufs_sync_fs(struct super_block *sb, int wait) -+{ -+ int err, e; -+ aufs_bindex_t bbot, bindex; -+ struct au_branch *br; -+ struct super_block *h_sb; -+ -+ err = 0; -+ si_noflush_read_lock(sb); -+ bbot = au_sbbot(sb); -+ for (bindex = 0; bindex <= bbot; bindex++) { -+ br = au_sbr(sb, bindex); -+ if (!au_br_writable(br->br_perm)) -+ continue; -+ -+ h_sb = au_sbr_sb(sb, bindex); -+ e = vfsub_sync_filesystem(h_sb, wait); -+ if (unlikely(e && !err)) -+ err = e; -+ /* go on even if an error happens */ -+ } -+ si_read_unlock(sb); -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* final actions when unmounting a file system */ -+static void aufs_put_super(struct super_block *sb) -+{ -+ struct au_sbinfo *sbinfo; -+ -+ sbinfo = au_sbi(sb); -+ if (sbinfo) -+ kobject_put(&sbinfo->si_kobj); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+void *au_array_alloc(unsigned long long *hint, au_arraycb_t cb, -+ struct super_block *sb, void *arg) -+{ -+ void *array; -+ unsigned long long n, sz; -+ -+ array = NULL; -+ n = 0; -+ if (!*hint) -+ goto out; -+ -+ if (*hint > ULLONG_MAX / sizeof(array)) { -+ array = ERR_PTR(-EMFILE); -+ pr_err("hint %llu\n", *hint); -+ goto out; -+ } -+ -+ sz = sizeof(array) * *hint; -+ array = kzalloc(sz, GFP_NOFS); -+ if (unlikely(!array)) -+ array = vzalloc(sz); -+ if (unlikely(!array)) { -+ array = ERR_PTR(-ENOMEM); -+ goto out; -+ } -+ -+ n = cb(sb, array, *hint, arg); -+ AuDebugOn(n > *hint); -+ -+out: -+ *hint = n; -+ return array; -+} -+ -+static unsigned long long au_iarray_cb(struct super_block *sb, void *a, -+ unsigned long long max __maybe_unused, -+ void *arg) -+{ -+ unsigned long long n; -+ struct inode **p, *inode; -+ struct list_head *head; -+ -+ n = 0; -+ p = a; -+ head = arg; -+ spin_lock(&sb->s_inode_list_lock); -+ list_for_each_entry(inode, head, i_sb_list) { -+ if (!au_is_bad_inode(inode) -+ && au_ii(inode)->ii_btop >= 0) { -+ spin_lock(&inode->i_lock); -+ if (atomic_read(&inode->i_count)) { -+ au_igrab(inode); -+ *p++ = inode; -+ n++; -+ AuDebugOn(n > max); -+ } -+ spin_unlock(&inode->i_lock); -+ } -+ } -+ spin_unlock(&sb->s_inode_list_lock); -+ -+ return n; -+} -+ -+struct inode **au_iarray_alloc(struct super_block *sb, unsigned long long *max) -+{ -+ struct au_sbinfo *sbi; -+ -+ sbi = au_sbi(sb); -+ *max = au_lcnt_read(&sbi->si_ninodes, /*do_rev*/1); -+ return au_array_alloc(max, au_iarray_cb, sb, &sb->s_inodes); -+} -+ -+void au_iarray_free(struct inode **a, unsigned long long max) -+{ -+ unsigned long long ull; -+ -+ for (ull = 0; ull < max; ull++) -+ iput(a[ull]); -+ kvfree(a); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * refresh dentry and inode at remount time. -+ */ -+/* todo: consolidate with simple_reval_dpath() and au_reval_for_attr() */ -+static int au_do_refresh(struct dentry *dentry, unsigned int dir_flags, -+ struct dentry *parent) -+{ -+ int err; -+ -+ di_write_lock_child(dentry); -+ di_read_lock_parent(parent, AuLock_IR); -+ err = au_refresh_dentry(dentry, parent); -+ if (!err && dir_flags) -+ au_hn_reset(d_inode(dentry), dir_flags); -+ di_read_unlock(parent, AuLock_IR); -+ di_write_unlock(dentry); -+ -+ return err; -+} -+ -+static int au_do_refresh_d(struct dentry *dentry, unsigned int sigen, -+ struct au_sbinfo *sbinfo, -+ const unsigned int dir_flags, unsigned int do_idop) -+{ -+ int err; -+ struct dentry *parent; -+ -+ err = 0; -+ parent = dget_parent(dentry); -+ if (!au_digen_test(parent, sigen) && au_digen_test(dentry, sigen)) { -+ if (d_really_is_positive(dentry)) { -+ if (!d_is_dir(dentry)) -+ err = au_do_refresh(dentry, /*dir_flags*/0, -+ parent); -+ else { -+ err = au_do_refresh(dentry, dir_flags, parent); -+ if (unlikely(err)) -+ au_fset_si(sbinfo, FAILED_REFRESH_DIR); -+ } -+ } else -+ err = au_do_refresh(dentry, /*dir_flags*/0, parent); -+ AuDbgDentry(dentry); -+ } -+ dput(parent); -+ -+ if (!err) { -+ if (do_idop) -+ au_refresh_dop(dentry, /*force_reval*/0); -+ } else -+ au_refresh_dop(dentry, /*force_reval*/1); -+ -+ AuTraceErr(err); -+ return err; -+} -+ -+static int au_refresh_d(struct super_block *sb, unsigned int do_idop) -+{ -+ int err, i, j, ndentry, e; -+ unsigned int sigen; -+ struct au_dcsub_pages dpages; -+ struct au_dpage *dpage; -+ struct dentry **dentries, *d; -+ struct au_sbinfo *sbinfo; -+ struct dentry *root = sb->s_root; -+ const unsigned int dir_flags = au_hi_flags(d_inode(root), /*isdir*/1); -+ -+ if (do_idop) -+ au_refresh_dop(root, /*force_reval*/0); -+ -+ err = au_dpages_init(&dpages, GFP_NOFS); -+ if (unlikely(err)) -+ goto out; -+ err = au_dcsub_pages(&dpages, root, NULL, NULL); -+ if (unlikely(err)) -+ goto out_dpages; -+ -+ sigen = au_sigen(sb); -+ sbinfo = au_sbi(sb); -+ for (i = 0; i < dpages.ndpage; i++) { -+ dpage = dpages.dpages + i; -+ dentries = dpage->dentries; -+ ndentry = dpage->ndentry; -+ for (j = 0; j < ndentry; j++) { -+ d = dentries[j]; -+ e = au_do_refresh_d(d, sigen, sbinfo, dir_flags, -+ do_idop); -+ if (unlikely(e && !err)) -+ err = e; -+ /* go on even err */ -+ } -+ } -+ -+out_dpages: -+ au_dpages_free(&dpages); -+out: -+ return err; -+} -+ -+static int au_refresh_i(struct super_block *sb, unsigned int do_idop) -+{ -+ int err, e; -+ unsigned int sigen; -+ unsigned long long max, ull; -+ struct inode *inode, **array; -+ -+ array = au_iarray_alloc(sb, &max); -+ err = PTR_ERR(array); -+ if (IS_ERR(array)) -+ goto out; -+ -+ err = 0; -+ sigen = au_sigen(sb); -+ for (ull = 0; ull < max; ull++) { -+ inode = array[ull]; -+ if (unlikely(!inode)) -+ break; -+ -+ e = 0; -+ ii_write_lock_child(inode); -+ if (au_iigen(inode, NULL) != sigen) { -+ e = au_refresh_hinode_self(inode); -+ if (unlikely(e)) { -+ au_refresh_iop(inode, /*force_getattr*/1); -+ pr_err("error %d, i%lu\n", e, inode->i_ino); -+ if (!err) -+ err = e; -+ /* go on even if err */ -+ } -+ } -+ if (!e && do_idop) -+ au_refresh_iop(inode, /*force_getattr*/0); -+ ii_write_unlock(inode); -+ } -+ -+ au_iarray_free(array, max); -+ -+out: -+ return err; -+} -+ -+static void au_remount_refresh(struct super_block *sb, unsigned int do_idop) -+{ -+ int err, e; -+ unsigned int udba; -+ aufs_bindex_t bindex, bbot; -+ struct dentry *root; -+ struct inode *inode; -+ struct au_branch *br; -+ struct au_sbinfo *sbi; -+ -+ au_sigen_inc(sb); -+ sbi = au_sbi(sb); -+ au_fclr_si(sbi, FAILED_REFRESH_DIR); -+ -+ root = sb->s_root; -+ DiMustNoWaiters(root); -+ inode = d_inode(root); -+ IiMustNoWaiters(inode); -+ -+ udba = au_opt_udba(sb); -+ bbot = au_sbbot(sb); -+ for (bindex = 0; bindex <= bbot; bindex++) { -+ br = au_sbr(sb, bindex); -+ err = au_hnotify_reset_br(udba, br, br->br_perm); -+ if (unlikely(err)) -+ AuIOErr("hnotify failed on br %d, %d, ignored\n", -+ bindex, err); -+ /* go on even if err */ -+ } -+ au_hn_reset(inode, au_hi_flags(inode, /*isdir*/1)); -+ -+ if (do_idop) { -+ if (au_ftest_si(sbi, NO_DREVAL)) { -+ AuDebugOn(sb->s_d_op == &aufs_dop_noreval); -+ sb->s_d_op = &aufs_dop_noreval; -+ AuDebugOn(sbi->si_iop_array == aufs_iop_nogetattr); -+ sbi->si_iop_array = aufs_iop_nogetattr; -+ } else { -+ AuDebugOn(sb->s_d_op == &aufs_dop); -+ sb->s_d_op = &aufs_dop; -+ AuDebugOn(sbi->si_iop_array == aufs_iop); -+ sbi->si_iop_array = aufs_iop; -+ } -+ pr_info("reset to %ps and %ps\n", -+ sb->s_d_op, sbi->si_iop_array); -+ } -+ -+ di_write_unlock(root); -+ err = au_refresh_d(sb, do_idop); -+ e = au_refresh_i(sb, do_idop); -+ if (unlikely(e && !err)) -+ err = e; -+ /* aufs_write_lock() calls ..._child() */ -+ di_write_lock_child(root); -+ -+ au_cpup_attr_all(inode, /*force*/1); -+ -+ if (unlikely(err)) -+ AuIOErr("refresh failed, ignored, %d\n", err); -+} -+ -+/* stop extra interpretation of errno in mount(8), and strange error messages */ -+static int cvt_err(int err) -+{ -+ AuTraceErr(err); -+ -+ switch (err) { -+ case -ENOENT: -+ case -ENOTDIR: -+ case -EEXIST: -+ case -EIO: -+ err = -EINVAL; -+ } -+ return err; -+} -+ -+static int aufs_remount_fs(struct super_block *sb, int *flags, char *data) -+{ -+ int err, do_dx; -+ unsigned int mntflags; -+ struct au_opts opts = { -+ .opt = NULL -+ }; -+ struct dentry *root; -+ struct inode *inode; -+ struct au_sbinfo *sbinfo; -+ -+ err = 0; -+ root = sb->s_root; -+ if (!data || !*data) { -+ err = si_write_lock(sb, AuLock_FLUSH | AuLock_NOPLM); -+ if (!err) { -+ di_write_lock_child(root); -+ err = au_opts_verify(sb, *flags, /*pending*/0); -+ aufs_write_unlock(root); -+ } -+ goto out; -+ } -+ -+ err = -ENOMEM; -+ opts.opt = (void *)__get_free_page(GFP_NOFS); -+ if (unlikely(!opts.opt)) -+ goto out; -+ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt); -+ opts.flags = AuOpts_REMOUNT; -+ opts.sb_flags = *flags; -+ -+ /* parse it before aufs lock */ -+ err = au_opts_parse(sb, data, &opts); -+ if (unlikely(err)) -+ goto out_opts; -+ -+ sbinfo = au_sbi(sb); -+ inode = d_inode(root); -+ inode_lock(inode); -+ err = si_write_lock(sb, AuLock_FLUSH | AuLock_NOPLM); -+ if (unlikely(err)) -+ goto out_mtx; -+ di_write_lock_child(root); -+ -+ /* au_opts_remount() may return an error */ -+ err = au_opts_remount(sb, &opts); -+ au_opts_free(&opts); -+ -+ if (au_ftest_opts(opts.flags, REFRESH)) -+ au_remount_refresh(sb, au_ftest_opts(opts.flags, REFRESH_IDOP)); -+ -+ if (au_ftest_opts(opts.flags, REFRESH_DYAOP)) { -+ mntflags = au_mntflags(sb); -+ do_dx = !!au_opt_test(mntflags, DIO); -+ au_dy_arefresh(do_dx); -+ } -+ -+ au_fhsm_wrote_all(sb, /*force*/1); /* ?? */ -+ aufs_write_unlock(root); -+ -+out_mtx: -+ inode_unlock(inode); -+out_opts: -+ free_page((unsigned long)opts.opt); -+out: -+ err = cvt_err(err); -+ AuTraceErr(err); -+ return err; -+} -+ -+static const struct super_operations aufs_sop = { -+ .alloc_inode = aufs_alloc_inode, -+ .destroy_inode = aufs_destroy_inode, -+ .free_inode = aufs_free_inode, -+ /* always deleting, no clearing */ -+ .drop_inode = generic_delete_inode, -+ .show_options = aufs_show_options, -+ .statfs = aufs_statfs, -+ .put_super = aufs_put_super, -+ .sync_fs = aufs_sync_fs, -+ .remount_fs = aufs_remount_fs -+}; -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int alloc_root(struct super_block *sb) -+{ -+ int err; -+ struct inode *inode; -+ struct dentry *root; -+ -+ err = -ENOMEM; -+ inode = au_iget_locked(sb, AUFS_ROOT_INO); -+ err = PTR_ERR(inode); -+ if (IS_ERR(inode)) -+ goto out; -+ -+ inode->i_op = aufs_iop + AuIop_DIR; /* with getattr by default */ -+ inode->i_fop = &aufs_dir_fop; -+ inode->i_mode = S_IFDIR; -+ set_nlink(inode, 2); -+ unlock_new_inode(inode); -+ -+ root = d_make_root(inode); -+ if (unlikely(!root)) -+ goto out; -+ err = PTR_ERR(root); -+ if (IS_ERR(root)) -+ goto out; -+ -+ err = au_di_init(root); -+ if (!err) { -+ sb->s_root = root; -+ return 0; /* success */ -+ } -+ dput(root); -+ -+out: -+ return err; -+} -+ -+static int aufs_fill_super(struct super_block *sb, void *raw_data, -+ int silent __maybe_unused) -+{ -+ int err; -+ struct au_opts opts = { -+ .opt = NULL -+ }; -+ struct au_sbinfo *sbinfo; -+ struct dentry *root; -+ struct inode *inode; -+ char *arg = raw_data; -+ -+ if (unlikely(!arg || !*arg)) { -+ err = -EINVAL; -+ pr_err("no arg\n"); -+ goto out; -+ } -+ -+ err = -ENOMEM; -+ opts.opt = (void *)__get_free_page(GFP_NOFS); -+ if (unlikely(!opts.opt)) -+ goto out; -+ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt); -+ opts.sb_flags = sb->s_flags; -+ -+ err = au_si_alloc(sb); -+ if (unlikely(err)) -+ goto out_opts; -+ sbinfo = au_sbi(sb); -+ -+ /* all timestamps always follow the ones on the branch */ -+ sb->s_flags |= SB_NOATIME | SB_NODIRATIME; -+ sb->s_flags |= SB_I_VERSION; /* do we really need this? */ -+ sb->s_op = &aufs_sop; -+ sb->s_d_op = &aufs_dop; -+ sb->s_magic = AUFS_SUPER_MAGIC; -+ sb->s_maxbytes = 0; -+ sb->s_stack_depth = 1; -+ au_export_init(sb); -+ au_xattr_init(sb); -+ -+ err = alloc_root(sb); -+ if (unlikely(err)) { -+ si_write_unlock(sb); -+ goto out_info; -+ } -+ root = sb->s_root; -+ inode = d_inode(root); -+ -+ /* -+ * actually we can parse options regardless aufs lock here. -+ * but at remount time, parsing must be done before aufs lock. -+ * so we follow the same rule. -+ */ -+ ii_write_lock_parent(inode); -+ aufs_write_unlock(root); -+ err = au_opts_parse(sb, arg, &opts); -+ if (unlikely(err)) -+ goto out_root; -+ -+ /* lock vfs_inode first, then aufs. */ -+ inode_lock(inode); -+ aufs_write_lock(root); -+ err = au_opts_mount(sb, &opts); -+ au_opts_free(&opts); -+ if (!err && au_ftest_si(sbinfo, NO_DREVAL)) { -+ sb->s_d_op = &aufs_dop_noreval; -+ pr_info("%ps\n", sb->s_d_op); -+ au_refresh_dop(root, /*force_reval*/0); -+ sbinfo->si_iop_array = aufs_iop_nogetattr; -+ au_refresh_iop(inode, /*force_getattr*/0); -+ } -+ aufs_write_unlock(root); -+ inode_unlock(inode); -+ if (!err) -+ goto out_opts; /* success */ -+ -+out_root: -+ dput(root); -+ sb->s_root = NULL; -+out_info: -+ kobject_put(&sbinfo->si_kobj); -+ sb->s_fs_info = NULL; -+out_opts: -+ free_page((unsigned long)opts.opt); -+out: -+ AuTraceErr(err); -+ err = cvt_err(err); -+ AuTraceErr(err); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static struct dentry *aufs_mount(struct file_system_type *fs_type, int flags, -+ const char *dev_name __maybe_unused, -+ void *raw_data) -+{ -+ struct dentry *root; -+ -+ /* all timestamps always follow the ones on the branch */ -+ /* mnt->mnt_flags |= MNT_NOATIME | MNT_NODIRATIME; */ -+ root = mount_nodev(fs_type, flags, raw_data, aufs_fill_super); -+ if (IS_ERR(root)) -+ goto out; -+ -+ au_sbilist_add(root->d_sb); -+ -+out: -+ return root; -+} -+ -+static void aufs_kill_sb(struct super_block *sb) -+{ -+ struct au_sbinfo *sbinfo; -+ -+ sbinfo = au_sbi(sb); -+ if (sbinfo) { -+ au_sbilist_del(sb); -+ aufs_write_lock(sb->s_root); -+ au_fhsm_fin(sb); -+ if (sbinfo->si_wbr_create_ops->fin) -+ sbinfo->si_wbr_create_ops->fin(sb); -+ if (au_opt_test(sbinfo->si_mntflags, UDBA_HNOTIFY)) { -+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_NONE); -+ au_remount_refresh(sb, /*do_idop*/0); -+ } -+ if (au_opt_test(sbinfo->si_mntflags, PLINK)) -+ au_plink_put(sb, /*verbose*/1); -+ au_xino_clr(sb); -+ au_dr_opt_flush(sb); -+ sbinfo->si_sb = NULL; -+ aufs_write_unlock(sb->s_root); -+ au_nwt_flush(&sbinfo->si_nowait); -+ } -+ kill_anon_super(sb); -+} -+ -+struct file_system_type aufs_fs_type = { -+ .name = AUFS_FSTYPE, -+ /* a race between rename and others */ -+ .fs_flags = FS_RENAME_DOES_D_MOVE, -+ .mount = aufs_mount, -+ .kill_sb = aufs_kill_sb, -+ /* no need to __module_get() and module_put(). */ -+ .owner = THIS_MODULE, -+}; -diff -Nurp linux-5.10-rc6/fs/aufs/super.h linux-5.10-rc6.aufs/fs/aufs/super.h ---- linux-5.10-rc6/fs/aufs/super.h 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/super.h 2020-12-02 21:19:51.883036833 +0200 -@@ -0,0 +1,576 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * super_block operations -+ */ -+ -+#ifndef __AUFS_SUPER_H__ -+#define __AUFS_SUPER_H__ -+ -+#ifdef __KERNEL__ -+ -+#include -+#include -+#include "hbl.h" -+#include "lcnt.h" -+#include "rwsem.h" -+#include "wkq.h" -+ -+/* policies to select one among multiple writable branches */ -+struct au_wbr_copyup_operations { -+ int (*copyup)(struct dentry *dentry); -+}; -+ -+#define AuWbr_DIR 1 /* target is a dir */ -+#define AuWbr_PARENT (1 << 1) /* always require a parent */ -+ -+#define au_ftest_wbr(flags, name) ((flags) & AuWbr_##name) -+#define au_fset_wbr(flags, name) { (flags) |= AuWbr_##name; } -+#define au_fclr_wbr(flags, name) { (flags) &= ~AuWbr_##name; } -+ -+struct au_wbr_create_operations { -+ int (*create)(struct dentry *dentry, unsigned int flags); -+ int (*init)(struct super_block *sb); -+ int (*fin)(struct super_block *sb); -+}; -+ -+struct au_wbr_mfs { -+ struct mutex mfs_lock; /* protect this structure */ -+ unsigned long mfs_jiffy; -+ unsigned long mfs_expire; -+ aufs_bindex_t mfs_bindex; -+ -+ unsigned long long mfsrr_bytes; -+ unsigned long long mfsrr_watermark; -+}; -+ -+#define AuPlink_NHASH 100 -+static inline int au_plink_hash(ino_t ino) -+{ -+ return ino % AuPlink_NHASH; -+} -+ -+/* File-based Hierarchical Storage Management */ -+struct au_fhsm { -+#ifdef CONFIG_AUFS_FHSM -+ /* allow only one process who can receive the notification */ -+ spinlock_t fhsm_spin; -+ pid_t fhsm_pid; -+ wait_queue_head_t fhsm_wqh; -+ atomic_t fhsm_readable; -+ -+ /* these are protected by si_rwsem */ -+ unsigned long fhsm_expire; -+ aufs_bindex_t fhsm_bottom; -+#endif -+}; -+ -+struct au_branch; -+struct au_sbinfo { -+ /* nowait tasks in the system-wide workqueue */ -+ struct au_nowait_tasks si_nowait; -+ -+ /* -+ * tried sb->s_umount, but failed due to the dependency between i_mutex. -+ * rwsem for au_sbinfo is necessary. -+ */ -+ struct au_rwsem si_rwsem; -+ -+ /* -+ * dirty approach to protect sb->sb_inodes and ->s_files (gone) from -+ * remount. -+ */ -+ au_lcnt_t si_ninodes, si_nfiles; -+ -+ /* branch management */ -+ unsigned int si_generation; -+ -+ /* see AuSi_ flags */ -+ unsigned char au_si_status; -+ -+ aufs_bindex_t si_bbot; -+ -+ /* dirty trick to keep br_id plus */ -+ unsigned int si_last_br_id : -+ sizeof(aufs_bindex_t) * BITS_PER_BYTE - 1; -+ struct au_branch **si_branch; -+ -+ /* policy to select a writable branch */ -+ unsigned char si_wbr_copyup; -+ unsigned char si_wbr_create; -+ struct au_wbr_copyup_operations *si_wbr_copyup_ops; -+ struct au_wbr_create_operations *si_wbr_create_ops; -+ -+ /* round robin */ -+ atomic_t si_wbr_rr_next; -+ -+ /* most free space */ -+ struct au_wbr_mfs si_wbr_mfs; -+ -+ /* File-based Hierarchical Storage Management */ -+ struct au_fhsm si_fhsm; -+ -+ /* mount flags */ -+ /* include/asm-ia64/siginfo.h defines a macro named si_flags */ -+ unsigned int si_mntflags; -+ -+ /* external inode number (bitmap and translation table) */ -+ vfs_readf_t si_xread; -+ vfs_writef_t si_xwrite; -+ loff_t si_ximaxent; /* max entries in a xino */ -+ -+ struct file *si_xib; -+ struct mutex si_xib_mtx; /* protect xib members */ -+ unsigned long *si_xib_buf; -+ unsigned long si_xib_last_pindex; -+ int si_xib_next_bit; -+ -+ unsigned long si_xino_jiffy; -+ unsigned long si_xino_expire; -+ /* reserved for future use */ -+ /* unsigned long long si_xib_limit; */ /* Max xib file size */ -+ -+#ifdef CONFIG_AUFS_EXPORT -+ /* i_generation */ -+ /* todo: make xigen file an array to support many inode numbers */ -+ struct file *si_xigen; -+ atomic_t si_xigen_next; -+#endif -+ -+ /* dirty trick to support atomic_open */ -+ struct hlist_bl_head si_aopen; -+ -+ /* vdir parameters */ -+ unsigned long si_rdcache; /* max cache time in jiffies */ -+ unsigned int si_rdblk; /* deblk size */ -+ unsigned int si_rdhash; /* hash size */ -+ -+ /* -+ * If the number of whiteouts are larger than si_dirwh, leave all of -+ * them after au_whtmp_ren to reduce the cost of rmdir(2). -+ * future fsck.aufs or kernel thread will remove them later. -+ * Otherwise, remove all whiteouts and the dir in rmdir(2). -+ */ -+ unsigned int si_dirwh; -+ -+ /* pseudo_link list */ -+ struct hlist_bl_head si_plink[AuPlink_NHASH]; -+ wait_queue_head_t si_plink_wq; -+ spinlock_t si_plink_maint_lock; -+ pid_t si_plink_maint_pid; -+ -+ /* file list */ -+ struct hlist_bl_head si_files; -+ -+ /* with/without getattr, brother of sb->s_d_op */ -+ const struct inode_operations *si_iop_array; -+ -+ /* -+ * sysfs and lifetime management. -+ * this is not a small structure and it may be a waste of memory in case -+ * of sysfs is disabled, particularly when many aufs-es are mounted. -+ * but using sysfs is majority. -+ */ -+ struct kobject si_kobj; -+#ifdef CONFIG_DEBUG_FS -+ struct dentry *si_dbgaufs; -+ struct dentry *si_dbgaufs_plink; -+ struct dentry *si_dbgaufs_xib; -+#ifdef CONFIG_AUFS_EXPORT -+ struct dentry *si_dbgaufs_xigen; -+#endif -+#endif -+ -+#ifdef CONFIG_AUFS_SBILIST -+ struct hlist_bl_node si_list; -+#endif -+ -+ /* dirty, necessary for unmounting, sysfs and sysrq */ -+ struct super_block *si_sb; -+}; -+ -+/* sbinfo status flags */ -+/* -+ * set true when refresh_dirs() failed at remount time. -+ * then try refreshing dirs at access time again. -+ * if it is false, refreshing dirs at access time is unnecessary -+ */ -+#define AuSi_FAILED_REFRESH_DIR 1 -+#define AuSi_FHSM (1 << 1) /* fhsm is active now */ -+#define AuSi_NO_DREVAL (1 << 2) /* disable all d_revalidate */ -+ -+#ifndef CONFIG_AUFS_FHSM -+#undef AuSi_FHSM -+#define AuSi_FHSM 0 -+#endif -+ -+static inline unsigned char au_do_ftest_si(struct au_sbinfo *sbi, -+ unsigned int flag) -+{ -+ AuRwMustAnyLock(&sbi->si_rwsem); -+ return sbi->au_si_status & flag; -+} -+#define au_ftest_si(sbinfo, name) au_do_ftest_si(sbinfo, AuSi_##name) -+#define au_fset_si(sbinfo, name) do { \ -+ AuRwMustWriteLock(&(sbinfo)->si_rwsem); \ -+ (sbinfo)->au_si_status |= AuSi_##name; \ -+} while (0) -+#define au_fclr_si(sbinfo, name) do { \ -+ AuRwMustWriteLock(&(sbinfo)->si_rwsem); \ -+ (sbinfo)->au_si_status &= ~AuSi_##name; \ -+} while (0) -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* policy to select one among writable branches */ -+#define AuWbrCopyup(sbinfo, ...) \ -+ ((sbinfo)->si_wbr_copyup_ops->copyup(__VA_ARGS__)) -+#define AuWbrCreate(sbinfo, ...) \ -+ ((sbinfo)->si_wbr_create_ops->create(__VA_ARGS__)) -+ -+/* flags for si_read_lock()/aufs_read_lock()/di_read_lock() */ -+#define AuLock_DW 1 /* write-lock dentry */ -+#define AuLock_IR (1 << 1) /* read-lock inode */ -+#define AuLock_IW (1 << 2) /* write-lock inode */ -+#define AuLock_FLUSH (1 << 3) /* wait for 'nowait' tasks */ -+#define AuLock_DIRS (1 << 4) /* target is a pair of dirs */ -+ /* except RENAME_EXCHANGE */ -+#define AuLock_NOPLM (1 << 5) /* return err in plm mode */ -+#define AuLock_NOPLMW (1 << 6) /* wait for plm mode ends */ -+#define AuLock_GEN (1 << 7) /* test digen/iigen */ -+#define au_ftest_lock(flags, name) ((flags) & AuLock_##name) -+#define au_fset_lock(flags, name) \ -+ do { (flags) |= AuLock_##name; } while (0) -+#define au_fclr_lock(flags, name) \ -+ do { (flags) &= ~AuLock_##name; } while (0) -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* super.c */ -+extern struct file_system_type aufs_fs_type; -+struct inode *au_iget_locked(struct super_block *sb, ino_t ino); -+typedef unsigned long long (*au_arraycb_t)(struct super_block *sb, void *array, -+ unsigned long long max, void *arg); -+void *au_array_alloc(unsigned long long *hint, au_arraycb_t cb, -+ struct super_block *sb, void *arg); -+struct inode **au_iarray_alloc(struct super_block *sb, unsigned long long *max); -+void au_iarray_free(struct inode **a, unsigned long long max); -+ -+/* sbinfo.c */ -+void au_si_free(struct kobject *kobj); -+int au_si_alloc(struct super_block *sb); -+int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr, int may_shrink); -+ -+unsigned int au_sigen_inc(struct super_block *sb); -+aufs_bindex_t au_new_br_id(struct super_block *sb); -+ -+int si_read_lock(struct super_block *sb, int flags); -+int si_write_lock(struct super_block *sb, int flags); -+int aufs_read_lock(struct dentry *dentry, int flags); -+void aufs_read_unlock(struct dentry *dentry, int flags); -+void aufs_write_lock(struct dentry *dentry); -+void aufs_write_unlock(struct dentry *dentry); -+int aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags); -+void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2); -+ -+/* wbr_policy.c */ -+extern struct au_wbr_copyup_operations au_wbr_copyup_ops[]; -+extern struct au_wbr_create_operations au_wbr_create_ops[]; -+int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst); -+int au_wbr_nonopq(struct dentry *dentry, aufs_bindex_t bindex); -+int au_wbr_do_copyup_bu(struct dentry *dentry, aufs_bindex_t btop); -+ -+/* mvdown.c */ -+int au_mvdown(struct dentry *dentry, struct aufs_mvdown __user *arg); -+ -+#ifdef CONFIG_AUFS_FHSM -+/* fhsm.c */ -+ -+static inline pid_t au_fhsm_pid(struct au_fhsm *fhsm) -+{ -+ pid_t pid; -+ -+ spin_lock(&fhsm->fhsm_spin); -+ pid = fhsm->fhsm_pid; -+ spin_unlock(&fhsm->fhsm_spin); -+ -+ return pid; -+} -+ -+void au_fhsm_wrote(struct super_block *sb, aufs_bindex_t bindex, int force); -+void au_fhsm_wrote_all(struct super_block *sb, int force); -+int au_fhsm_fd(struct super_block *sb, int oflags); -+int au_fhsm_br_alloc(struct au_branch *br); -+void au_fhsm_set_bottom(struct super_block *sb, aufs_bindex_t bindex); -+void au_fhsm_fin(struct super_block *sb); -+void au_fhsm_init(struct au_sbinfo *sbinfo); -+void au_fhsm_set(struct au_sbinfo *sbinfo, unsigned int sec); -+void au_fhsm_show(struct seq_file *seq, struct au_sbinfo *sbinfo); -+#else -+AuStubVoid(au_fhsm_wrote, struct super_block *sb, aufs_bindex_t bindex, -+ int force) -+AuStubVoid(au_fhsm_wrote_all, struct super_block *sb, int force) -+AuStub(int, au_fhsm_fd, return -EOPNOTSUPP, struct super_block *sb, int oflags) -+AuStub(pid_t, au_fhsm_pid, return 0, struct au_fhsm *fhsm) -+AuStubInt0(au_fhsm_br_alloc, struct au_branch *br) -+AuStubVoid(au_fhsm_set_bottom, struct super_block *sb, aufs_bindex_t bindex) -+AuStubVoid(au_fhsm_fin, struct super_block *sb) -+AuStubVoid(au_fhsm_init, struct au_sbinfo *sbinfo) -+AuStubVoid(au_fhsm_set, struct au_sbinfo *sbinfo, unsigned int sec) -+AuStubVoid(au_fhsm_show, struct seq_file *seq, struct au_sbinfo *sbinfo) -+#endif -+ -+/* ---------------------------------------------------------------------- */ -+ -+static inline struct au_sbinfo *au_sbi(struct super_block *sb) -+{ -+ return sb->s_fs_info; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+#ifdef CONFIG_AUFS_EXPORT -+int au_test_nfsd(void); -+void au_export_init(struct super_block *sb); -+void au_xigen_inc(struct inode *inode); -+int au_xigen_new(struct inode *inode); -+int au_xigen_set(struct super_block *sb, struct path *path); -+void au_xigen_clr(struct super_block *sb); -+ -+static inline int au_busy_or_stale(void) -+{ -+ if (!au_test_nfsd()) -+ return -EBUSY; -+ return -ESTALE; -+} -+#else -+AuStubInt0(au_test_nfsd, void) -+AuStubVoid(au_export_init, struct super_block *sb) -+AuStubVoid(au_xigen_inc, struct inode *inode) -+AuStubInt0(au_xigen_new, struct inode *inode) -+AuStubInt0(au_xigen_set, struct super_block *sb, struct path *path) -+AuStubVoid(au_xigen_clr, struct super_block *sb) -+AuStub(int, au_busy_or_stale, return -EBUSY, void) -+#endif /* CONFIG_AUFS_EXPORT */ -+ -+/* ---------------------------------------------------------------------- */ -+ -+#ifdef CONFIG_AUFS_SBILIST -+/* module.c */ -+extern struct hlist_bl_head au_sbilist; -+ -+static inline void au_sbilist_init(void) -+{ -+ INIT_HLIST_BL_HEAD(&au_sbilist); -+} -+ -+static inline void au_sbilist_add(struct super_block *sb) -+{ -+ au_hbl_add(&au_sbi(sb)->si_list, &au_sbilist); -+} -+ -+static inline void au_sbilist_del(struct super_block *sb) -+{ -+ au_hbl_del(&au_sbi(sb)->si_list, &au_sbilist); -+} -+ -+#ifdef CONFIG_AUFS_MAGIC_SYSRQ -+static inline void au_sbilist_lock(void) -+{ -+ hlist_bl_lock(&au_sbilist); -+} -+ -+static inline void au_sbilist_unlock(void) -+{ -+ hlist_bl_unlock(&au_sbilist); -+} -+#define AuGFP_SBILIST GFP_ATOMIC -+#else -+AuStubVoid(au_sbilist_lock, void) -+AuStubVoid(au_sbilist_unlock, void) -+#define AuGFP_SBILIST GFP_NOFS -+#endif /* CONFIG_AUFS_MAGIC_SYSRQ */ -+#else -+AuStubVoid(au_sbilist_init, void) -+AuStubVoid(au_sbilist_add, struct super_block *sb) -+AuStubVoid(au_sbilist_del, struct super_block *sb) -+AuStubVoid(au_sbilist_lock, void) -+AuStubVoid(au_sbilist_unlock, void) -+#define AuGFP_SBILIST GFP_NOFS -+#endif -+ -+/* ---------------------------------------------------------------------- */ -+ -+static inline void dbgaufs_si_null(struct au_sbinfo *sbinfo) -+{ -+ /* -+ * This function is a dynamic '__init' function actually, -+ * so the tiny check for si_rwsem is unnecessary. -+ */ -+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */ -+#ifdef CONFIG_DEBUG_FS -+ sbinfo->si_dbgaufs = NULL; -+ sbinfo->si_dbgaufs_plink = NULL; -+ sbinfo->si_dbgaufs_xib = NULL; -+#ifdef CONFIG_AUFS_EXPORT -+ sbinfo->si_dbgaufs_xigen = NULL; -+#endif -+#endif -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* current->atomic_flags */ -+/* this value should never corrupt the ones defined in linux/sched.h */ -+#define PFA_AUFS 0x10 -+ -+TASK_PFA_TEST(AUFS, test_aufs) /* task_test_aufs */ -+TASK_PFA_SET(AUFS, aufs) /* task_set_aufs */ -+TASK_PFA_CLEAR(AUFS, aufs) /* task_clear_aufs */ -+ -+static inline int si_pid_test(struct super_block *sb) -+{ -+ return !!task_test_aufs(current); -+} -+ -+static inline void si_pid_clr(struct super_block *sb) -+{ -+ AuDebugOn(!task_test_aufs(current)); -+ task_clear_aufs(current); -+} -+ -+static inline void si_pid_set(struct super_block *sb) -+{ -+ AuDebugOn(task_test_aufs(current)); -+ task_set_aufs(current); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* lock superblock. mainly for entry point functions */ -+#define __si_read_lock(sb) au_rw_read_lock(&au_sbi(sb)->si_rwsem) -+#define __si_write_lock(sb) au_rw_write_lock(&au_sbi(sb)->si_rwsem) -+#define __si_read_trylock(sb) au_rw_read_trylock(&au_sbi(sb)->si_rwsem) -+#define __si_write_trylock(sb) au_rw_write_trylock(&au_sbi(sb)->si_rwsem) -+/* -+#define __si_read_trylock_nested(sb) \ -+ au_rw_read_trylock_nested(&au_sbi(sb)->si_rwsem) -+#define __si_write_trylock_nested(sb) \ -+ au_rw_write_trylock_nested(&au_sbi(sb)->si_rwsem) -+*/ -+ -+#define __si_read_unlock(sb) au_rw_read_unlock(&au_sbi(sb)->si_rwsem) -+#define __si_write_unlock(sb) au_rw_write_unlock(&au_sbi(sb)->si_rwsem) -+#define __si_downgrade_lock(sb) au_rw_dgrade_lock(&au_sbi(sb)->si_rwsem) -+ -+#define SiMustNoWaiters(sb) AuRwMustNoWaiters(&au_sbi(sb)->si_rwsem) -+#define SiMustAnyLock(sb) AuRwMustAnyLock(&au_sbi(sb)->si_rwsem) -+#define SiMustWriteLock(sb) AuRwMustWriteLock(&au_sbi(sb)->si_rwsem) -+ -+static inline void si_noflush_read_lock(struct super_block *sb) -+{ -+ __si_read_lock(sb); -+ si_pid_set(sb); -+} -+ -+static inline int si_noflush_read_trylock(struct super_block *sb) -+{ -+ int locked; -+ -+ locked = __si_read_trylock(sb); -+ if (locked) -+ si_pid_set(sb); -+ return locked; -+} -+ -+static inline void si_noflush_write_lock(struct super_block *sb) -+{ -+ __si_write_lock(sb); -+ si_pid_set(sb); -+} -+ -+static inline int si_noflush_write_trylock(struct super_block *sb) -+{ -+ int locked; -+ -+ locked = __si_write_trylock(sb); -+ if (locked) -+ si_pid_set(sb); -+ return locked; -+} -+ -+#if 0 /* reserved */ -+static inline int si_read_trylock(struct super_block *sb, int flags) -+{ -+ if (au_ftest_lock(flags, FLUSH)) -+ au_nwt_flush(&au_sbi(sb)->si_nowait); -+ return si_noflush_read_trylock(sb); -+} -+#endif -+ -+static inline void si_read_unlock(struct super_block *sb) -+{ -+ si_pid_clr(sb); -+ __si_read_unlock(sb); -+} -+ -+#if 0 /* reserved */ -+static inline int si_write_trylock(struct super_block *sb, int flags) -+{ -+ if (au_ftest_lock(flags, FLUSH)) -+ au_nwt_flush(&au_sbi(sb)->si_nowait); -+ return si_noflush_write_trylock(sb); -+} -+#endif -+ -+static inline void si_write_unlock(struct super_block *sb) -+{ -+ si_pid_clr(sb); -+ __si_write_unlock(sb); -+} -+ -+#if 0 /* reserved */ -+static inline void si_downgrade_lock(struct super_block *sb) -+{ -+ __si_downgrade_lock(sb); -+} -+#endif -+ -+/* ---------------------------------------------------------------------- */ -+ -+static inline aufs_bindex_t au_sbbot(struct super_block *sb) -+{ -+ SiMustAnyLock(sb); -+ return au_sbi(sb)->si_bbot; -+} -+ -+static inline unsigned int au_mntflags(struct super_block *sb) -+{ -+ SiMustAnyLock(sb); -+ return au_sbi(sb)->si_mntflags; -+} -+ -+static inline unsigned int au_sigen(struct super_block *sb) -+{ -+ SiMustAnyLock(sb); -+ return au_sbi(sb)->si_generation; -+} -+ -+static inline struct au_branch *au_sbr(struct super_block *sb, -+ aufs_bindex_t bindex) -+{ -+ SiMustAnyLock(sb); -+ return au_sbi(sb)->si_branch[0 + bindex]; -+} -+ -+static inline loff_t au_xi_maxent(struct super_block *sb) -+{ -+ SiMustAnyLock(sb); -+ return au_sbi(sb)->si_ximaxent; -+} -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_SUPER_H__ */ -diff -Nurp linux-5.10-rc6/fs/aufs/sysaufs.c linux-5.10-rc6.aufs/fs/aufs/sysaufs.c ---- linux-5.10-rc6/fs/aufs/sysaufs.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/sysaufs.c 2020-12-02 21:19:51.883036833 +0200 -@@ -0,0 +1,80 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * sysfs interface and lifetime management -+ * they are necessary regardless sysfs is disabled. -+ */ -+ -+#include -+#include "aufs.h" -+ -+unsigned long sysaufs_si_mask; -+struct kset *sysaufs_kset; -+ -+#define AuSiAttr(_name) { \ -+ .attr = { .name = __stringify(_name), .mode = 0444 }, \ -+ .show = sysaufs_si_##_name, \ -+} -+ -+static struct sysaufs_si_attr sysaufs_si_attr_xi_path = AuSiAttr(xi_path); -+struct attribute *sysaufs_si_attrs[] = { -+ &sysaufs_si_attr_xi_path.attr, -+ NULL, -+}; -+ -+static const struct sysfs_ops au_sbi_ops = { -+ .show = sysaufs_si_show -+}; -+ -+static struct kobj_type au_sbi_ktype = { -+ .release = au_si_free, -+ .sysfs_ops = &au_sbi_ops, -+ .default_attrs = sysaufs_si_attrs -+}; -+ -+/* ---------------------------------------------------------------------- */ -+ -+int sysaufs_si_init(struct au_sbinfo *sbinfo) -+{ -+ int err; -+ -+ sbinfo->si_kobj.kset = sysaufs_kset; -+ /* cf. sysaufs_name() */ -+ err = kobject_init_and_add -+ (&sbinfo->si_kobj, &au_sbi_ktype, /*&sysaufs_kset->kobj*/NULL, -+ SysaufsSiNamePrefix "%lx", sysaufs_si_id(sbinfo)); -+ -+ return err; -+} -+ -+void sysaufs_fin(void) -+{ -+ sysfs_remove_group(&sysaufs_kset->kobj, sysaufs_attr_group); -+ kset_unregister(sysaufs_kset); -+} -+ -+int __init sysaufs_init(void) -+{ -+ int err; -+ -+ do { -+ get_random_bytes(&sysaufs_si_mask, sizeof(sysaufs_si_mask)); -+ } while (!sysaufs_si_mask); -+ -+ err = -EINVAL; -+ sysaufs_kset = kset_create_and_add(AUFS_NAME, NULL, fs_kobj); -+ if (unlikely(!sysaufs_kset)) -+ goto out; -+ err = PTR_ERR(sysaufs_kset); -+ if (IS_ERR(sysaufs_kset)) -+ goto out; -+ err = sysfs_create_group(&sysaufs_kset->kobj, sysaufs_attr_group); -+ if (unlikely(err)) -+ kset_unregister(sysaufs_kset); -+ -+out: -+ return err; -+} -diff -Nurp linux-5.10-rc6/fs/aufs/sysaufs.h linux-5.10-rc6.aufs/fs/aufs/sysaufs.h ---- linux-5.10-rc6/fs/aufs/sysaufs.h 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/sysaufs.h 2020-12-02 21:19:51.883036833 +0200 -@@ -0,0 +1,89 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * sysfs interface and mount lifetime management -+ */ -+ -+#ifndef __SYSAUFS_H__ -+#define __SYSAUFS_H__ -+ -+#ifdef __KERNEL__ -+ -+#include -+#include "module.h" -+ -+struct super_block; -+struct au_sbinfo; -+ -+struct sysaufs_si_attr { -+ struct attribute attr; -+ int (*show)(struct seq_file *seq, struct super_block *sb); -+}; -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* sysaufs.c */ -+extern unsigned long sysaufs_si_mask; -+extern struct kset *sysaufs_kset; -+extern struct attribute *sysaufs_si_attrs[]; -+int sysaufs_si_init(struct au_sbinfo *sbinfo); -+int __init sysaufs_init(void); -+void sysaufs_fin(void); -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* some people doesn't like to show a pointer in kernel */ -+static inline unsigned long sysaufs_si_id(struct au_sbinfo *sbinfo) -+{ -+ return sysaufs_si_mask ^ (unsigned long)sbinfo; -+} -+ -+#define SysaufsSiNamePrefix "si_" -+#define SysaufsSiNameLen (sizeof(SysaufsSiNamePrefix) + 16) -+static inline void sysaufs_name(struct au_sbinfo *sbinfo, char *name) -+{ -+ snprintf(name, SysaufsSiNameLen, SysaufsSiNamePrefix "%lx", -+ sysaufs_si_id(sbinfo)); -+} -+ -+struct au_branch; -+#ifdef CONFIG_SYSFS -+/* sysfs.c */ -+extern struct attribute_group *sysaufs_attr_group; -+ -+int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb); -+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr, -+ char *buf); -+long au_brinfo_ioctl(struct file *file, unsigned long arg); -+#ifdef CONFIG_COMPAT -+long au_brinfo_compat_ioctl(struct file *file, unsigned long arg); -+#endif -+ -+void sysaufs_br_init(struct au_branch *br); -+void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex); -+void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex); -+ -+#define sysaufs_brs_init() do {} while (0) -+ -+#else -+#define sysaufs_attr_group NULL -+ -+AuStubInt0(sysaufs_si_xi_path, struct seq_file *seq, struct super_block *sb) -+AuStub(ssize_t, sysaufs_si_show, return 0, struct kobject *kobj, -+ struct attribute *attr, char *buf) -+AuStubVoid(sysaufs_br_init, struct au_branch *br) -+AuStubVoid(sysaufs_brs_add, struct super_block *sb, aufs_bindex_t bindex) -+AuStubVoid(sysaufs_brs_del, struct super_block *sb, aufs_bindex_t bindex) -+ -+static inline void sysaufs_brs_init(void) -+{ -+ sysaufs_brs = 0; -+} -+ -+#endif /* CONFIG_SYSFS */ -+ -+#endif /* __KERNEL__ */ -+#endif /* __SYSAUFS_H__ */ -diff -Nurp linux-5.10-rc6/fs/aufs/sysfs.c linux-5.10-rc6.aufs/fs/aufs/sysfs.c ---- linux-5.10-rc6/fs/aufs/sysfs.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/sysfs.c 2020-12-02 21:19:51.883036833 +0200 -@@ -0,0 +1,338 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * sysfs interface -+ */ -+ -+#include -+#include -+#include "aufs.h" -+ -+static struct attribute *au_attr[] = { -+ NULL, /* need to NULL terminate the list of attributes */ -+}; -+ -+static struct attribute_group sysaufs_attr_group_body = { -+ .attrs = au_attr -+}; -+ -+struct attribute_group *sysaufs_attr_group = &sysaufs_attr_group_body; -+ -+/* ---------------------------------------------------------------------- */ -+ -+int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb) -+{ -+ int err; -+ -+ SiMustAnyLock(sb); -+ -+ err = 0; -+ if (au_opt_test(au_mntflags(sb), XINO)) { -+ err = au_xino_path(seq, au_sbi(sb)->si_xib); -+ seq_putc(seq, '\n'); -+ } -+ return err; -+} -+ -+/* -+ * the lifetime of branch is independent from the entry under sysfs. -+ * sysfs handles the lifetime of the entry, and never call ->show() after it is -+ * unlinked. -+ */ -+static int sysaufs_si_br(struct seq_file *seq, struct super_block *sb, -+ aufs_bindex_t bindex, int idx) -+{ -+ int err; -+ struct path path; -+ struct dentry *root; -+ struct au_branch *br; -+ au_br_perm_str_t perm; -+ -+ AuDbg("b%d\n", bindex); -+ -+ err = 0; -+ root = sb->s_root; -+ di_read_lock_parent(root, !AuLock_IR); -+ br = au_sbr(sb, bindex); -+ -+ switch (idx) { -+ case AuBrSysfs_BR: -+ path.mnt = au_br_mnt(br); -+ path.dentry = au_h_dptr(root, bindex); -+ err = au_seq_path(seq, &path); -+ if (!err) { -+ au_optstr_br_perm(&perm, br->br_perm); -+ seq_printf(seq, "=%s\n", perm.a); -+ } -+ break; -+ case AuBrSysfs_BRID: -+ seq_printf(seq, "%d\n", br->br_id); -+ break; -+ } -+ di_read_unlock(root, !AuLock_IR); -+ if (unlikely(err || seq_has_overflowed(seq))) -+ err = -E2BIG; -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static struct seq_file *au_seq(char *p, ssize_t len) -+{ -+ struct seq_file *seq; -+ -+ seq = kzalloc(sizeof(*seq), GFP_NOFS); -+ if (seq) { -+ /* mutex_init(&seq.lock); */ -+ seq->buf = p; -+ seq->size = len; -+ return seq; /* success */ -+ } -+ -+ seq = ERR_PTR(-ENOMEM); -+ return seq; -+} -+ -+#define SysaufsBr_PREFIX "br" -+#define SysaufsBrid_PREFIX "brid" -+ -+/* todo: file size may exceed PAGE_SIZE */ -+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr, -+ char *buf) -+{ -+ ssize_t err; -+ int idx; -+ long l; -+ aufs_bindex_t bbot; -+ struct au_sbinfo *sbinfo; -+ struct super_block *sb; -+ struct seq_file *seq; -+ char *name; -+ struct attribute **cattr; -+ -+ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj); -+ sb = sbinfo->si_sb; -+ -+ /* -+ * prevent a race condition between sysfs and aufs. -+ * for instance, sysfs_file_read() calls sysfs_get_active_two() which -+ * prohibits maintaining the sysfs entries. -+ * hew we acquire read lock after sysfs_get_active_two(). -+ * on the other hand, the remount process may maintain the sysfs/aufs -+ * entries after acquiring write lock. -+ * it can cause a deadlock. -+ * simply we gave up processing read here. -+ */ -+ err = -EBUSY; -+ if (unlikely(!si_noflush_read_trylock(sb))) -+ goto out; -+ -+ seq = au_seq(buf, PAGE_SIZE); -+ err = PTR_ERR(seq); -+ if (IS_ERR(seq)) -+ goto out_unlock; -+ -+ name = (void *)attr->name; -+ cattr = sysaufs_si_attrs; -+ while (*cattr) { -+ if (!strcmp(name, (*cattr)->name)) { -+ err = container_of(*cattr, struct sysaufs_si_attr, attr) -+ ->show(seq, sb); -+ goto out_seq; -+ } -+ cattr++; -+ } -+ -+ if (!strncmp(name, SysaufsBrid_PREFIX, -+ sizeof(SysaufsBrid_PREFIX) - 1)) { -+ idx = AuBrSysfs_BRID; -+ name += sizeof(SysaufsBrid_PREFIX) - 1; -+ } else if (!strncmp(name, SysaufsBr_PREFIX, -+ sizeof(SysaufsBr_PREFIX) - 1)) { -+ idx = AuBrSysfs_BR; -+ name += sizeof(SysaufsBr_PREFIX) - 1; -+ } else -+ BUG(); -+ -+ err = kstrtol(name, 10, &l); -+ if (!err) { -+ bbot = au_sbbot(sb); -+ if (l <= bbot) -+ err = sysaufs_si_br(seq, sb, (aufs_bindex_t)l, idx); -+ else -+ err = -ENOENT; -+ } -+ -+out_seq: -+ if (!err) { -+ err = seq->count; -+ /* sysfs limit */ -+ if (unlikely(err == PAGE_SIZE)) -+ err = -EFBIG; -+ } -+ au_kfree_rcu(seq); -+out_unlock: -+ si_read_unlock(sb); -+out: -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int au_brinfo(struct super_block *sb, union aufs_brinfo __user *arg) -+{ -+ int err; -+ int16_t brid; -+ aufs_bindex_t bindex, bbot; -+ size_t sz; -+ char *buf; -+ struct seq_file *seq; -+ struct au_branch *br; -+ -+ si_read_lock(sb, AuLock_FLUSH); -+ bbot = au_sbbot(sb); -+ err = bbot + 1; -+ if (!arg) -+ goto out; -+ -+ err = -ENOMEM; -+ buf = (void *)__get_free_page(GFP_NOFS); -+ if (unlikely(!buf)) -+ goto out; -+ -+ seq = au_seq(buf, PAGE_SIZE); -+ err = PTR_ERR(seq); -+ if (IS_ERR(seq)) -+ goto out_buf; -+ -+ sz = sizeof(*arg) - offsetof(union aufs_brinfo, path); -+ for (bindex = 0; bindex <= bbot; bindex++, arg++) { -+ /* VERIFY_WRITE */ -+ err = !access_ok(arg, sizeof(*arg)); -+ if (unlikely(err)) -+ break; -+ -+ br = au_sbr(sb, bindex); -+ brid = br->br_id; -+ BUILD_BUG_ON(sizeof(brid) != sizeof(arg->id)); -+ err = __put_user(brid, &arg->id); -+ if (unlikely(err)) -+ break; -+ -+ BUILD_BUG_ON(sizeof(br->br_perm) != sizeof(arg->perm)); -+ err = __put_user(br->br_perm, &arg->perm); -+ if (unlikely(err)) -+ break; -+ -+ err = au_seq_path(seq, &br->br_path); -+ if (unlikely(err)) -+ break; -+ seq_putc(seq, '\0'); -+ if (!seq_has_overflowed(seq)) { -+ err = copy_to_user(arg->path, seq->buf, seq->count); -+ seq->count = 0; -+ if (unlikely(err)) -+ break; -+ } else { -+ err = -E2BIG; -+ goto out_seq; -+ } -+ } -+ if (unlikely(err)) -+ err = -EFAULT; -+ -+out_seq: -+ au_kfree_rcu(seq); -+out_buf: -+ free_page((unsigned long)buf); -+out: -+ si_read_unlock(sb); -+ return err; -+} -+ -+long au_brinfo_ioctl(struct file *file, unsigned long arg) -+{ -+ return au_brinfo(file->f_path.dentry->d_sb, (void __user *)arg); -+} -+ -+#ifdef CONFIG_COMPAT -+long au_brinfo_compat_ioctl(struct file *file, unsigned long arg) -+{ -+ return au_brinfo(file->f_path.dentry->d_sb, compat_ptr(arg)); -+} -+#endif -+ -+/* ---------------------------------------------------------------------- */ -+ -+void sysaufs_br_init(struct au_branch *br) -+{ -+ int i; -+ struct au_brsysfs *br_sysfs; -+ struct attribute *attr; -+ -+ br_sysfs = br->br_sysfs; -+ for (i = 0; i < ARRAY_SIZE(br->br_sysfs); i++) { -+ attr = &br_sysfs->attr; -+ sysfs_attr_init(attr); -+ attr->name = br_sysfs->name; -+ attr->mode = 0444; -+ br_sysfs++; -+ } -+} -+ -+void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex) -+{ -+ struct au_branch *br; -+ struct kobject *kobj; -+ struct au_brsysfs *br_sysfs; -+ int i; -+ aufs_bindex_t bbot; -+ -+ if (!sysaufs_brs) -+ return; -+ -+ kobj = &au_sbi(sb)->si_kobj; -+ bbot = au_sbbot(sb); -+ for (; bindex <= bbot; bindex++) { -+ br = au_sbr(sb, bindex); -+ br_sysfs = br->br_sysfs; -+ for (i = 0; i < ARRAY_SIZE(br->br_sysfs); i++) { -+ sysfs_remove_file(kobj, &br_sysfs->attr); -+ br_sysfs++; -+ } -+ } -+} -+ -+void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex) -+{ -+ int err, i; -+ aufs_bindex_t bbot; -+ struct kobject *kobj; -+ struct au_branch *br; -+ struct au_brsysfs *br_sysfs; -+ -+ if (!sysaufs_brs) -+ return; -+ -+ kobj = &au_sbi(sb)->si_kobj; -+ bbot = au_sbbot(sb); -+ for (; bindex <= bbot; bindex++) { -+ br = au_sbr(sb, bindex); -+ br_sysfs = br->br_sysfs; -+ snprintf(br_sysfs[AuBrSysfs_BR].name, sizeof(br_sysfs->name), -+ SysaufsBr_PREFIX "%d", bindex); -+ snprintf(br_sysfs[AuBrSysfs_BRID].name, sizeof(br_sysfs->name), -+ SysaufsBrid_PREFIX "%d", bindex); -+ for (i = 0; i < ARRAY_SIZE(br->br_sysfs); i++) { -+ err = sysfs_create_file(kobj, &br_sysfs->attr); -+ if (unlikely(err)) -+ pr_warn("failed %s under sysfs(%d)\n", -+ br_sysfs->name, err); -+ br_sysfs++; -+ } -+ } -+} -diff -Nurp linux-5.10-rc6/fs/aufs/sysrq.c linux-5.10-rc6.aufs/fs/aufs/sysrq.c ---- linux-5.10-rc6/fs/aufs/sysrq.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/sysrq.c 2020-12-02 21:19:51.883036833 +0200 -@@ -0,0 +1,136 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * magic sysrq handler -+ */ -+ -+/* #include */ -+#include -+#include "aufs.h" -+ -+/* ---------------------------------------------------------------------- */ -+ -+static void sysrq_sb(struct super_block *sb) -+{ -+ char *plevel; -+ struct au_sbinfo *sbinfo; -+ struct file *file; -+ struct hlist_bl_head *files; -+ struct hlist_bl_node *pos; -+ struct au_finfo *finfo; -+ struct inode *i; -+ -+ plevel = au_plevel; -+ au_plevel = KERN_WARNING; -+ -+ /* since we define pr_fmt, call printk directly */ -+#define pr(str) printk(KERN_WARNING AUFS_NAME ": " str) -+ -+ sbinfo = au_sbi(sb); -+ printk(KERN_WARNING "si=%lx\n", sysaufs_si_id(sbinfo)); -+ pr("superblock\n"); -+ au_dpri_sb(sb); -+ -+#if 0 /* reserved */ -+ do { -+ int err, i, j, ndentry; -+ struct au_dcsub_pages dpages; -+ struct au_dpage *dpage; -+ -+ err = au_dpages_init(&dpages, GFP_ATOMIC); -+ if (unlikely(err)) -+ break; -+ err = au_dcsub_pages(&dpages, sb->s_root, NULL, NULL); -+ if (!err) -+ for (i = 0; i < dpages.ndpage; i++) { -+ dpage = dpages.dpages + i; -+ ndentry = dpage->ndentry; -+ for (j = 0; j < ndentry; j++) -+ au_dpri_dentry(dpage->dentries[j]); -+ } -+ au_dpages_free(&dpages); -+ } while (0); -+#endif -+ -+ pr("isolated inode\n"); -+ spin_lock(&sb->s_inode_list_lock); -+ list_for_each_entry(i, &sb->s_inodes, i_sb_list) { -+ spin_lock(&i->i_lock); -+ if (hlist_empty(&i->i_dentry)) -+ au_dpri_inode(i); -+ spin_unlock(&i->i_lock); -+ } -+ spin_unlock(&sb->s_inode_list_lock); -+ -+ pr("files\n"); -+ files = &au_sbi(sb)->si_files; -+ hlist_bl_lock(files); -+ hlist_bl_for_each_entry(finfo, pos, files, fi_hlist) { -+ umode_t mode; -+ -+ file = finfo->fi_file; -+ mode = file_inode(file)->i_mode; -+ if (!special_file(mode)) -+ au_dpri_file(file); -+ } -+ hlist_bl_unlock(files); -+ pr("done\n"); -+ -+#undef pr -+ au_plevel = plevel; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* module parameter */ -+static char *aufs_sysrq_key = "a"; -+module_param_named(sysrq, aufs_sysrq_key, charp, 0444); -+MODULE_PARM_DESC(sysrq, "MagicSysRq key for " AUFS_NAME); -+ -+static void au_sysrq(int key __maybe_unused) -+{ -+ struct au_sbinfo *sbinfo; -+ struct hlist_bl_node *pos; -+ -+ lockdep_off(); -+ au_sbilist_lock(); -+ hlist_bl_for_each_entry(sbinfo, pos, &au_sbilist, si_list) -+ sysrq_sb(sbinfo->si_sb); -+ au_sbilist_unlock(); -+ lockdep_on(); -+} -+ -+static struct sysrq_key_op au_sysrq_op = { -+ .handler = au_sysrq, -+ .help_msg = "Aufs", -+ .action_msg = "Aufs", -+ .enable_mask = SYSRQ_ENABLE_DUMP -+}; -+ -+/* ---------------------------------------------------------------------- */ -+ -+int __init au_sysrq_init(void) -+{ -+ int err; -+ char key; -+ -+ err = -1; -+ key = *aufs_sysrq_key; -+ if ('a' <= key && key <= 'z') -+ err = register_sysrq_key(key, &au_sysrq_op); -+ if (unlikely(err)) -+ pr_err("err %d, sysrq=%c\n", err, key); -+ return err; -+} -+ -+void au_sysrq_fin(void) -+{ -+ int err; -+ -+ err = unregister_sysrq_key(*aufs_sysrq_key, &au_sysrq_op); -+ if (unlikely(err)) -+ pr_err("err %d (ignored)\n", err); -+} -diff -Nurp linux-5.10-rc6/fs/aufs/wbr_policy.c linux-5.10-rc6.aufs/fs/aufs/wbr_policy.c ---- linux-5.10-rc6/fs/aufs/wbr_policy.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/wbr_policy.c 2020-12-02 21:19:51.884036878 +0200 -@@ -0,0 +1,817 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * policies for selecting one among multiple writable branches -+ */ -+ -+#include -+#include "aufs.h" -+ -+/* subset of cpup_attr() */ -+static noinline_for_stack -+int au_cpdown_attr(struct path *h_path, struct dentry *h_src) -+{ -+ int err, sbits; -+ struct iattr ia; -+ struct inode *h_isrc; -+ -+ h_isrc = d_inode(h_src); -+ ia.ia_valid = ATTR_FORCE | ATTR_MODE | ATTR_UID | ATTR_GID; -+ ia.ia_mode = h_isrc->i_mode; -+ ia.ia_uid = h_isrc->i_uid; -+ ia.ia_gid = h_isrc->i_gid; -+ sbits = !!(ia.ia_mode & (S_ISUID | S_ISGID)); -+ au_cpup_attr_flags(d_inode(h_path->dentry), h_isrc->i_flags); -+ /* no delegation since it is just created */ -+ err = vfsub_sio_notify_change(h_path, &ia, /*delegated*/NULL); -+ -+ /* is this nfs only? */ -+ if (!err && sbits && au_test_nfs(h_path->dentry->d_sb)) { -+ ia.ia_valid = ATTR_FORCE | ATTR_MODE; -+ ia.ia_mode = h_isrc->i_mode; -+ err = vfsub_sio_notify_change(h_path, &ia, /*delegated*/NULL); -+ } -+ -+ return err; -+} -+ -+#define AuCpdown_PARENT_OPQ 1 -+#define AuCpdown_WHED (1 << 1) -+#define AuCpdown_MADE_DIR (1 << 2) -+#define AuCpdown_DIROPQ (1 << 3) -+#define au_ftest_cpdown(flags, name) ((flags) & AuCpdown_##name) -+#define au_fset_cpdown(flags, name) \ -+ do { (flags) |= AuCpdown_##name; } while (0) -+#define au_fclr_cpdown(flags, name) \ -+ do { (flags) &= ~AuCpdown_##name; } while (0) -+ -+static int au_cpdown_dir_opq(struct dentry *dentry, aufs_bindex_t bdst, -+ unsigned int *flags) -+{ -+ int err; -+ struct dentry *opq_dentry; -+ -+ opq_dentry = au_diropq_create(dentry, bdst); -+ err = PTR_ERR(opq_dentry); -+ if (IS_ERR(opq_dentry)) -+ goto out; -+ dput(opq_dentry); -+ au_fset_cpdown(*flags, DIROPQ); -+ -+out: -+ return err; -+} -+ -+static int au_cpdown_dir_wh(struct dentry *dentry, struct dentry *h_parent, -+ struct inode *dir, aufs_bindex_t bdst) -+{ -+ int err; -+ struct path h_path; -+ struct au_branch *br; -+ -+ br = au_sbr(dentry->d_sb, bdst); -+ h_path.dentry = au_wh_lkup(h_parent, &dentry->d_name, br); -+ err = PTR_ERR(h_path.dentry); -+ if (IS_ERR(h_path.dentry)) -+ goto out; -+ -+ err = 0; -+ if (d_is_positive(h_path.dentry)) { -+ h_path.mnt = au_br_mnt(br); -+ err = au_wh_unlink_dentry(au_h_iptr(dir, bdst), &h_path, -+ dentry); -+ } -+ dput(h_path.dentry); -+ -+out: -+ return err; -+} -+ -+static int au_cpdown_dir(struct dentry *dentry, aufs_bindex_t bdst, -+ struct au_pin *pin, -+ struct dentry *h_parent, void *arg) -+{ -+ int err, rerr; -+ aufs_bindex_t bopq, btop; -+ struct path h_path; -+ struct dentry *parent; -+ struct inode *h_dir, *h_inode, *inode, *dir; -+ unsigned int *flags = arg; -+ -+ btop = au_dbtop(dentry); -+ /* dentry is di-locked */ -+ parent = dget_parent(dentry); -+ dir = d_inode(parent); -+ h_dir = d_inode(h_parent); -+ AuDebugOn(h_dir != au_h_iptr(dir, bdst)); -+ IMustLock(h_dir); -+ -+ err = au_lkup_neg(dentry, bdst, /*wh*/0); -+ if (unlikely(err < 0)) -+ goto out; -+ h_path.dentry = au_h_dptr(dentry, bdst); -+ h_path.mnt = au_sbr_mnt(dentry->d_sb, bdst); -+ err = vfsub_sio_mkdir(au_h_iptr(dir, bdst), &h_path, 0755); -+ if (unlikely(err)) -+ goto out_put; -+ au_fset_cpdown(*flags, MADE_DIR); -+ -+ bopq = au_dbdiropq(dentry); -+ au_fclr_cpdown(*flags, WHED); -+ au_fclr_cpdown(*flags, DIROPQ); -+ if (au_dbwh(dentry) == bdst) -+ au_fset_cpdown(*flags, WHED); -+ if (!au_ftest_cpdown(*flags, PARENT_OPQ) && bopq <= bdst) -+ au_fset_cpdown(*flags, PARENT_OPQ); -+ h_inode = d_inode(h_path.dentry); -+ inode_lock_nested(h_inode, AuLsc_I_CHILD); -+ if (au_ftest_cpdown(*flags, WHED)) { -+ err = au_cpdown_dir_opq(dentry, bdst, flags); -+ if (unlikely(err)) { -+ inode_unlock(h_inode); -+ goto out_dir; -+ } -+ } -+ -+ err = au_cpdown_attr(&h_path, au_h_dptr(dentry, btop)); -+ inode_unlock(h_inode); -+ if (unlikely(err)) -+ goto out_opq; -+ -+ if (au_ftest_cpdown(*flags, WHED)) { -+ err = au_cpdown_dir_wh(dentry, h_parent, dir, bdst); -+ if (unlikely(err)) -+ goto out_opq; -+ } -+ -+ inode = d_inode(dentry); -+ if (au_ibbot(inode) < bdst) -+ au_set_ibbot(inode, bdst); -+ au_set_h_iptr(inode, bdst, au_igrab(h_inode), -+ au_hi_flags(inode, /*isdir*/1)); -+ au_fhsm_wrote(dentry->d_sb, bdst, /*force*/0); -+ goto out; /* success */ -+ -+ /* revert */ -+out_opq: -+ if (au_ftest_cpdown(*flags, DIROPQ)) { -+ inode_lock_nested(h_inode, AuLsc_I_CHILD); -+ rerr = au_diropq_remove(dentry, bdst); -+ inode_unlock(h_inode); -+ if (unlikely(rerr)) { -+ AuIOErr("failed removing diropq for %pd b%d (%d)\n", -+ dentry, bdst, rerr); -+ err = -EIO; -+ goto out; -+ } -+ } -+out_dir: -+ if (au_ftest_cpdown(*flags, MADE_DIR)) { -+ rerr = vfsub_sio_rmdir(au_h_iptr(dir, bdst), &h_path); -+ if (unlikely(rerr)) { -+ AuIOErr("failed removing %pd b%d (%d)\n", -+ dentry, bdst, rerr); -+ err = -EIO; -+ } -+ } -+out_put: -+ au_set_h_dptr(dentry, bdst, NULL); -+ if (au_dbbot(dentry) == bdst) -+ au_update_dbbot(dentry); -+out: -+ dput(parent); -+ return err; -+} -+ -+int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst) -+{ -+ int err; -+ unsigned int flags; -+ -+ flags = 0; -+ err = au_cp_dirs(dentry, bdst, au_cpdown_dir, &flags); -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* policies for create */ -+ -+int au_wbr_nonopq(struct dentry *dentry, aufs_bindex_t bindex) -+{ -+ int err, i, j, ndentry; -+ aufs_bindex_t bopq; -+ struct au_dcsub_pages dpages; -+ struct au_dpage *dpage; -+ struct dentry **dentries, *parent, *d; -+ -+ err = au_dpages_init(&dpages, GFP_NOFS); -+ if (unlikely(err)) -+ goto out; -+ parent = dget_parent(dentry); -+ err = au_dcsub_pages_rev_aufs(&dpages, parent, /*do_include*/0); -+ if (unlikely(err)) -+ goto out_free; -+ -+ err = bindex; -+ for (i = 0; i < dpages.ndpage; i++) { -+ dpage = dpages.dpages + i; -+ dentries = dpage->dentries; -+ ndentry = dpage->ndentry; -+ for (j = 0; j < ndentry; j++) { -+ d = dentries[j]; -+ di_read_lock_parent2(d, !AuLock_IR); -+ bopq = au_dbdiropq(d); -+ di_read_unlock(d, !AuLock_IR); -+ if (bopq >= 0 && bopq < err) -+ err = bopq; -+ } -+ } -+ -+out_free: -+ dput(parent); -+ au_dpages_free(&dpages); -+out: -+ return err; -+} -+ -+static int au_wbr_bu(struct super_block *sb, aufs_bindex_t bindex) -+{ -+ for (; bindex >= 0; bindex--) -+ if (!au_br_rdonly(au_sbr(sb, bindex))) -+ return bindex; -+ return -EROFS; -+} -+ -+/* top down parent */ -+static int au_wbr_create_tdp(struct dentry *dentry, -+ unsigned int flags __maybe_unused) -+{ -+ int err; -+ aufs_bindex_t btop, bindex; -+ struct super_block *sb; -+ struct dentry *parent, *h_parent; -+ -+ sb = dentry->d_sb; -+ btop = au_dbtop(dentry); -+ err = btop; -+ if (!au_br_rdonly(au_sbr(sb, btop))) -+ goto out; -+ -+ err = -EROFS; -+ parent = dget_parent(dentry); -+ for (bindex = au_dbtop(parent); bindex < btop; bindex++) { -+ h_parent = au_h_dptr(parent, bindex); -+ if (!h_parent || d_is_negative(h_parent)) -+ continue; -+ -+ if (!au_br_rdonly(au_sbr(sb, bindex))) { -+ err = bindex; -+ break; -+ } -+ } -+ dput(parent); -+ -+ /* bottom up here */ -+ if (unlikely(err < 0)) { -+ err = au_wbr_bu(sb, btop - 1); -+ if (err >= 0) -+ err = au_wbr_nonopq(dentry, err); -+ } -+ -+out: -+ AuDbg("b%d\n", err); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* an exception for the policy other than tdp */ -+static int au_wbr_create_exp(struct dentry *dentry) -+{ -+ int err; -+ aufs_bindex_t bwh, bdiropq; -+ struct dentry *parent; -+ -+ err = -1; -+ bwh = au_dbwh(dentry); -+ parent = dget_parent(dentry); -+ bdiropq = au_dbdiropq(parent); -+ if (bwh >= 0) { -+ if (bdiropq >= 0) -+ err = min(bdiropq, bwh); -+ else -+ err = bwh; -+ AuDbg("%d\n", err); -+ } else if (bdiropq >= 0) { -+ err = bdiropq; -+ AuDbg("%d\n", err); -+ } -+ dput(parent); -+ -+ if (err >= 0) -+ err = au_wbr_nonopq(dentry, err); -+ -+ if (err >= 0 && au_br_rdonly(au_sbr(dentry->d_sb, err))) -+ err = -1; -+ -+ AuDbg("%d\n", err); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* round robin */ -+static int au_wbr_create_init_rr(struct super_block *sb) -+{ -+ int err; -+ -+ err = au_wbr_bu(sb, au_sbbot(sb)); -+ atomic_set(&au_sbi(sb)->si_wbr_rr_next, -err); /* less important */ -+ /* smp_mb(); */ -+ -+ AuDbg("b%d\n", err); -+ return err; -+} -+ -+static int au_wbr_create_rr(struct dentry *dentry, unsigned int flags) -+{ -+ int err, nbr; -+ unsigned int u; -+ aufs_bindex_t bindex, bbot; -+ struct super_block *sb; -+ atomic_t *next; -+ -+ err = au_wbr_create_exp(dentry); -+ if (err >= 0) -+ goto out; -+ -+ sb = dentry->d_sb; -+ next = &au_sbi(sb)->si_wbr_rr_next; -+ bbot = au_sbbot(sb); -+ nbr = bbot + 1; -+ for (bindex = 0; bindex <= bbot; bindex++) { -+ if (!au_ftest_wbr(flags, DIR)) { -+ err = atomic_dec_return(next) + 1; -+ /* modulo for 0 is meaningless */ -+ if (unlikely(!err)) -+ err = atomic_dec_return(next) + 1; -+ } else -+ err = atomic_read(next); -+ AuDbg("%d\n", err); -+ u = err; -+ err = u % nbr; -+ AuDbg("%d\n", err); -+ if (!au_br_rdonly(au_sbr(sb, err))) -+ break; -+ err = -EROFS; -+ } -+ -+ if (err >= 0) -+ err = au_wbr_nonopq(dentry, err); -+ -+out: -+ AuDbg("%d\n", err); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* most free space */ -+static void au_mfs(struct dentry *dentry, struct dentry *parent) -+{ -+ struct super_block *sb; -+ struct au_branch *br; -+ struct au_wbr_mfs *mfs; -+ struct dentry *h_parent; -+ aufs_bindex_t bindex, bbot; -+ int err; -+ unsigned long long b, bavail; -+ struct path h_path; -+ /* reduce the stack usage */ -+ struct kstatfs *st; -+ -+ st = kmalloc(sizeof(*st), GFP_NOFS); -+ if (unlikely(!st)) { -+ AuWarn1("failed updating mfs(%d), ignored\n", -ENOMEM); -+ return; -+ } -+ -+ bavail = 0; -+ sb = dentry->d_sb; -+ mfs = &au_sbi(sb)->si_wbr_mfs; -+ MtxMustLock(&mfs->mfs_lock); -+ mfs->mfs_bindex = -EROFS; -+ mfs->mfsrr_bytes = 0; -+ if (!parent) { -+ bindex = 0; -+ bbot = au_sbbot(sb); -+ } else { -+ bindex = au_dbtop(parent); -+ bbot = au_dbtaildir(parent); -+ } -+ -+ for (; bindex <= bbot; bindex++) { -+ if (parent) { -+ h_parent = au_h_dptr(parent, bindex); -+ if (!h_parent || d_is_negative(h_parent)) -+ continue; -+ } -+ br = au_sbr(sb, bindex); -+ if (au_br_rdonly(br)) -+ continue; -+ -+ /* sb->s_root for NFS is unreliable */ -+ h_path.mnt = au_br_mnt(br); -+ h_path.dentry = h_path.mnt->mnt_root; -+ err = vfs_statfs(&h_path, st); -+ if (unlikely(err)) { -+ AuWarn1("failed statfs, b%d, %d\n", bindex, err); -+ continue; -+ } -+ -+ /* when the available size is equal, select the lower one */ -+ BUILD_BUG_ON(sizeof(b) < sizeof(st->f_bavail) -+ || sizeof(b) < sizeof(st->f_bsize)); -+ b = st->f_bavail * st->f_bsize; -+ br->br_wbr->wbr_bytes = b; -+ if (b >= bavail) { -+ bavail = b; -+ mfs->mfs_bindex = bindex; -+ mfs->mfs_jiffy = jiffies; -+ } -+ } -+ -+ mfs->mfsrr_bytes = bavail; -+ AuDbg("b%d\n", mfs->mfs_bindex); -+ au_kfree_rcu(st); -+} -+ -+static int au_wbr_create_mfs(struct dentry *dentry, unsigned int flags) -+{ -+ int err; -+ struct dentry *parent; -+ struct super_block *sb; -+ struct au_wbr_mfs *mfs; -+ -+ err = au_wbr_create_exp(dentry); -+ if (err >= 0) -+ goto out; -+ -+ sb = dentry->d_sb; -+ parent = NULL; -+ if (au_ftest_wbr(flags, PARENT)) -+ parent = dget_parent(dentry); -+ mfs = &au_sbi(sb)->si_wbr_mfs; -+ mutex_lock(&mfs->mfs_lock); -+ if (time_after(jiffies, mfs->mfs_jiffy + mfs->mfs_expire) -+ || mfs->mfs_bindex < 0 -+ || au_br_rdonly(au_sbr(sb, mfs->mfs_bindex))) -+ au_mfs(dentry, parent); -+ mutex_unlock(&mfs->mfs_lock); -+ err = mfs->mfs_bindex; -+ dput(parent); -+ -+ if (err >= 0) -+ err = au_wbr_nonopq(dentry, err); -+ -+out: -+ AuDbg("b%d\n", err); -+ return err; -+} -+ -+static int au_wbr_create_init_mfs(struct super_block *sb) -+{ -+ struct au_wbr_mfs *mfs; -+ -+ mfs = &au_sbi(sb)->si_wbr_mfs; -+ mutex_init(&mfs->mfs_lock); -+ mfs->mfs_jiffy = 0; -+ mfs->mfs_bindex = -EROFS; -+ -+ return 0; -+} -+ -+static int au_wbr_create_fin_mfs(struct super_block *sb __maybe_unused) -+{ -+ mutex_destroy(&au_sbi(sb)->si_wbr_mfs.mfs_lock); -+ return 0; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* top down regardless parent, and then mfs */ -+static int au_wbr_create_tdmfs(struct dentry *dentry, -+ unsigned int flags __maybe_unused) -+{ -+ int err; -+ aufs_bindex_t bwh, btail, bindex, bfound, bmfs; -+ unsigned long long watermark; -+ struct super_block *sb; -+ struct au_wbr_mfs *mfs; -+ struct au_branch *br; -+ struct dentry *parent; -+ -+ sb = dentry->d_sb; -+ mfs = &au_sbi(sb)->si_wbr_mfs; -+ mutex_lock(&mfs->mfs_lock); -+ if (time_after(jiffies, mfs->mfs_jiffy + mfs->mfs_expire) -+ || mfs->mfs_bindex < 0) -+ au_mfs(dentry, /*parent*/NULL); -+ watermark = mfs->mfsrr_watermark; -+ bmfs = mfs->mfs_bindex; -+ mutex_unlock(&mfs->mfs_lock); -+ -+ /* another style of au_wbr_create_exp() */ -+ bwh = au_dbwh(dentry); -+ parent = dget_parent(dentry); -+ btail = au_dbtaildir(parent); -+ if (bwh >= 0 && bwh < btail) -+ btail = bwh; -+ -+ err = au_wbr_nonopq(dentry, btail); -+ if (unlikely(err < 0)) -+ goto out; -+ btail = err; -+ bfound = -1; -+ for (bindex = 0; bindex <= btail; bindex++) { -+ br = au_sbr(sb, bindex); -+ if (au_br_rdonly(br)) -+ continue; -+ if (br->br_wbr->wbr_bytes > watermark) { -+ bfound = bindex; -+ break; -+ } -+ } -+ err = bfound; -+ if (err < 0) -+ err = bmfs; -+ -+out: -+ dput(parent); -+ AuDbg("b%d\n", err); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* most free space and then round robin */ -+static int au_wbr_create_mfsrr(struct dentry *dentry, unsigned int flags) -+{ -+ int err; -+ struct au_wbr_mfs *mfs; -+ -+ err = au_wbr_create_mfs(dentry, flags); -+ if (err >= 0) { -+ mfs = &au_sbi(dentry->d_sb)->si_wbr_mfs; -+ mutex_lock(&mfs->mfs_lock); -+ if (mfs->mfsrr_bytes < mfs->mfsrr_watermark) -+ err = au_wbr_create_rr(dentry, flags); -+ mutex_unlock(&mfs->mfs_lock); -+ } -+ -+ AuDbg("b%d\n", err); -+ return err; -+} -+ -+static int au_wbr_create_init_mfsrr(struct super_block *sb) -+{ -+ int err; -+ -+ au_wbr_create_init_mfs(sb); /* ignore */ -+ err = au_wbr_create_init_rr(sb); -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* top down parent and most free space */ -+static int au_wbr_create_pmfs(struct dentry *dentry, unsigned int flags) -+{ -+ int err, e2; -+ unsigned long long b; -+ aufs_bindex_t bindex, btop, bbot; -+ struct super_block *sb; -+ struct dentry *parent, *h_parent; -+ struct au_branch *br; -+ -+ err = au_wbr_create_tdp(dentry, flags); -+ if (unlikely(err < 0)) -+ goto out; -+ parent = dget_parent(dentry); -+ btop = au_dbtop(parent); -+ bbot = au_dbtaildir(parent); -+ if (btop == bbot) -+ goto out_parent; /* success */ -+ -+ e2 = au_wbr_create_mfs(dentry, flags); -+ if (e2 < 0) -+ goto out_parent; /* success */ -+ -+ /* when the available size is equal, select upper one */ -+ sb = dentry->d_sb; -+ br = au_sbr(sb, err); -+ b = br->br_wbr->wbr_bytes; -+ AuDbg("b%d, %llu\n", err, b); -+ -+ for (bindex = btop; bindex <= bbot; bindex++) { -+ h_parent = au_h_dptr(parent, bindex); -+ if (!h_parent || d_is_negative(h_parent)) -+ continue; -+ -+ br = au_sbr(sb, bindex); -+ if (!au_br_rdonly(br) && br->br_wbr->wbr_bytes > b) { -+ b = br->br_wbr->wbr_bytes; -+ err = bindex; -+ AuDbg("b%d, %llu\n", err, b); -+ } -+ } -+ -+ if (err >= 0) -+ err = au_wbr_nonopq(dentry, err); -+ -+out_parent: -+ dput(parent); -+out: -+ AuDbg("b%d\n", err); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * - top down parent -+ * - most free space with parent -+ * - most free space round-robin regardless parent -+ */ -+static int au_wbr_create_pmfsrr(struct dentry *dentry, unsigned int flags) -+{ -+ int err; -+ unsigned long long watermark; -+ struct super_block *sb; -+ struct au_branch *br; -+ struct au_wbr_mfs *mfs; -+ -+ err = au_wbr_create_pmfs(dentry, flags | AuWbr_PARENT); -+ if (unlikely(err < 0)) -+ goto out; -+ -+ sb = dentry->d_sb; -+ br = au_sbr(sb, err); -+ mfs = &au_sbi(sb)->si_wbr_mfs; -+ mutex_lock(&mfs->mfs_lock); -+ watermark = mfs->mfsrr_watermark; -+ mutex_unlock(&mfs->mfs_lock); -+ if (br->br_wbr->wbr_bytes < watermark) -+ /* regardless the parent dir */ -+ err = au_wbr_create_mfsrr(dentry, flags); -+ -+out: -+ AuDbg("b%d\n", err); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* policies for copyup */ -+ -+/* top down parent */ -+static int au_wbr_copyup_tdp(struct dentry *dentry) -+{ -+ return au_wbr_create_tdp(dentry, /*flags, anything is ok*/0); -+} -+ -+/* bottom up parent */ -+static int au_wbr_copyup_bup(struct dentry *dentry) -+{ -+ int err; -+ aufs_bindex_t bindex, btop; -+ struct dentry *parent, *h_parent; -+ struct super_block *sb; -+ -+ err = -EROFS; -+ sb = dentry->d_sb; -+ parent = dget_parent(dentry); -+ btop = au_dbtop(parent); -+ for (bindex = au_dbtop(dentry); bindex >= btop; bindex--) { -+ h_parent = au_h_dptr(parent, bindex); -+ if (!h_parent || d_is_negative(h_parent)) -+ continue; -+ -+ if (!au_br_rdonly(au_sbr(sb, bindex))) { -+ err = bindex; -+ break; -+ } -+ } -+ dput(parent); -+ -+ /* bottom up here */ -+ if (unlikely(err < 0)) -+ err = au_wbr_bu(sb, btop - 1); -+ -+ AuDbg("b%d\n", err); -+ return err; -+} -+ -+/* bottom up */ -+int au_wbr_do_copyup_bu(struct dentry *dentry, aufs_bindex_t btop) -+{ -+ int err; -+ -+ err = au_wbr_bu(dentry->d_sb, btop); -+ AuDbg("b%d\n", err); -+ if (err > btop) -+ err = au_wbr_nonopq(dentry, err); -+ -+ AuDbg("b%d\n", err); -+ return err; -+} -+ -+static int au_wbr_copyup_bu(struct dentry *dentry) -+{ -+ int err; -+ aufs_bindex_t btop; -+ -+ btop = au_dbtop(dentry); -+ err = au_wbr_do_copyup_bu(dentry, btop); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct au_wbr_copyup_operations au_wbr_copyup_ops[] = { -+ [AuWbrCopyup_TDP] = { -+ .copyup = au_wbr_copyup_tdp -+ }, -+ [AuWbrCopyup_BUP] = { -+ .copyup = au_wbr_copyup_bup -+ }, -+ [AuWbrCopyup_BU] = { -+ .copyup = au_wbr_copyup_bu -+ } -+}; -+ -+struct au_wbr_create_operations au_wbr_create_ops[] = { -+ [AuWbrCreate_TDP] = { -+ .create = au_wbr_create_tdp -+ }, -+ [AuWbrCreate_RR] = { -+ .create = au_wbr_create_rr, -+ .init = au_wbr_create_init_rr -+ }, -+ [AuWbrCreate_MFS] = { -+ .create = au_wbr_create_mfs, -+ .init = au_wbr_create_init_mfs, -+ .fin = au_wbr_create_fin_mfs -+ }, -+ [AuWbrCreate_MFSV] = { -+ .create = au_wbr_create_mfs, -+ .init = au_wbr_create_init_mfs, -+ .fin = au_wbr_create_fin_mfs -+ }, -+ [AuWbrCreate_MFSRR] = { -+ .create = au_wbr_create_mfsrr, -+ .init = au_wbr_create_init_mfsrr, -+ .fin = au_wbr_create_fin_mfs -+ }, -+ [AuWbrCreate_MFSRRV] = { -+ .create = au_wbr_create_mfsrr, -+ .init = au_wbr_create_init_mfsrr, -+ .fin = au_wbr_create_fin_mfs -+ }, -+ [AuWbrCreate_TDMFS] = { -+ .create = au_wbr_create_tdmfs, -+ .init = au_wbr_create_init_mfs, -+ .fin = au_wbr_create_fin_mfs -+ }, -+ [AuWbrCreate_TDMFSV] = { -+ .create = au_wbr_create_tdmfs, -+ .init = au_wbr_create_init_mfs, -+ .fin = au_wbr_create_fin_mfs -+ }, -+ [AuWbrCreate_PMFS] = { -+ .create = au_wbr_create_pmfs, -+ .init = au_wbr_create_init_mfs, -+ .fin = au_wbr_create_fin_mfs -+ }, -+ [AuWbrCreate_PMFSV] = { -+ .create = au_wbr_create_pmfs, -+ .init = au_wbr_create_init_mfs, -+ .fin = au_wbr_create_fin_mfs -+ }, -+ [AuWbrCreate_PMFSRR] = { -+ .create = au_wbr_create_pmfsrr, -+ .init = au_wbr_create_init_mfsrr, -+ .fin = au_wbr_create_fin_mfs -+ }, -+ [AuWbrCreate_PMFSRRV] = { -+ .create = au_wbr_create_pmfsrr, -+ .init = au_wbr_create_init_mfsrr, -+ .fin = au_wbr_create_fin_mfs -+ } -+}; -diff -Nurp linux-5.10-rc6/fs/aufs/vdir.c linux-5.10-rc6.aufs/fs/aufs/vdir.c ---- linux-5.10-rc6/fs/aufs/vdir.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/vdir.c 2020-12-02 21:19:51.884036878 +0200 -@@ -0,0 +1,883 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * virtual or vertical directory -+ */ -+ -+#include -+#include "aufs.h" -+ -+static unsigned int calc_size(int nlen) -+{ -+ return ALIGN(sizeof(struct au_vdir_de) + nlen, sizeof(ino_t)); -+} -+ -+static int set_deblk_end(union au_vdir_deblk_p *p, -+ union au_vdir_deblk_p *deblk_end) -+{ -+ if (calc_size(0) <= deblk_end->deblk - p->deblk) { -+ p->de->de_str.len = 0; -+ /* smp_mb(); */ -+ return 0; -+ } -+ return -1; /* error */ -+} -+ -+/* returns true or false */ -+static int is_deblk_end(union au_vdir_deblk_p *p, -+ union au_vdir_deblk_p *deblk_end) -+{ -+ if (calc_size(0) <= deblk_end->deblk - p->deblk) -+ return !p->de->de_str.len; -+ return 1; -+} -+ -+static unsigned char *last_deblk(struct au_vdir *vdir) -+{ -+ return vdir->vd_deblk[vdir->vd_nblk - 1]; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* estimate the appropriate size for name hash table */ -+unsigned int au_rdhash_est(loff_t sz) -+{ -+ unsigned int n; -+ -+ n = UINT_MAX; -+ sz >>= 10; -+ if (sz < n) -+ n = sz; -+ if (sz < AUFS_RDHASH_DEF) -+ n = AUFS_RDHASH_DEF; -+ /* pr_info("n %u\n", n); */ -+ return n; -+} -+ -+/* -+ * the allocated memory has to be freed by -+ * au_nhash_wh_free() or au_nhash_de_free(). -+ */ -+int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp) -+{ -+ struct hlist_head *head; -+ unsigned int u; -+ size_t sz; -+ -+ sz = sizeof(*nhash->nh_head) * num_hash; -+ head = kmalloc(sz, gfp); -+ if (head) { -+ nhash->nh_num = num_hash; -+ nhash->nh_head = head; -+ for (u = 0; u < num_hash; u++) -+ INIT_HLIST_HEAD(head++); -+ return 0; /* success */ -+ } -+ -+ return -ENOMEM; -+} -+ -+static void nhash_count(struct hlist_head *head) -+{ -+#if 0 /* debugging */ -+ unsigned long n; -+ struct hlist_node *pos; -+ -+ n = 0; -+ hlist_for_each(pos, head) -+ n++; -+ pr_info("%lu\n", n); -+#endif -+} -+ -+static void au_nhash_wh_do_free(struct hlist_head *head) -+{ -+ struct au_vdir_wh *pos; -+ struct hlist_node *node; -+ -+ hlist_for_each_entry_safe(pos, node, head, wh_hash) -+ au_kfree_rcu(pos); -+} -+ -+static void au_nhash_de_do_free(struct hlist_head *head) -+{ -+ struct au_vdir_dehstr *pos; -+ struct hlist_node *node; -+ -+ hlist_for_each_entry_safe(pos, node, head, hash) -+ au_cache_free_vdir_dehstr(pos); -+} -+ -+static void au_nhash_do_free(struct au_nhash *nhash, -+ void (*free)(struct hlist_head *head)) -+{ -+ unsigned int n; -+ struct hlist_head *head; -+ -+ n = nhash->nh_num; -+ if (!n) -+ return; -+ -+ head = nhash->nh_head; -+ while (n-- > 0) { -+ nhash_count(head); -+ free(head++); -+ } -+ au_kfree_try_rcu(nhash->nh_head); -+} -+ -+void au_nhash_wh_free(struct au_nhash *whlist) -+{ -+ au_nhash_do_free(whlist, au_nhash_wh_do_free); -+} -+ -+static void au_nhash_de_free(struct au_nhash *delist) -+{ -+ au_nhash_do_free(delist, au_nhash_de_do_free); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt, -+ int limit) -+{ -+ int num; -+ unsigned int u, n; -+ struct hlist_head *head; -+ struct au_vdir_wh *pos; -+ -+ num = 0; -+ n = whlist->nh_num; -+ head = whlist->nh_head; -+ for (u = 0; u < n; u++, head++) -+ hlist_for_each_entry(pos, head, wh_hash) -+ if (pos->wh_bindex == btgt && ++num > limit) -+ return 1; -+ return 0; -+} -+ -+static struct hlist_head *au_name_hash(struct au_nhash *nhash, -+ unsigned char *name, -+ unsigned int len) -+{ -+ unsigned int v; -+ /* const unsigned int magic_bit = 12; */ -+ -+ AuDebugOn(!nhash->nh_num || !nhash->nh_head); -+ -+ v = 0; -+ if (len > 8) -+ len = 8; -+ while (len--) -+ v += *name++; -+ /* v = hash_long(v, magic_bit); */ -+ v %= nhash->nh_num; -+ return nhash->nh_head + v; -+} -+ -+static int au_nhash_test_name(struct au_vdir_destr *str, const char *name, -+ int nlen) -+{ -+ return str->len == nlen && !memcmp(str->name, name, nlen); -+} -+ -+/* returns found or not */ -+int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen) -+{ -+ struct hlist_head *head; -+ struct au_vdir_wh *pos; -+ struct au_vdir_destr *str; -+ -+ head = au_name_hash(whlist, name, nlen); -+ hlist_for_each_entry(pos, head, wh_hash) { -+ str = &pos->wh_str; -+ AuDbg("%.*s\n", str->len, str->name); -+ if (au_nhash_test_name(str, name, nlen)) -+ return 1; -+ } -+ return 0; -+} -+ -+/* returns found(true) or not */ -+static int test_known(struct au_nhash *delist, char *name, int nlen) -+{ -+ struct hlist_head *head; -+ struct au_vdir_dehstr *pos; -+ struct au_vdir_destr *str; -+ -+ head = au_name_hash(delist, name, nlen); -+ hlist_for_each_entry(pos, head, hash) { -+ str = pos->str; -+ AuDbg("%.*s\n", str->len, str->name); -+ if (au_nhash_test_name(str, name, nlen)) -+ return 1; -+ } -+ return 0; -+} -+ -+static void au_shwh_init_wh(struct au_vdir_wh *wh, ino_t ino, -+ unsigned char d_type) -+{ -+#ifdef CONFIG_AUFS_SHWH -+ wh->wh_ino = ino; -+ wh->wh_type = d_type; -+#endif -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino, -+ unsigned int d_type, aufs_bindex_t bindex, -+ unsigned char shwh) -+{ -+ int err; -+ struct au_vdir_destr *str; -+ struct au_vdir_wh *wh; -+ -+ AuDbg("%.*s\n", nlen, name); -+ AuDebugOn(!whlist->nh_num || !whlist->nh_head); -+ -+ err = -ENOMEM; -+ wh = kmalloc(sizeof(*wh) + nlen, GFP_NOFS); -+ if (unlikely(!wh)) -+ goto out; -+ -+ err = 0; -+ wh->wh_bindex = bindex; -+ if (shwh) -+ au_shwh_init_wh(wh, ino, d_type); -+ str = &wh->wh_str; -+ str->len = nlen; -+ memcpy(str->name, name, nlen); -+ hlist_add_head(&wh->wh_hash, au_name_hash(whlist, name, nlen)); -+ /* smp_mb(); */ -+ -+out: -+ return err; -+} -+ -+static int append_deblk(struct au_vdir *vdir) -+{ -+ int err; -+ unsigned long ul; -+ const unsigned int deblk_sz = vdir->vd_deblk_sz; -+ union au_vdir_deblk_p p, deblk_end; -+ unsigned char **o; -+ -+ err = -ENOMEM; -+ o = au_krealloc(vdir->vd_deblk, sizeof(*o) * (vdir->vd_nblk + 1), -+ GFP_NOFS, /*may_shrink*/0); -+ if (unlikely(!o)) -+ goto out; -+ -+ vdir->vd_deblk = o; -+ p.deblk = kmalloc(deblk_sz, GFP_NOFS); -+ if (p.deblk) { -+ ul = vdir->vd_nblk++; -+ vdir->vd_deblk[ul] = p.deblk; -+ vdir->vd_last.ul = ul; -+ vdir->vd_last.p.deblk = p.deblk; -+ deblk_end.deblk = p.deblk + deblk_sz; -+ err = set_deblk_end(&p, &deblk_end); -+ } -+ -+out: -+ return err; -+} -+ -+static int append_de(struct au_vdir *vdir, char *name, int nlen, ino_t ino, -+ unsigned int d_type, struct au_nhash *delist) -+{ -+ int err; -+ unsigned int sz; -+ const unsigned int deblk_sz = vdir->vd_deblk_sz; -+ union au_vdir_deblk_p p, *room, deblk_end; -+ struct au_vdir_dehstr *dehstr; -+ -+ p.deblk = last_deblk(vdir); -+ deblk_end.deblk = p.deblk + deblk_sz; -+ room = &vdir->vd_last.p; -+ AuDebugOn(room->deblk < p.deblk || deblk_end.deblk <= room->deblk -+ || !is_deblk_end(room, &deblk_end)); -+ -+ sz = calc_size(nlen); -+ if (unlikely(sz > deblk_end.deblk - room->deblk)) { -+ err = append_deblk(vdir); -+ if (unlikely(err)) -+ goto out; -+ -+ p.deblk = last_deblk(vdir); -+ deblk_end.deblk = p.deblk + deblk_sz; -+ /* smp_mb(); */ -+ AuDebugOn(room->deblk != p.deblk); -+ } -+ -+ err = -ENOMEM; -+ dehstr = au_cache_alloc_vdir_dehstr(); -+ if (unlikely(!dehstr)) -+ goto out; -+ -+ dehstr->str = &room->de->de_str; -+ hlist_add_head(&dehstr->hash, au_name_hash(delist, name, nlen)); -+ room->de->de_ino = ino; -+ room->de->de_type = d_type; -+ room->de->de_str.len = nlen; -+ memcpy(room->de->de_str.name, name, nlen); -+ -+ err = 0; -+ room->deblk += sz; -+ if (unlikely(set_deblk_end(room, &deblk_end))) -+ err = append_deblk(vdir); -+ /* smp_mb(); */ -+ -+out: -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+void au_vdir_free(struct au_vdir *vdir) -+{ -+ unsigned char **deblk; -+ -+ deblk = vdir->vd_deblk; -+ while (vdir->vd_nblk--) -+ au_kfree_try_rcu(*deblk++); -+ au_kfree_try_rcu(vdir->vd_deblk); -+ au_cache_free_vdir(vdir); -+} -+ -+static struct au_vdir *alloc_vdir(struct file *file) -+{ -+ struct au_vdir *vdir; -+ struct super_block *sb; -+ int err; -+ -+ sb = file->f_path.dentry->d_sb; -+ SiMustAnyLock(sb); -+ -+ err = -ENOMEM; -+ vdir = au_cache_alloc_vdir(); -+ if (unlikely(!vdir)) -+ goto out; -+ -+ vdir->vd_deblk = kzalloc(sizeof(*vdir->vd_deblk), GFP_NOFS); -+ if (unlikely(!vdir->vd_deblk)) -+ goto out_free; -+ -+ vdir->vd_deblk_sz = au_sbi(sb)->si_rdblk; -+ if (!vdir->vd_deblk_sz) { -+ /* estimate the appropriate size for deblk */ -+ vdir->vd_deblk_sz = au_dir_size(file, /*dentry*/NULL); -+ /* pr_info("vd_deblk_sz %u\n", vdir->vd_deblk_sz); */ -+ } -+ vdir->vd_nblk = 0; -+ vdir->vd_version = 0; -+ vdir->vd_jiffy = 0; -+ err = append_deblk(vdir); -+ if (!err) -+ return vdir; /* success */ -+ -+ au_kfree_try_rcu(vdir->vd_deblk); -+ -+out_free: -+ au_cache_free_vdir(vdir); -+out: -+ vdir = ERR_PTR(err); -+ return vdir; -+} -+ -+static int reinit_vdir(struct au_vdir *vdir) -+{ -+ int err; -+ union au_vdir_deblk_p p, deblk_end; -+ -+ while (vdir->vd_nblk > 1) { -+ au_kfree_try_rcu(vdir->vd_deblk[vdir->vd_nblk - 1]); -+ /* vdir->vd_deblk[vdir->vd_nblk - 1] = NULL; */ -+ vdir->vd_nblk--; -+ } -+ p.deblk = vdir->vd_deblk[0]; -+ deblk_end.deblk = p.deblk + vdir->vd_deblk_sz; -+ err = set_deblk_end(&p, &deblk_end); -+ /* keep vd_dblk_sz */ -+ vdir->vd_last.ul = 0; -+ vdir->vd_last.p.deblk = vdir->vd_deblk[0]; -+ vdir->vd_version = 0; -+ vdir->vd_jiffy = 0; -+ /* smp_mb(); */ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+#define AuFillVdir_CALLED 1 -+#define AuFillVdir_WHABLE (1 << 1) -+#define AuFillVdir_SHWH (1 << 2) -+#define au_ftest_fillvdir(flags, name) ((flags) & AuFillVdir_##name) -+#define au_fset_fillvdir(flags, name) \ -+ do { (flags) |= AuFillVdir_##name; } while (0) -+#define au_fclr_fillvdir(flags, name) \ -+ do { (flags) &= ~AuFillVdir_##name; } while (0) -+ -+#ifndef CONFIG_AUFS_SHWH -+#undef AuFillVdir_SHWH -+#define AuFillVdir_SHWH 0 -+#endif -+ -+struct fillvdir_arg { -+ struct dir_context ctx; -+ struct file *file; -+ struct au_vdir *vdir; -+ struct au_nhash delist; -+ struct au_nhash whlist; -+ aufs_bindex_t bindex; -+ unsigned int flags; -+ int err; -+}; -+ -+static int fillvdir(struct dir_context *ctx, const char *__name, int nlen, -+ loff_t offset __maybe_unused, u64 h_ino, -+ unsigned int d_type) -+{ -+ struct fillvdir_arg *arg = container_of(ctx, struct fillvdir_arg, ctx); -+ char *name = (void *)__name; -+ struct super_block *sb; -+ ino_t ino; -+ const unsigned char shwh = !!au_ftest_fillvdir(arg->flags, SHWH); -+ -+ arg->err = 0; -+ sb = arg->file->f_path.dentry->d_sb; -+ au_fset_fillvdir(arg->flags, CALLED); -+ /* smp_mb(); */ -+ if (nlen <= AUFS_WH_PFX_LEN -+ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) { -+ if (test_known(&arg->delist, name, nlen) -+ || au_nhash_test_known_wh(&arg->whlist, name, nlen)) -+ goto out; /* already exists or whiteouted */ -+ -+ arg->err = au_ino(sb, arg->bindex, h_ino, d_type, &ino); -+ if (!arg->err) { -+ if (unlikely(nlen > AUFS_MAX_NAMELEN)) -+ d_type = DT_UNKNOWN; -+ arg->err = append_de(arg->vdir, name, nlen, ino, -+ d_type, &arg->delist); -+ } -+ } else if (au_ftest_fillvdir(arg->flags, WHABLE)) { -+ name += AUFS_WH_PFX_LEN; -+ nlen -= AUFS_WH_PFX_LEN; -+ if (au_nhash_test_known_wh(&arg->whlist, name, nlen)) -+ goto out; /* already whiteouted */ -+ -+ ino = 0; /* just to suppress a warning */ -+ if (shwh) -+ arg->err = au_wh_ino(sb, arg->bindex, h_ino, d_type, -+ &ino); -+ if (!arg->err) { -+ if (nlen <= AUFS_MAX_NAMELEN + AUFS_WH_PFX_LEN) -+ d_type = DT_UNKNOWN; -+ arg->err = au_nhash_append_wh -+ (&arg->whlist, name, nlen, ino, d_type, -+ arg->bindex, shwh); -+ } -+ } -+ -+out: -+ if (!arg->err) -+ arg->vdir->vd_jiffy = jiffies; -+ /* smp_mb(); */ -+ AuTraceErr(arg->err); -+ return arg->err; -+} -+ -+static int au_handle_shwh(struct super_block *sb, struct au_vdir *vdir, -+ struct au_nhash *whlist, struct au_nhash *delist) -+{ -+#ifdef CONFIG_AUFS_SHWH -+ int err; -+ unsigned int nh, u; -+ struct hlist_head *head; -+ struct au_vdir_wh *pos; -+ struct hlist_node *n; -+ char *p, *o; -+ struct au_vdir_destr *destr; -+ -+ AuDebugOn(!au_opt_test(au_mntflags(sb), SHWH)); -+ -+ err = -ENOMEM; -+ o = p = (void *)__get_free_page(GFP_NOFS); -+ if (unlikely(!p)) -+ goto out; -+ -+ err = 0; -+ nh = whlist->nh_num; -+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN); -+ p += AUFS_WH_PFX_LEN; -+ for (u = 0; u < nh; u++) { -+ head = whlist->nh_head + u; -+ hlist_for_each_entry_safe(pos, n, head, wh_hash) { -+ destr = &pos->wh_str; -+ memcpy(p, destr->name, destr->len); -+ err = append_de(vdir, o, destr->len + AUFS_WH_PFX_LEN, -+ pos->wh_ino, pos->wh_type, delist); -+ if (unlikely(err)) -+ break; -+ } -+ } -+ -+ free_page((unsigned long)o); -+ -+out: -+ AuTraceErr(err); -+ return err; -+#else -+ return 0; -+#endif -+} -+ -+static int au_do_read_vdir(struct fillvdir_arg *arg) -+{ -+ int err; -+ unsigned int rdhash; -+ loff_t offset; -+ aufs_bindex_t bbot, bindex, btop; -+ unsigned char shwh; -+ struct file *hf, *file; -+ struct super_block *sb; -+ -+ file = arg->file; -+ sb = file->f_path.dentry->d_sb; -+ SiMustAnyLock(sb); -+ -+ rdhash = au_sbi(sb)->si_rdhash; -+ if (!rdhash) -+ rdhash = au_rdhash_est(au_dir_size(file, /*dentry*/NULL)); -+ err = au_nhash_alloc(&arg->delist, rdhash, GFP_NOFS); -+ if (unlikely(err)) -+ goto out; -+ err = au_nhash_alloc(&arg->whlist, rdhash, GFP_NOFS); -+ if (unlikely(err)) -+ goto out_delist; -+ -+ err = 0; -+ arg->flags = 0; -+ shwh = 0; -+ if (au_opt_test(au_mntflags(sb), SHWH)) { -+ shwh = 1; -+ au_fset_fillvdir(arg->flags, SHWH); -+ } -+ btop = au_fbtop(file); -+ bbot = au_fbbot_dir(file); -+ for (bindex = btop; !err && bindex <= bbot; bindex++) { -+ hf = au_hf_dir(file, bindex); -+ if (!hf) -+ continue; -+ -+ offset = vfsub_llseek(hf, 0, SEEK_SET); -+ err = offset; -+ if (unlikely(offset)) -+ break; -+ -+ arg->bindex = bindex; -+ au_fclr_fillvdir(arg->flags, WHABLE); -+ if (shwh -+ || (bindex != bbot -+ && au_br_whable(au_sbr_perm(sb, bindex)))) -+ au_fset_fillvdir(arg->flags, WHABLE); -+ do { -+ arg->err = 0; -+ au_fclr_fillvdir(arg->flags, CALLED); -+ /* smp_mb(); */ -+ err = vfsub_iterate_dir(hf, &arg->ctx); -+ if (err >= 0) -+ err = arg->err; -+ } while (!err && au_ftest_fillvdir(arg->flags, CALLED)); -+ -+ /* -+ * dir_relax() may be good for concurrency, but aufs should not -+ * use it since it will cause a lockdep problem. -+ */ -+ } -+ -+ if (!err && shwh) -+ err = au_handle_shwh(sb, arg->vdir, &arg->whlist, &arg->delist); -+ -+ au_nhash_wh_free(&arg->whlist); -+ -+out_delist: -+ au_nhash_de_free(&arg->delist); -+out: -+ return err; -+} -+ -+static int read_vdir(struct file *file, int may_read) -+{ -+ int err; -+ unsigned long expire; -+ unsigned char do_read; -+ struct fillvdir_arg arg = { -+ .ctx = { -+ .actor = fillvdir -+ } -+ }; -+ struct inode *inode; -+ struct au_vdir *vdir, *allocated; -+ -+ err = 0; -+ inode = file_inode(file); -+ IMustLock(inode); -+ IiMustWriteLock(inode); -+ SiMustAnyLock(inode->i_sb); -+ -+ allocated = NULL; -+ do_read = 0; -+ expire = au_sbi(inode->i_sb)->si_rdcache; -+ vdir = au_ivdir(inode); -+ if (!vdir) { -+ do_read = 1; -+ vdir = alloc_vdir(file); -+ err = PTR_ERR(vdir); -+ if (IS_ERR(vdir)) -+ goto out; -+ err = 0; -+ allocated = vdir; -+ } else if (may_read -+ && (!inode_eq_iversion(inode, vdir->vd_version) -+ || time_after(jiffies, vdir->vd_jiffy + expire))) { -+ do_read = 1; -+ err = reinit_vdir(vdir); -+ if (unlikely(err)) -+ goto out; -+ } -+ -+ if (!do_read) -+ return 0; /* success */ -+ -+ arg.file = file; -+ arg.vdir = vdir; -+ err = au_do_read_vdir(&arg); -+ if (!err) { -+ /* file->f_pos = 0; */ /* todo: ctx->pos? */ -+ vdir->vd_version = inode_query_iversion(inode); -+ vdir->vd_last.ul = 0; -+ vdir->vd_last.p.deblk = vdir->vd_deblk[0]; -+ if (allocated) -+ au_set_ivdir(inode, allocated); -+ } else if (allocated) -+ au_vdir_free(allocated); -+ -+out: -+ return err; -+} -+ -+static int copy_vdir(struct au_vdir *tgt, struct au_vdir *src) -+{ -+ int err, rerr; -+ unsigned long ul, n; -+ const unsigned int deblk_sz = src->vd_deblk_sz; -+ -+ AuDebugOn(tgt->vd_nblk != 1); -+ -+ err = -ENOMEM; -+ if (tgt->vd_nblk < src->vd_nblk) { -+ unsigned char **p; -+ -+ p = au_krealloc(tgt->vd_deblk, sizeof(*p) * src->vd_nblk, -+ GFP_NOFS, /*may_shrink*/0); -+ if (unlikely(!p)) -+ goto out; -+ tgt->vd_deblk = p; -+ } -+ -+ if (tgt->vd_deblk_sz != deblk_sz) { -+ unsigned char *p; -+ -+ tgt->vd_deblk_sz = deblk_sz; -+ p = au_krealloc(tgt->vd_deblk[0], deblk_sz, GFP_NOFS, -+ /*may_shrink*/1); -+ if (unlikely(!p)) -+ goto out; -+ tgt->vd_deblk[0] = p; -+ } -+ memcpy(tgt->vd_deblk[0], src->vd_deblk[0], deblk_sz); -+ tgt->vd_version = src->vd_version; -+ tgt->vd_jiffy = src->vd_jiffy; -+ -+ n = src->vd_nblk; -+ for (ul = 1; ul < n; ul++) { -+ tgt->vd_deblk[ul] = kmemdup(src->vd_deblk[ul], deblk_sz, -+ GFP_NOFS); -+ if (unlikely(!tgt->vd_deblk[ul])) -+ goto out; -+ tgt->vd_nblk++; -+ } -+ tgt->vd_nblk = n; -+ tgt->vd_last.ul = tgt->vd_last.ul; -+ tgt->vd_last.p.deblk = tgt->vd_deblk[tgt->vd_last.ul]; -+ tgt->vd_last.p.deblk += src->vd_last.p.deblk -+ - src->vd_deblk[src->vd_last.ul]; -+ /* smp_mb(); */ -+ return 0; /* success */ -+ -+out: -+ rerr = reinit_vdir(tgt); -+ BUG_ON(rerr); -+ return err; -+} -+ -+int au_vdir_init(struct file *file) -+{ -+ int err; -+ struct inode *inode; -+ struct au_vdir *vdir_cache, *allocated; -+ -+ /* test file->f_pos here instead of ctx->pos */ -+ err = read_vdir(file, !file->f_pos); -+ if (unlikely(err)) -+ goto out; -+ -+ allocated = NULL; -+ vdir_cache = au_fvdir_cache(file); -+ if (!vdir_cache) { -+ vdir_cache = alloc_vdir(file); -+ err = PTR_ERR(vdir_cache); -+ if (IS_ERR(vdir_cache)) -+ goto out; -+ allocated = vdir_cache; -+ } else if (!file->f_pos && vdir_cache->vd_version != file->f_version) { -+ /* test file->f_pos here instead of ctx->pos */ -+ err = reinit_vdir(vdir_cache); -+ if (unlikely(err)) -+ goto out; -+ } else -+ return 0; /* success */ -+ -+ inode = file_inode(file); -+ err = copy_vdir(vdir_cache, au_ivdir(inode)); -+ if (!err) { -+ file->f_version = inode_query_iversion(inode); -+ if (allocated) -+ au_set_fvdir_cache(file, allocated); -+ } else if (allocated) -+ au_vdir_free(allocated); -+ -+out: -+ return err; -+} -+ -+static loff_t calc_offset(struct au_vdir *vdir) -+{ -+ loff_t offset; -+ union au_vdir_deblk_p p; -+ -+ p.deblk = vdir->vd_deblk[vdir->vd_last.ul]; -+ offset = vdir->vd_last.p.deblk - p.deblk; -+ offset += vdir->vd_deblk_sz * vdir->vd_last.ul; -+ return offset; -+} -+ -+/* returns true or false */ -+static int seek_vdir(struct file *file, struct dir_context *ctx) -+{ -+ int valid; -+ unsigned int deblk_sz; -+ unsigned long ul, n; -+ loff_t offset; -+ union au_vdir_deblk_p p, deblk_end; -+ struct au_vdir *vdir_cache; -+ -+ valid = 1; -+ vdir_cache = au_fvdir_cache(file); -+ offset = calc_offset(vdir_cache); -+ AuDbg("offset %lld\n", offset); -+ if (ctx->pos == offset) -+ goto out; -+ -+ vdir_cache->vd_last.ul = 0; -+ vdir_cache->vd_last.p.deblk = vdir_cache->vd_deblk[0]; -+ if (!ctx->pos) -+ goto out; -+ -+ valid = 0; -+ deblk_sz = vdir_cache->vd_deblk_sz; -+ ul = div64_u64(ctx->pos, deblk_sz); -+ AuDbg("ul %lu\n", ul); -+ if (ul >= vdir_cache->vd_nblk) -+ goto out; -+ -+ n = vdir_cache->vd_nblk; -+ for (; ul < n; ul++) { -+ p.deblk = vdir_cache->vd_deblk[ul]; -+ deblk_end.deblk = p.deblk + deblk_sz; -+ offset = ul; -+ offset *= deblk_sz; -+ while (!is_deblk_end(&p, &deblk_end) && offset < ctx->pos) { -+ unsigned int l; -+ -+ l = calc_size(p.de->de_str.len); -+ offset += l; -+ p.deblk += l; -+ } -+ if (!is_deblk_end(&p, &deblk_end)) { -+ valid = 1; -+ vdir_cache->vd_last.ul = ul; -+ vdir_cache->vd_last.p = p; -+ break; -+ } -+ } -+ -+out: -+ /* smp_mb(); */ -+ if (!valid) -+ AuDbg("valid %d\n", !valid); -+ return valid; -+} -+ -+int au_vdir_fill_de(struct file *file, struct dir_context *ctx) -+{ -+ unsigned int l, deblk_sz; -+ union au_vdir_deblk_p deblk_end; -+ struct au_vdir *vdir_cache; -+ struct au_vdir_de *de; -+ -+ if (!seek_vdir(file, ctx)) -+ return 0; -+ -+ vdir_cache = au_fvdir_cache(file); -+ deblk_sz = vdir_cache->vd_deblk_sz; -+ while (1) { -+ deblk_end.deblk = vdir_cache->vd_deblk[vdir_cache->vd_last.ul]; -+ deblk_end.deblk += deblk_sz; -+ while (!is_deblk_end(&vdir_cache->vd_last.p, &deblk_end)) { -+ de = vdir_cache->vd_last.p.de; -+ AuDbg("%.*s, off%lld, i%lu, dt%d\n", -+ de->de_str.len, de->de_str.name, ctx->pos, -+ (unsigned long)de->de_ino, de->de_type); -+ if (unlikely(!dir_emit(ctx, de->de_str.name, -+ de->de_str.len, de->de_ino, -+ de->de_type))) { -+ /* todo: ignore the error caused by udba? */ -+ /* return err; */ -+ return 0; -+ } -+ -+ l = calc_size(de->de_str.len); -+ vdir_cache->vd_last.p.deblk += l; -+ ctx->pos += l; -+ } -+ if (vdir_cache->vd_last.ul < vdir_cache->vd_nblk - 1) { -+ vdir_cache->vd_last.ul++; -+ vdir_cache->vd_last.p.deblk -+ = vdir_cache->vd_deblk[vdir_cache->vd_last.ul]; -+ ctx->pos = deblk_sz * vdir_cache->vd_last.ul; -+ continue; -+ } -+ break; -+ } -+ -+ /* smp_mb(); */ -+ return 0; -+} -diff -Nurp linux-5.10-rc6/fs/aufs/vfsub.c linux-5.10-rc6.aufs/fs/aufs/vfsub.c ---- linux-5.10-rc6/fs/aufs/vfsub.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/vfsub.c 2020-12-02 21:19:51.884036878 +0200 -@@ -0,0 +1,882 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * sub-routines for VFS -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include "aufs.h" -+ -+#ifdef CONFIG_AUFS_BR_FUSE -+int vfsub_test_mntns(struct vfsmount *mnt, struct super_block *h_sb) -+{ -+ if (!au_test_fuse(h_sb) || !au_userns) -+ return 0; -+ -+ return is_current_mnt_ns(mnt) ? 0 : -EACCES; -+} -+#endif -+ -+int vfsub_sync_filesystem(struct super_block *h_sb, int wait) -+{ -+ int err; -+ -+ lockdep_off(); -+ down_read(&h_sb->s_umount); -+ err = __sync_filesystem(h_sb, wait); -+ up_read(&h_sb->s_umount); -+ lockdep_on(); -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+int vfsub_update_h_iattr(struct path *h_path, int *did) -+{ -+ int err; -+ struct kstat st; -+ struct super_block *h_sb; -+ -+ /* for remote fs, leave work for its getattr or d_revalidate */ -+ /* for bad i_attr fs, handle them in aufs_getattr() */ -+ /* still some fs may acquire i_mutex. we need to skip them */ -+ err = 0; -+ if (!did) -+ did = &err; -+ h_sb = h_path->dentry->d_sb; -+ *did = (!au_test_fs_remote(h_sb) && au_test_fs_refresh_iattr(h_sb)); -+ if (*did) -+ err = vfsub_getattr(h_path, &st); -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct file *vfsub_dentry_open(struct path *path, int flags) -+{ -+ return dentry_open(path, flags /* | __FMODE_NONOTIFY */, -+ current_cred()); -+} -+ -+struct file *vfsub_filp_open(const char *path, int oflags, int mode) -+{ -+ struct file *file; -+ -+ lockdep_off(); -+ file = filp_open(path, -+ oflags /* | __FMODE_NONOTIFY */, -+ mode); -+ lockdep_on(); -+ if (IS_ERR(file)) -+ goto out; -+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/ -+ -+out: -+ return file; -+} -+ -+/* -+ * Ideally this function should call VFS:do_last() in order to keep all its -+ * checkings. But it is very hard for aufs to regenerate several VFS internal -+ * structure such as nameidata. This is a second (or third) best approach. -+ * cf. linux/fs/namei.c:do_last(), lookup_open() and atomic_open(). -+ */ -+int vfsub_atomic_open(struct inode *dir, struct dentry *dentry, -+ struct vfsub_aopen_args *args) -+{ -+ int err; -+ struct au_branch *br = args->br; -+ struct file *file = args->file; -+ /* copied from linux/fs/namei.c:atomic_open() */ -+ struct dentry *const DENTRY_NOT_SET = (void *)-1UL; -+ -+ IMustLock(dir); -+ AuDebugOn(!dir->i_op->atomic_open); -+ -+ err = au_br_test_oflag(args->open_flag, br); -+ if (unlikely(err)) -+ goto out; -+ -+ au_lcnt_inc(&br->br_nfiles); -+ file->f_path.dentry = DENTRY_NOT_SET; -+ file->f_path.mnt = au_br_mnt(br); -+ AuDbg("%ps\n", dir->i_op->atomic_open); -+ err = dir->i_op->atomic_open(dir, dentry, file, args->open_flag, -+ args->create_mode); -+ if (unlikely(err < 0)) { -+ au_lcnt_dec(&br->br_nfiles); -+ goto out; -+ } -+ -+ /* temporary workaround for nfsv4 branch */ -+ if (au_test_nfs(dir->i_sb)) -+ nfs_mark_for_revalidate(dir); -+ -+ if (file->f_mode & FMODE_CREATED) -+ fsnotify_create(dir, dentry); -+ if (!(file->f_mode & FMODE_OPENED)) { -+ au_lcnt_dec(&br->br_nfiles); -+ goto out; -+ } -+ -+ /* todo: call VFS:may_open() here */ -+ /* todo: ima_file_check() too? */ -+ if (!err && (args->open_flag & __FMODE_EXEC)) -+ err = deny_write_access(file); -+ if (!err) -+ fsnotify_open(file); -+ else -+ au_lcnt_dec(&br->br_nfiles); -+ /* note that the file is created and still opened */ -+ -+out: -+ return err; -+} -+ -+int vfsub_kern_path(const char *name, unsigned int flags, struct path *path) -+{ -+ int err; -+ -+ err = kern_path(name, flags, path); -+ if (!err && d_is_positive(path->dentry)) -+ vfsub_update_h_iattr(path, /*did*/NULL); /*ignore*/ -+ return err; -+} -+ -+struct dentry *vfsub_lookup_one_len_unlocked(const char *name, -+ struct dentry *parent, int len) -+{ -+ struct path path = { -+ .mnt = NULL -+ }; -+ -+ path.dentry = lookup_one_len_unlocked(name, parent, len); -+ if (IS_ERR(path.dentry)) -+ goto out; -+ if (d_is_positive(path.dentry)) -+ vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/ -+ -+out: -+ AuTraceErrPtr(path.dentry); -+ return path.dentry; -+} -+ -+struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent, -+ int len) -+{ -+ struct path path = { -+ .mnt = NULL -+ }; -+ -+ /* VFS checks it too, but by WARN_ON_ONCE() */ -+ IMustLock(d_inode(parent)); -+ -+ path.dentry = lookup_one_len(name, parent, len); -+ if (IS_ERR(path.dentry)) -+ goto out; -+ if (d_is_positive(path.dentry)) -+ vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/ -+ -+out: -+ AuTraceErrPtr(path.dentry); -+ return path.dentry; -+} -+ -+void vfsub_call_lkup_one(void *args) -+{ -+ struct vfsub_lkup_one_args *a = args; -+ *a->errp = vfsub_lkup_one(a->name, a->parent); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1, -+ struct dentry *d2, struct au_hinode *hdir2) -+{ -+ struct dentry *d; -+ -+ lockdep_off(); -+ d = lock_rename(d1, d2); -+ lockdep_on(); -+ au_hn_suspend(hdir1); -+ if (hdir1 != hdir2) -+ au_hn_suspend(hdir2); -+ -+ return d; -+} -+ -+void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1, -+ struct dentry *d2, struct au_hinode *hdir2) -+{ -+ au_hn_resume(hdir1); -+ if (hdir1 != hdir2) -+ au_hn_resume(hdir2); -+ lockdep_off(); -+ unlock_rename(d1, d2); -+ lockdep_on(); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+int vfsub_create(struct inode *dir, struct path *path, int mode, bool want_excl) -+{ -+ int err; -+ struct dentry *d; -+ -+ IMustLock(dir); -+ -+ d = path->dentry; -+ path->dentry = d->d_parent; -+ err = security_path_mknod(path, d, mode, 0); -+ path->dentry = d; -+ if (unlikely(err)) -+ goto out; -+ -+ lockdep_off(); -+ err = vfs_create(dir, path->dentry, mode, want_excl); -+ lockdep_on(); -+ if (!err) { -+ struct path tmp = *path; -+ int did; -+ -+ vfsub_update_h_iattr(&tmp, &did); -+ if (did) { -+ tmp.dentry = path->dentry->d_parent; -+ vfsub_update_h_iattr(&tmp, /*did*/NULL); -+ } -+ /*ignore*/ -+ } -+ -+out: -+ return err; -+} -+ -+int vfsub_symlink(struct inode *dir, struct path *path, const char *symname) -+{ -+ int err; -+ struct dentry *d; -+ -+ IMustLock(dir); -+ -+ d = path->dentry; -+ path->dentry = d->d_parent; -+ err = security_path_symlink(path, d, symname); -+ path->dentry = d; -+ if (unlikely(err)) -+ goto out; -+ -+ lockdep_off(); -+ err = vfs_symlink(dir, path->dentry, symname); -+ lockdep_on(); -+ if (!err) { -+ struct path tmp = *path; -+ int did; -+ -+ vfsub_update_h_iattr(&tmp, &did); -+ if (did) { -+ tmp.dentry = path->dentry->d_parent; -+ vfsub_update_h_iattr(&tmp, /*did*/NULL); -+ } -+ /*ignore*/ -+ } -+ -+out: -+ return err; -+} -+ -+int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev) -+{ -+ int err; -+ struct dentry *d; -+ -+ IMustLock(dir); -+ -+ d = path->dentry; -+ path->dentry = d->d_parent; -+ err = security_path_mknod(path, d, mode, new_encode_dev(dev)); -+ path->dentry = d; -+ if (unlikely(err)) -+ goto out; -+ -+ lockdep_off(); -+ err = vfs_mknod(dir, path->dentry, mode, dev); -+ lockdep_on(); -+ if (!err) { -+ struct path tmp = *path; -+ int did; -+ -+ vfsub_update_h_iattr(&tmp, &did); -+ if (did) { -+ tmp.dentry = path->dentry->d_parent; -+ vfsub_update_h_iattr(&tmp, /*did*/NULL); -+ } -+ /*ignore*/ -+ } -+ -+out: -+ return err; -+} -+ -+static int au_test_nlink(struct inode *inode) -+{ -+ const unsigned int link_max = UINT_MAX >> 1; /* rough margin */ -+ -+ if (!au_test_fs_no_limit_nlink(inode->i_sb) -+ || inode->i_nlink < link_max) -+ return 0; -+ return -EMLINK; -+} -+ -+int vfsub_link(struct dentry *src_dentry, struct inode *dir, struct path *path, -+ struct inode **delegated_inode) -+{ -+ int err; -+ struct dentry *d; -+ -+ IMustLock(dir); -+ -+ err = au_test_nlink(d_inode(src_dentry)); -+ if (unlikely(err)) -+ return err; -+ -+ /* we don't call may_linkat() */ -+ d = path->dentry; -+ path->dentry = d->d_parent; -+ err = security_path_link(src_dentry, path, d); -+ path->dentry = d; -+ if (unlikely(err)) -+ goto out; -+ -+ lockdep_off(); -+ err = vfs_link(src_dentry, dir, path->dentry, delegated_inode); -+ lockdep_on(); -+ if (!err) { -+ struct path tmp = *path; -+ int did; -+ -+ /* fuse has different memory inode for the same inumber */ -+ vfsub_update_h_iattr(&tmp, &did); -+ if (did) { -+ tmp.dentry = path->dentry->d_parent; -+ vfsub_update_h_iattr(&tmp, /*did*/NULL); -+ tmp.dentry = src_dentry; -+ vfsub_update_h_iattr(&tmp, /*did*/NULL); -+ } -+ /*ignore*/ -+ } -+ -+out: -+ return err; -+} -+ -+int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry, -+ struct inode *dir, struct path *path, -+ struct inode **delegated_inode, unsigned int flags) -+{ -+ int err; -+ struct path tmp = { -+ .mnt = path->mnt -+ }; -+ struct dentry *d; -+ -+ IMustLock(dir); -+ IMustLock(src_dir); -+ -+ d = path->dentry; -+ path->dentry = d->d_parent; -+ tmp.dentry = src_dentry->d_parent; -+ err = security_path_rename(&tmp, src_dentry, path, d, /*flags*/0); -+ path->dentry = d; -+ if (unlikely(err)) -+ goto out; -+ -+ lockdep_off(); -+ err = vfs_rename(src_dir, src_dentry, dir, path->dentry, -+ delegated_inode, flags); -+ lockdep_on(); -+ if (!err) { -+ int did; -+ -+ tmp.dentry = d->d_parent; -+ vfsub_update_h_iattr(&tmp, &did); -+ if (did) { -+ tmp.dentry = src_dentry; -+ vfsub_update_h_iattr(&tmp, /*did*/NULL); -+ tmp.dentry = src_dentry->d_parent; -+ vfsub_update_h_iattr(&tmp, /*did*/NULL); -+ } -+ /*ignore*/ -+ } -+ -+out: -+ return err; -+} -+ -+int vfsub_mkdir(struct inode *dir, struct path *path, int mode) -+{ -+ int err; -+ struct dentry *d; -+ -+ IMustLock(dir); -+ -+ d = path->dentry; -+ path->dentry = d->d_parent; -+ err = security_path_mkdir(path, d, mode); -+ path->dentry = d; -+ if (unlikely(err)) -+ goto out; -+ -+ lockdep_off(); -+ err = vfs_mkdir(dir, path->dentry, mode); -+ lockdep_on(); -+ if (!err) { -+ struct path tmp = *path; -+ int did; -+ -+ vfsub_update_h_iattr(&tmp, &did); -+ if (did) { -+ tmp.dentry = path->dentry->d_parent; -+ vfsub_update_h_iattr(&tmp, /*did*/NULL); -+ } -+ /*ignore*/ -+ } -+ -+out: -+ return err; -+} -+ -+int vfsub_rmdir(struct inode *dir, struct path *path) -+{ -+ int err; -+ struct dentry *d; -+ -+ IMustLock(dir); -+ -+ d = path->dentry; -+ path->dentry = d->d_parent; -+ err = security_path_rmdir(path, d); -+ path->dentry = d; -+ if (unlikely(err)) -+ goto out; -+ -+ lockdep_off(); -+ err = vfs_rmdir(dir, path->dentry); -+ lockdep_on(); -+ if (!err) { -+ struct path tmp = { -+ .dentry = path->dentry->d_parent, -+ .mnt = path->mnt -+ }; -+ -+ vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/ -+ } -+ -+out: -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* todo: support mmap_sem? */ -+ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count, -+ loff_t *ppos) -+{ -+ ssize_t err; -+ -+ lockdep_off(); -+ err = vfs_read(file, ubuf, count, ppos); -+ lockdep_on(); -+ if (err >= 0) -+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/ -+ return err; -+} -+ -+/* todo: kernel_read()? */ -+ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count, -+ loff_t *ppos) -+{ -+ ssize_t err; -+ mm_segment_t oldfs; -+ union { -+ void *k; -+ char __user *u; -+ } buf; -+ -+ buf.k = kbuf; -+ oldfs = get_fs(); -+ set_fs(KERNEL_DS); -+ err = vfsub_read_u(file, buf.u, count, ppos); -+ set_fs(oldfs); -+ return err; -+} -+ -+ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count, -+ loff_t *ppos) -+{ -+ ssize_t err; -+ -+ lockdep_off(); -+ err = vfs_write(file, ubuf, count, ppos); -+ lockdep_on(); -+ if (err >= 0) -+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/ -+ return err; -+} -+ -+ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, loff_t *ppos) -+{ -+ ssize_t err; -+ mm_segment_t oldfs; -+ union { -+ void *k; -+ const char __user *u; -+ } buf; -+ -+ buf.k = kbuf; -+ oldfs = get_fs(); -+ set_fs(KERNEL_DS); -+ err = vfsub_write_u(file, buf.u, count, ppos); -+ set_fs(oldfs); -+ return err; -+} -+ -+int vfsub_flush(struct file *file, fl_owner_t id) -+{ -+ int err; -+ -+ err = 0; -+ if (file->f_op->flush) { -+ if (!au_test_nfs(file->f_path.dentry->d_sb)) -+ err = file->f_op->flush(file, id); -+ else { -+ lockdep_off(); -+ err = file->f_op->flush(file, id); -+ lockdep_on(); -+ } -+ if (!err) -+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); -+ /*ignore*/ -+ } -+ return err; -+} -+ -+int vfsub_iterate_dir(struct file *file, struct dir_context *ctx) -+{ -+ int err; -+ -+ AuDbg("%pD, ctx{%ps, %llu}\n", file, ctx->actor, ctx->pos); -+ -+ lockdep_off(); -+ err = iterate_dir(file, ctx); -+ lockdep_on(); -+ if (err >= 0) -+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/ -+ -+ return err; -+} -+ -+long vfsub_splice_to(struct file *in, loff_t *ppos, -+ struct pipe_inode_info *pipe, size_t len, -+ unsigned int flags) -+{ -+ long err; -+ -+ lockdep_off(); -+ err = do_splice_to(in, ppos, pipe, len, flags); -+ lockdep_on(); -+ file_accessed(in); -+ if (err >= 0) -+ vfsub_update_h_iattr(&in->f_path, /*did*/NULL); /*ignore*/ -+ return err; -+} -+ -+long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out, -+ loff_t *ppos, size_t len, unsigned int flags) -+{ -+ long err; -+ -+ lockdep_off(); -+ err = do_splice_from(pipe, out, ppos, len, flags); -+ lockdep_on(); -+ if (err >= 0) -+ vfsub_update_h_iattr(&out->f_path, /*did*/NULL); /*ignore*/ -+ return err; -+} -+ -+int vfsub_fsync(struct file *file, struct path *path, int datasync) -+{ -+ int err; -+ -+ /* file can be NULL */ -+ lockdep_off(); -+ err = vfs_fsync(file, datasync); -+ lockdep_on(); -+ if (!err) { -+ if (!path) { -+ AuDebugOn(!file); -+ path = &file->f_path; -+ } -+ vfsub_update_h_iattr(path, /*did*/NULL); /*ignore*/ -+ } -+ return err; -+} -+ -+/* cf. open.c:do_sys_truncate() and do_sys_ftruncate() */ -+int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr, -+ struct file *h_file) -+{ -+ int err; -+ struct inode *h_inode; -+ struct super_block *h_sb; -+ -+ if (!h_file) { -+ err = vfsub_truncate(h_path, length); -+ goto out; -+ } -+ -+ h_inode = d_inode(h_path->dentry); -+ h_sb = h_inode->i_sb; -+ lockdep_off(); -+ sb_start_write(h_sb); -+ lockdep_on(); -+ err = locks_verify_truncate(h_inode, h_file, length); -+ if (!err) -+ err = security_path_truncate(h_path); -+ if (!err) { -+ lockdep_off(); -+ err = do_truncate(h_path->dentry, length, attr, h_file); -+ lockdep_on(); -+ } -+ lockdep_off(); -+ sb_end_write(h_sb); -+ lockdep_on(); -+ -+out: -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct au_vfsub_mkdir_args { -+ int *errp; -+ struct inode *dir; -+ struct path *path; -+ int mode; -+}; -+ -+static void au_call_vfsub_mkdir(void *args) -+{ -+ struct au_vfsub_mkdir_args *a = args; -+ *a->errp = vfsub_mkdir(a->dir, a->path, a->mode); -+} -+ -+int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode) -+{ -+ int err, do_sio, wkq_err; -+ -+ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE); -+ if (!do_sio) { -+ lockdep_off(); -+ err = vfsub_mkdir(dir, path, mode); -+ lockdep_on(); -+ } else { -+ struct au_vfsub_mkdir_args args = { -+ .errp = &err, -+ .dir = dir, -+ .path = path, -+ .mode = mode -+ }; -+ wkq_err = au_wkq_wait(au_call_vfsub_mkdir, &args); -+ if (unlikely(wkq_err)) -+ err = wkq_err; -+ } -+ -+ return err; -+} -+ -+struct au_vfsub_rmdir_args { -+ int *errp; -+ struct inode *dir; -+ struct path *path; -+}; -+ -+static void au_call_vfsub_rmdir(void *args) -+{ -+ struct au_vfsub_rmdir_args *a = args; -+ *a->errp = vfsub_rmdir(a->dir, a->path); -+} -+ -+int vfsub_sio_rmdir(struct inode *dir, struct path *path) -+{ -+ int err, do_sio, wkq_err; -+ -+ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE); -+ if (!do_sio) { -+ lockdep_off(); -+ err = vfsub_rmdir(dir, path); -+ lockdep_on(); -+ } else { -+ struct au_vfsub_rmdir_args args = { -+ .errp = &err, -+ .dir = dir, -+ .path = path -+ }; -+ wkq_err = au_wkq_wait(au_call_vfsub_rmdir, &args); -+ if (unlikely(wkq_err)) -+ err = wkq_err; -+ } -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct notify_change_args { -+ int *errp; -+ struct path *path; -+ struct iattr *ia; -+ struct inode **delegated_inode; -+}; -+ -+static void call_notify_change(void *args) -+{ -+ struct notify_change_args *a = args; -+ struct inode *h_inode; -+ -+ h_inode = d_inode(a->path->dentry); -+ IMustLock(h_inode); -+ -+ *a->errp = -EPERM; -+ if (!IS_IMMUTABLE(h_inode) && !IS_APPEND(h_inode)) { -+ lockdep_off(); -+ *a->errp = notify_change(a->path->dentry, a->ia, -+ a->delegated_inode); -+ lockdep_on(); -+ if (!*a->errp) -+ vfsub_update_h_iattr(a->path, /*did*/NULL); /*ignore*/ -+ } -+ AuTraceErr(*a->errp); -+} -+ -+int vfsub_notify_change(struct path *path, struct iattr *ia, -+ struct inode **delegated_inode) -+{ -+ int err; -+ struct notify_change_args args = { -+ .errp = &err, -+ .path = path, -+ .ia = ia, -+ .delegated_inode = delegated_inode -+ }; -+ -+ call_notify_change(&args); -+ -+ return err; -+} -+ -+int vfsub_sio_notify_change(struct path *path, struct iattr *ia, -+ struct inode **delegated_inode) -+{ -+ int err, wkq_err; -+ struct notify_change_args args = { -+ .errp = &err, -+ .path = path, -+ .ia = ia, -+ .delegated_inode = delegated_inode -+ }; -+ -+ wkq_err = au_wkq_wait(call_notify_change, &args); -+ if (unlikely(wkq_err)) -+ err = wkq_err; -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct unlink_args { -+ int *errp; -+ struct inode *dir; -+ struct path *path; -+ struct inode **delegated_inode; -+}; -+ -+static void call_unlink(void *args) -+{ -+ struct unlink_args *a = args; -+ struct dentry *d = a->path->dentry; -+ struct inode *h_inode; -+ const int stop_sillyrename = (au_test_nfs(d->d_sb) -+ && au_dcount(d) == 1); -+ -+ IMustLock(a->dir); -+ -+ a->path->dentry = d->d_parent; -+ *a->errp = security_path_unlink(a->path, d); -+ a->path->dentry = d; -+ if (unlikely(*a->errp)) -+ return; -+ -+ if (!stop_sillyrename) -+ dget(d); -+ h_inode = NULL; -+ if (d_is_positive(d)) { -+ h_inode = d_inode(d); -+ ihold(h_inode); -+ } -+ -+ lockdep_off(); -+ *a->errp = vfs_unlink(a->dir, d, a->delegated_inode); -+ lockdep_on(); -+ if (!*a->errp) { -+ struct path tmp = { -+ .dentry = d->d_parent, -+ .mnt = a->path->mnt -+ }; -+ vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/ -+ } -+ -+ if (!stop_sillyrename) -+ dput(d); -+ if (h_inode) -+ iput(h_inode); -+ -+ AuTraceErr(*a->errp); -+} -+ -+/* -+ * @dir: must be locked. -+ * @dentry: target dentry. -+ */ -+int vfsub_unlink(struct inode *dir, struct path *path, -+ struct inode **delegated_inode, int force) -+{ -+ int err; -+ struct unlink_args args = { -+ .errp = &err, -+ .dir = dir, -+ .path = path, -+ .delegated_inode = delegated_inode -+ }; -+ -+ if (!force) -+ call_unlink(&args); -+ else { -+ int wkq_err; -+ -+ wkq_err = au_wkq_wait(call_unlink, &args); -+ if (unlikely(wkq_err)) -+ err = wkq_err; -+ } -+ -+ return err; -+} -diff -Nurp linux-5.10-rc6/fs/aufs/vfsub.h linux-5.10-rc6.aufs/fs/aufs/vfsub.h ---- linux-5.10-rc6/fs/aufs/vfsub.h 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/vfsub.h 2020-12-02 21:19:51.884036878 +0200 -@@ -0,0 +1,341 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * sub-routines for VFS -+ */ -+ -+#ifndef __AUFS_VFSUB_H__ -+#define __AUFS_VFSUB_H__ -+ -+#ifdef __KERNEL__ -+ -+#include -+#include -+#include -+#include -+#include "debug.h" -+ -+/* copied from linux/fs/internal.h */ -+/* todo: BAD approach!! */ -+extern void __mnt_drop_write(struct vfsmount *); -+extern struct file *alloc_empty_file(int, const struct cred *); -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* lock subclass for lower inode */ -+/* default MAX_LOCKDEP_SUBCLASSES(8) is not enough */ -+/* reduce? gave up. */ -+enum { -+ AuLsc_I_Begin = I_MUTEX_PARENT2, /* 5 */ -+ AuLsc_I_PARENT, /* lower inode, parent first */ -+ AuLsc_I_PARENT2, /* copyup dirs */ -+ AuLsc_I_PARENT3, /* copyup wh */ -+ AuLsc_I_CHILD, -+ AuLsc_I_CHILD2, -+ AuLsc_I_End -+}; -+ -+/* to debug easier, do not make them inlined functions */ -+#define MtxMustLock(mtx) AuDebugOn(!mutex_is_locked(mtx)) -+#define IMustLock(i) AuDebugOn(!inode_is_locked(i)) -+ -+/* ---------------------------------------------------------------------- */ -+ -+static inline void vfsub_drop_nlink(struct inode *inode) -+{ -+ AuDebugOn(!inode->i_nlink); -+ drop_nlink(inode); -+} -+ -+static inline void vfsub_dead_dir(struct inode *inode) -+{ -+ AuDebugOn(!S_ISDIR(inode->i_mode)); -+ inode->i_flags |= S_DEAD; -+ clear_nlink(inode); -+} -+ -+static inline int vfsub_native_ro(struct inode *inode) -+{ -+ return sb_rdonly(inode->i_sb) -+ || IS_RDONLY(inode) -+ /* || IS_APPEND(inode) */ -+ || IS_IMMUTABLE(inode); -+} -+ -+#ifdef CONFIG_AUFS_BR_FUSE -+int vfsub_test_mntns(struct vfsmount *mnt, struct super_block *h_sb); -+#else -+AuStubInt0(vfsub_test_mntns, struct vfsmount *mnt, struct super_block *h_sb); -+#endif -+ -+int vfsub_sync_filesystem(struct super_block *h_sb, int wait); -+ -+/* ---------------------------------------------------------------------- */ -+ -+int vfsub_update_h_iattr(struct path *h_path, int *did); -+struct file *vfsub_dentry_open(struct path *path, int flags); -+struct file *vfsub_filp_open(const char *path, int oflags, int mode); -+struct au_branch; -+struct vfsub_aopen_args { -+ struct file *file; -+ unsigned int open_flag; -+ umode_t create_mode; -+ struct au_branch *br; -+}; -+int vfsub_atomic_open(struct inode *dir, struct dentry *dentry, -+ struct vfsub_aopen_args *args); -+int vfsub_kern_path(const char *name, unsigned int flags, struct path *path); -+ -+struct dentry *vfsub_lookup_one_len_unlocked(const char *name, -+ struct dentry *parent, int len); -+struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent, -+ int len); -+ -+struct vfsub_lkup_one_args { -+ struct dentry **errp; -+ struct qstr *name; -+ struct dentry *parent; -+}; -+ -+static inline struct dentry *vfsub_lkup_one(struct qstr *name, -+ struct dentry *parent) -+{ -+ return vfsub_lookup_one_len(name->name, parent, name->len); -+} -+ -+void vfsub_call_lkup_one(void *args); -+ -+/* ---------------------------------------------------------------------- */ -+ -+static inline int vfsub_mnt_want_write(struct vfsmount *mnt) -+{ -+ int err; -+ -+ lockdep_off(); -+ err = mnt_want_write(mnt); -+ lockdep_on(); -+ return err; -+} -+ -+static inline void vfsub_mnt_drop_write(struct vfsmount *mnt) -+{ -+ lockdep_off(); -+ mnt_drop_write(mnt); -+ lockdep_on(); -+} -+ -+#if 0 /* reserved */ -+static inline void vfsub_mnt_drop_write_file(struct file *file) -+{ -+ lockdep_off(); -+ mnt_drop_write_file(file); -+ lockdep_on(); -+} -+#endif -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct au_hinode; -+struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1, -+ struct dentry *d2, struct au_hinode *hdir2); -+void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1, -+ struct dentry *d2, struct au_hinode *hdir2); -+ -+int vfsub_create(struct inode *dir, struct path *path, int mode, -+ bool want_excl); -+int vfsub_symlink(struct inode *dir, struct path *path, -+ const char *symname); -+int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev); -+int vfsub_link(struct dentry *src_dentry, struct inode *dir, -+ struct path *path, struct inode **delegated_inode); -+int vfsub_rename(struct inode *src_hdir, struct dentry *src_dentry, -+ struct inode *hdir, struct path *path, -+ struct inode **delegated_inode, unsigned int flags); -+int vfsub_mkdir(struct inode *dir, struct path *path, int mode); -+int vfsub_rmdir(struct inode *dir, struct path *path); -+ -+/* ---------------------------------------------------------------------- */ -+ -+ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count, -+ loff_t *ppos); -+ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count, -+ loff_t *ppos); -+ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count, -+ loff_t *ppos); -+ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, -+ loff_t *ppos); -+int vfsub_flush(struct file *file, fl_owner_t id); -+int vfsub_iterate_dir(struct file *file, struct dir_context *ctx); -+ -+static inline loff_t vfsub_f_size_read(struct file *file) -+{ -+ return i_size_read(file_inode(file)); -+} -+ -+static inline unsigned int vfsub_file_flags(struct file *file) -+{ -+ unsigned int flags; -+ -+ spin_lock(&file->f_lock); -+ flags = file->f_flags; -+ spin_unlock(&file->f_lock); -+ -+ return flags; -+} -+ -+static inline int vfsub_file_execed(struct file *file) -+{ -+ /* todo: direct access f_flags */ -+ return !!(vfsub_file_flags(file) & __FMODE_EXEC); -+} -+ -+#if 0 /* reserved */ -+static inline void vfsub_file_accessed(struct file *h_file) -+{ -+ file_accessed(h_file); -+ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL); /*ignore*/ -+} -+#endif -+ -+#if 0 /* reserved */ -+static inline void vfsub_touch_atime(struct vfsmount *h_mnt, -+ struct dentry *h_dentry) -+{ -+ struct path h_path = { -+ .dentry = h_dentry, -+ .mnt = h_mnt -+ }; -+ touch_atime(&h_path); -+ vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/ -+} -+#endif -+ -+static inline int vfsub_update_time(struct inode *h_inode, -+ struct timespec64 *ts, int flags) -+{ -+ return update_time(h_inode, ts, flags); -+ /* no vfsub_update_h_iattr() since we don't have struct path */ -+} -+ -+#ifdef CONFIG_FS_POSIX_ACL -+static inline int vfsub_acl_chmod(struct inode *h_inode, umode_t h_mode) -+{ -+ int err; -+ -+ err = posix_acl_chmod(h_inode, h_mode); -+ if (err == -EOPNOTSUPP) -+ err = 0; -+ return err; -+} -+#else -+AuStubInt0(vfsub_acl_chmod, struct inode *h_inode, umode_t h_mode); -+#endif -+ -+long vfsub_splice_to(struct file *in, loff_t *ppos, -+ struct pipe_inode_info *pipe, size_t len, -+ unsigned int flags); -+long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out, -+ loff_t *ppos, size_t len, unsigned int flags); -+ -+static inline long vfsub_truncate(struct path *path, loff_t length) -+{ -+ long err; -+ -+ lockdep_off(); -+ err = vfs_truncate(path, length); -+ lockdep_on(); -+ return err; -+} -+ -+int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr, -+ struct file *h_file); -+int vfsub_fsync(struct file *file, struct path *path, int datasync); -+ -+/* -+ * re-use branch fs's ioctl(FICLONE) while aufs itself doesn't support such -+ * ioctl. -+ */ -+static inline loff_t vfsub_clone_file_range(struct file *src, struct file *dst, -+ loff_t len) -+{ -+ loff_t err; -+ -+ lockdep_off(); -+ err = vfs_clone_file_range(src, 0, dst, 0, len, /*remap_flags*/0); -+ lockdep_on(); -+ -+ return err; -+} -+ -+/* copy_file_range(2) is a systemcall */ -+static inline ssize_t vfsub_copy_file_range(struct file *src, loff_t src_pos, -+ struct file *dst, loff_t dst_pos, -+ size_t len, unsigned int flags) -+{ -+ ssize_t ssz; -+ -+ lockdep_off(); -+ ssz = vfs_copy_file_range(src, src_pos, dst, dst_pos, len, flags); -+ lockdep_on(); -+ -+ return ssz; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static inline loff_t vfsub_llseek(struct file *file, loff_t offset, int origin) -+{ -+ loff_t err; -+ -+ lockdep_off(); -+ err = vfs_llseek(file, offset, origin); -+ lockdep_on(); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode); -+int vfsub_sio_rmdir(struct inode *dir, struct path *path); -+int vfsub_sio_notify_change(struct path *path, struct iattr *ia, -+ struct inode **delegated_inode); -+int vfsub_notify_change(struct path *path, struct iattr *ia, -+ struct inode **delegated_inode); -+int vfsub_unlink(struct inode *dir, struct path *path, -+ struct inode **delegated_inode, int force); -+ -+static inline int vfsub_getattr(const struct path *path, struct kstat *st) -+{ -+ return vfs_getattr(path, st, STATX_BASIC_STATS, AT_STATX_SYNC_AS_STAT); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static inline int vfsub_setxattr(struct dentry *dentry, const char *name, -+ const void *value, size_t size, int flags) -+{ -+ int err; -+ -+ lockdep_off(); -+ err = vfs_setxattr(dentry, name, value, size, flags); -+ lockdep_on(); -+ -+ return err; -+} -+ -+static inline int vfsub_removexattr(struct dentry *dentry, const char *name) -+{ -+ int err; -+ -+ lockdep_off(); -+ err = vfs_removexattr(dentry, name); -+ lockdep_on(); -+ -+ return err; -+} -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_VFSUB_H__ */ -diff -Nurp linux-5.10-rc6/fs/aufs/whout.c linux-5.10-rc6.aufs/fs/aufs/whout.c ---- linux-5.10-rc6/fs/aufs/whout.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/whout.c 2020-12-02 21:19:51.884036878 +0200 -@@ -0,0 +1,1049 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * whiteout for logical deletion and opaque directory -+ */ -+ -+#include "aufs.h" -+ -+#define WH_MASK 0444 -+ -+/* -+ * If a directory contains this file, then it is opaque. We start with the -+ * .wh. flag so that it is blocked by lookup. -+ */ -+static struct qstr diropq_name = QSTR_INIT(AUFS_WH_DIROPQ, -+ sizeof(AUFS_WH_DIROPQ) - 1); -+ -+/* -+ * generate whiteout name, which is NOT terminated by NULL. -+ * @name: original d_name.name -+ * @len: original d_name.len -+ * @wh: whiteout qstr -+ * returns zero when succeeds, otherwise error. -+ * succeeded value as wh->name should be freed by kfree(). -+ */ -+int au_wh_name_alloc(struct qstr *wh, const struct qstr *name) -+{ -+ char *p; -+ -+ if (unlikely(name->len > PATH_MAX - AUFS_WH_PFX_LEN)) -+ return -ENAMETOOLONG; -+ -+ wh->len = name->len + AUFS_WH_PFX_LEN; -+ p = kmalloc(wh->len, GFP_NOFS); -+ wh->name = p; -+ if (p) { -+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN); -+ memcpy(p + AUFS_WH_PFX_LEN, name->name, name->len); -+ /* smp_mb(); */ -+ return 0; -+ } -+ return -ENOMEM; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * test if the @wh_name exists under @h_parent. -+ * @try_sio specifies the necessary of super-io. -+ */ -+int au_wh_test(struct dentry *h_parent, struct qstr *wh_name, int try_sio) -+{ -+ int err; -+ struct dentry *wh_dentry; -+ -+ if (!try_sio) -+ wh_dentry = vfsub_lkup_one(wh_name, h_parent); -+ else -+ wh_dentry = au_sio_lkup_one(wh_name, h_parent); -+ err = PTR_ERR(wh_dentry); -+ if (IS_ERR(wh_dentry)) { -+ if (err == -ENAMETOOLONG) -+ err = 0; -+ goto out; -+ } -+ -+ err = 0; -+ if (d_is_negative(wh_dentry)) -+ goto out_wh; /* success */ -+ -+ err = 1; -+ if (d_is_reg(wh_dentry)) -+ goto out_wh; /* success */ -+ -+ err = -EIO; -+ AuIOErr("%pd Invalid whiteout entry type 0%o.\n", -+ wh_dentry, d_inode(wh_dentry)->i_mode); -+ -+out_wh: -+ dput(wh_dentry); -+out: -+ return err; -+} -+ -+/* -+ * test if the @h_dentry sets opaque or not. -+ */ -+int au_diropq_test(struct dentry *h_dentry) -+{ -+ int err; -+ struct inode *h_dir; -+ -+ h_dir = d_inode(h_dentry); -+ err = au_wh_test(h_dentry, &diropq_name, -+ au_test_h_perm_sio(h_dir, MAY_EXEC)); -+ return err; -+} -+ -+/* -+ * returns a negative dentry whose name is unique and temporary. -+ */ -+struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br, -+ struct qstr *prefix) -+{ -+ struct dentry *dentry; -+ int i; -+ char defname[NAME_MAX - AUFS_MAX_NAMELEN + DNAME_INLINE_LEN + 1], -+ *name, *p; -+ /* strict atomic_t is unnecessary here */ -+ static unsigned short cnt; -+ struct qstr qs; -+ -+ BUILD_BUG_ON(sizeof(cnt) * 2 > AUFS_WH_TMP_LEN); -+ -+ name = defname; -+ qs.len = sizeof(defname) - DNAME_INLINE_LEN + prefix->len - 1; -+ if (unlikely(prefix->len > DNAME_INLINE_LEN)) { -+ dentry = ERR_PTR(-ENAMETOOLONG); -+ if (unlikely(qs.len > NAME_MAX)) -+ goto out; -+ dentry = ERR_PTR(-ENOMEM); -+ name = kmalloc(qs.len + 1, GFP_NOFS); -+ if (unlikely(!name)) -+ goto out; -+ } -+ -+ /* doubly whiteout-ed */ -+ memcpy(name, AUFS_WH_PFX AUFS_WH_PFX, AUFS_WH_PFX_LEN * 2); -+ p = name + AUFS_WH_PFX_LEN * 2; -+ memcpy(p, prefix->name, prefix->len); -+ p += prefix->len; -+ *p++ = '.'; -+ AuDebugOn(name + qs.len + 1 - p <= AUFS_WH_TMP_LEN); -+ -+ qs.name = name; -+ for (i = 0; i < 3; i++) { -+ sprintf(p, "%.*x", AUFS_WH_TMP_LEN, cnt++); -+ dentry = au_sio_lkup_one(&qs, h_parent); -+ if (IS_ERR(dentry) || d_is_negative(dentry)) -+ goto out_name; -+ dput(dentry); -+ } -+ /* pr_warn("could not get random name\n"); */ -+ dentry = ERR_PTR(-EEXIST); -+ AuDbg("%.*s\n", AuLNPair(&qs)); -+ BUG(); -+ -+out_name: -+ if (name != defname) -+ au_kfree_try_rcu(name); -+out: -+ AuTraceErrPtr(dentry); -+ return dentry; -+} -+ -+/* -+ * rename the @h_dentry on @br to the whiteouted temporary name. -+ */ -+int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br) -+{ -+ int err; -+ struct path h_path = { -+ .mnt = au_br_mnt(br) -+ }; -+ struct inode *h_dir, *delegated; -+ struct dentry *h_parent; -+ -+ h_parent = h_dentry->d_parent; /* dir inode is locked */ -+ h_dir = d_inode(h_parent); -+ IMustLock(h_dir); -+ -+ h_path.dentry = au_whtmp_lkup(h_parent, br, &h_dentry->d_name); -+ err = PTR_ERR(h_path.dentry); -+ if (IS_ERR(h_path.dentry)) -+ goto out; -+ -+ /* under the same dir, no need to lock_rename() */ -+ delegated = NULL; -+ err = vfsub_rename(h_dir, h_dentry, h_dir, &h_path, &delegated, -+ /*flags*/0); -+ AuTraceErr(err); -+ if (unlikely(err == -EWOULDBLOCK)) { -+ pr_warn("cannot retry for NFSv4 delegation" -+ " for an internal rename\n"); -+ iput(delegated); -+ } -+ dput(h_path.dentry); -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+/* -+ * functions for removing a whiteout -+ */ -+ -+static int do_unlink_wh(struct inode *h_dir, struct path *h_path) -+{ -+ int err, force; -+ struct inode *delegated; -+ -+ /* -+ * forces superio when the dir has a sticky bit. -+ * this may be a violation of unix fs semantics. -+ */ -+ force = (h_dir->i_mode & S_ISVTX) -+ && !uid_eq(current_fsuid(), d_inode(h_path->dentry)->i_uid); -+ delegated = NULL; -+ err = vfsub_unlink(h_dir, h_path, &delegated, force); -+ if (unlikely(err == -EWOULDBLOCK)) { -+ pr_warn("cannot retry for NFSv4 delegation" -+ " for an internal unlink\n"); -+ iput(delegated); -+ } -+ return err; -+} -+ -+int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path, -+ struct dentry *dentry) -+{ -+ int err; -+ -+ err = do_unlink_wh(h_dir, h_path); -+ if (!err && dentry) -+ au_set_dbwh(dentry, -1); -+ -+ return err; -+} -+ -+static int unlink_wh_name(struct dentry *h_parent, struct qstr *wh, -+ struct au_branch *br) -+{ -+ int err; -+ struct path h_path = { -+ .mnt = au_br_mnt(br) -+ }; -+ -+ err = 0; -+ h_path.dentry = vfsub_lkup_one(wh, h_parent); -+ if (IS_ERR(h_path.dentry)) -+ err = PTR_ERR(h_path.dentry); -+ else { -+ if (d_is_reg(h_path.dentry)) -+ err = do_unlink_wh(d_inode(h_parent), &h_path); -+ dput(h_path.dentry); -+ } -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+/* -+ * initialize/clean whiteout for a branch -+ */ -+ -+static void au_wh_clean(struct inode *h_dir, struct path *whpath, -+ const int isdir) -+{ -+ int err; -+ struct inode *delegated; -+ -+ if (d_is_negative(whpath->dentry)) -+ return; -+ -+ if (isdir) -+ err = vfsub_rmdir(h_dir, whpath); -+ else { -+ delegated = NULL; -+ err = vfsub_unlink(h_dir, whpath, &delegated, /*force*/0); -+ if (unlikely(err == -EWOULDBLOCK)) { -+ pr_warn("cannot retry for NFSv4 delegation" -+ " for an internal unlink\n"); -+ iput(delegated); -+ } -+ } -+ if (unlikely(err)) -+ pr_warn("failed removing %pd (%d), ignored.\n", -+ whpath->dentry, err); -+} -+ -+static int test_linkable(struct dentry *h_root) -+{ -+ struct inode *h_dir = d_inode(h_root); -+ -+ if (h_dir->i_op->link) -+ return 0; -+ -+ pr_err("%pd (%s) doesn't support link(2), use noplink and rw+nolwh\n", -+ h_root, au_sbtype(h_root->d_sb)); -+ return -ENOSYS; /* the branch doesn't have its ->link() */ -+} -+ -+/* todo: should this mkdir be done in /sbin/mount.aufs helper? */ -+static int au_whdir(struct inode *h_dir, struct path *path) -+{ -+ int err; -+ -+ err = -EEXIST; -+ if (d_is_negative(path->dentry)) { -+ int mode = 0700; -+ -+ if (au_test_nfs(path->dentry->d_sb)) -+ mode |= 0111; -+ err = vfsub_mkdir(h_dir, path, mode); -+ } else if (d_is_dir(path->dentry)) -+ err = 0; -+ else -+ pr_err("unknown %pd exists\n", path->dentry); -+ -+ return err; -+} -+ -+struct au_wh_base { -+ const struct qstr *name; -+ struct dentry *dentry; -+}; -+ -+static void au_wh_init_ro(struct inode *h_dir, struct au_wh_base base[], -+ struct path *h_path) -+{ -+ h_path->dentry = base[AuBrWh_BASE].dentry; -+ au_wh_clean(h_dir, h_path, /*isdir*/0); -+ h_path->dentry = base[AuBrWh_PLINK].dentry; -+ au_wh_clean(h_dir, h_path, /*isdir*/1); -+ h_path->dentry = base[AuBrWh_ORPH].dentry; -+ au_wh_clean(h_dir, h_path, /*isdir*/1); -+} -+ -+/* -+ * returns tri-state, -+ * minus: error, caller should print the message -+ * zero: success -+ * plus: error, caller should NOT print the message -+ */ -+static int au_wh_init_rw_nolink(struct dentry *h_root, struct au_wbr *wbr, -+ int do_plink, struct au_wh_base base[], -+ struct path *h_path) -+{ -+ int err; -+ struct inode *h_dir; -+ -+ h_dir = d_inode(h_root); -+ h_path->dentry = base[AuBrWh_BASE].dentry; -+ au_wh_clean(h_dir, h_path, /*isdir*/0); -+ h_path->dentry = base[AuBrWh_PLINK].dentry; -+ if (do_plink) { -+ err = test_linkable(h_root); -+ if (unlikely(err)) { -+ err = 1; -+ goto out; -+ } -+ -+ err = au_whdir(h_dir, h_path); -+ if (unlikely(err)) -+ goto out; -+ wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry); -+ } else -+ au_wh_clean(h_dir, h_path, /*isdir*/1); -+ h_path->dentry = base[AuBrWh_ORPH].dentry; -+ err = au_whdir(h_dir, h_path); -+ if (unlikely(err)) -+ goto out; -+ wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry); -+ -+out: -+ return err; -+} -+ -+/* -+ * for the moment, aufs supports the branch filesystem which does not support -+ * link(2). testing on FAT which does not support i_op->setattr() fully either, -+ * copyup failed. finally, such filesystem will not be used as the writable -+ * branch. -+ * -+ * returns tri-state, see above. -+ */ -+static int au_wh_init_rw(struct dentry *h_root, struct au_wbr *wbr, -+ int do_plink, struct au_wh_base base[], -+ struct path *h_path) -+{ -+ int err; -+ struct inode *h_dir; -+ -+ WbrWhMustWriteLock(wbr); -+ -+ err = test_linkable(h_root); -+ if (unlikely(err)) { -+ err = 1; -+ goto out; -+ } -+ -+ /* -+ * todo: should this create be done in /sbin/mount.aufs helper? -+ */ -+ err = -EEXIST; -+ h_dir = d_inode(h_root); -+ if (d_is_negative(base[AuBrWh_BASE].dentry)) { -+ h_path->dentry = base[AuBrWh_BASE].dentry; -+ err = vfsub_create(h_dir, h_path, WH_MASK, /*want_excl*/true); -+ } else if (d_is_reg(base[AuBrWh_BASE].dentry)) -+ err = 0; -+ else -+ pr_err("unknown %pd2 exists\n", base[AuBrWh_BASE].dentry); -+ if (unlikely(err)) -+ goto out; -+ -+ h_path->dentry = base[AuBrWh_PLINK].dentry; -+ if (do_plink) { -+ err = au_whdir(h_dir, h_path); -+ if (unlikely(err)) -+ goto out; -+ wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry); -+ } else -+ au_wh_clean(h_dir, h_path, /*isdir*/1); -+ wbr->wbr_whbase = dget(base[AuBrWh_BASE].dentry); -+ -+ h_path->dentry = base[AuBrWh_ORPH].dentry; -+ err = au_whdir(h_dir, h_path); -+ if (unlikely(err)) -+ goto out; -+ wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry); -+ -+out: -+ return err; -+} -+ -+/* -+ * initialize the whiteout base file/dir for @br. -+ */ -+int au_wh_init(struct au_branch *br, struct super_block *sb) -+{ -+ int err, i; -+ const unsigned char do_plink -+ = !!au_opt_test(au_mntflags(sb), PLINK); -+ struct inode *h_dir; -+ struct path path = br->br_path; -+ struct dentry *h_root = path.dentry; -+ struct au_wbr *wbr = br->br_wbr; -+ static const struct qstr base_name[] = { -+ [AuBrWh_BASE] = QSTR_INIT(AUFS_BASE_NAME, -+ sizeof(AUFS_BASE_NAME) - 1), -+ [AuBrWh_PLINK] = QSTR_INIT(AUFS_PLINKDIR_NAME, -+ sizeof(AUFS_PLINKDIR_NAME) - 1), -+ [AuBrWh_ORPH] = QSTR_INIT(AUFS_ORPHDIR_NAME, -+ sizeof(AUFS_ORPHDIR_NAME) - 1) -+ }; -+ struct au_wh_base base[] = { -+ [AuBrWh_BASE] = { -+ .name = base_name + AuBrWh_BASE, -+ .dentry = NULL -+ }, -+ [AuBrWh_PLINK] = { -+ .name = base_name + AuBrWh_PLINK, -+ .dentry = NULL -+ }, -+ [AuBrWh_ORPH] = { -+ .name = base_name + AuBrWh_ORPH, -+ .dentry = NULL -+ } -+ }; -+ -+ if (wbr) -+ WbrWhMustWriteLock(wbr); -+ -+ for (i = 0; i < AuBrWh_Last; i++) { -+ /* doubly whiteouted */ -+ struct dentry *d; -+ -+ d = au_wh_lkup(h_root, (void *)base[i].name, br); -+ err = PTR_ERR(d); -+ if (IS_ERR(d)) -+ goto out; -+ -+ base[i].dentry = d; -+ AuDebugOn(wbr -+ && wbr->wbr_wh[i] -+ && wbr->wbr_wh[i] != base[i].dentry); -+ } -+ -+ if (wbr) -+ for (i = 0; i < AuBrWh_Last; i++) { -+ dput(wbr->wbr_wh[i]); -+ wbr->wbr_wh[i] = NULL; -+ } -+ -+ err = 0; -+ if (!au_br_writable(br->br_perm)) { -+ h_dir = d_inode(h_root); -+ au_wh_init_ro(h_dir, base, &path); -+ } else if (!au_br_wh_linkable(br->br_perm)) { -+ err = au_wh_init_rw_nolink(h_root, wbr, do_plink, base, &path); -+ if (err > 0) -+ goto out; -+ else if (err) -+ goto out_err; -+ } else { -+ err = au_wh_init_rw(h_root, wbr, do_plink, base, &path); -+ if (err > 0) -+ goto out; -+ else if (err) -+ goto out_err; -+ } -+ goto out; /* success */ -+ -+out_err: -+ pr_err("an error(%d) on the writable branch %pd(%s)\n", -+ err, h_root, au_sbtype(h_root->d_sb)); -+out: -+ for (i = 0; i < AuBrWh_Last; i++) -+ dput(base[i].dentry); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+/* -+ * whiteouts are all hard-linked usually. -+ * when its link count reaches a ceiling, we create a new whiteout base -+ * asynchronously. -+ */ -+ -+struct reinit_br_wh { -+ struct super_block *sb; -+ struct au_branch *br; -+}; -+ -+static void reinit_br_wh(void *arg) -+{ -+ int err; -+ aufs_bindex_t bindex; -+ struct path h_path; -+ struct reinit_br_wh *a = arg; -+ struct au_wbr *wbr; -+ struct inode *dir, *delegated; -+ struct dentry *h_root; -+ struct au_hinode *hdir; -+ -+ err = 0; -+ wbr = a->br->br_wbr; -+ /* big aufs lock */ -+ si_noflush_write_lock(a->sb); -+ if (!au_br_writable(a->br->br_perm)) -+ goto out; -+ bindex = au_br_index(a->sb, a->br->br_id); -+ if (unlikely(bindex < 0)) -+ goto out; -+ -+ di_read_lock_parent(a->sb->s_root, AuLock_IR); -+ dir = d_inode(a->sb->s_root); -+ hdir = au_hi(dir, bindex); -+ h_root = au_h_dptr(a->sb->s_root, bindex); -+ AuDebugOn(h_root != au_br_dentry(a->br)); -+ -+ au_hn_inode_lock_nested(hdir, AuLsc_I_PARENT); -+ wbr_wh_write_lock(wbr); -+ err = au_h_verify(wbr->wbr_whbase, au_opt_udba(a->sb), hdir->hi_inode, -+ h_root, a->br); -+ if (!err) { -+ h_path.dentry = wbr->wbr_whbase; -+ h_path.mnt = au_br_mnt(a->br); -+ delegated = NULL; -+ err = vfsub_unlink(hdir->hi_inode, &h_path, &delegated, -+ /*force*/0); -+ if (unlikely(err == -EWOULDBLOCK)) { -+ pr_warn("cannot retry for NFSv4 delegation" -+ " for an internal unlink\n"); -+ iput(delegated); -+ } -+ } else { -+ pr_warn("%pd is moved, ignored\n", wbr->wbr_whbase); -+ err = 0; -+ } -+ dput(wbr->wbr_whbase); -+ wbr->wbr_whbase = NULL; -+ if (!err) -+ err = au_wh_init(a->br, a->sb); -+ wbr_wh_write_unlock(wbr); -+ au_hn_inode_unlock(hdir); -+ di_read_unlock(a->sb->s_root, AuLock_IR); -+ if (!err) -+ au_fhsm_wrote(a->sb, bindex, /*force*/0); -+ -+out: -+ if (wbr) -+ atomic_dec(&wbr->wbr_wh_running); -+ au_lcnt_dec(&a->br->br_count); -+ si_write_unlock(a->sb); -+ au_nwt_done(&au_sbi(a->sb)->si_nowait); -+ au_kfree_rcu(a); -+ if (unlikely(err)) -+ AuIOErr("err %d\n", err); -+} -+ -+static void kick_reinit_br_wh(struct super_block *sb, struct au_branch *br) -+{ -+ int do_dec, wkq_err; -+ struct reinit_br_wh *arg; -+ -+ do_dec = 1; -+ if (atomic_inc_return(&br->br_wbr->wbr_wh_running) != 1) -+ goto out; -+ -+ /* ignore ENOMEM */ -+ arg = kmalloc(sizeof(*arg), GFP_NOFS); -+ if (arg) { -+ /* -+ * dec(wh_running), kfree(arg) and dec(br_count) -+ * in reinit function -+ */ -+ arg->sb = sb; -+ arg->br = br; -+ au_lcnt_inc(&br->br_count); -+ wkq_err = au_wkq_nowait(reinit_br_wh, arg, sb, /*flags*/0); -+ if (unlikely(wkq_err)) { -+ atomic_dec(&br->br_wbr->wbr_wh_running); -+ au_lcnt_dec(&br->br_count); -+ au_kfree_rcu(arg); -+ } -+ do_dec = 0; -+ } -+ -+out: -+ if (do_dec) -+ atomic_dec(&br->br_wbr->wbr_wh_running); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * create the whiteout @wh. -+ */ -+static int link_or_create_wh(struct super_block *sb, aufs_bindex_t bindex, -+ struct dentry *wh) -+{ -+ int err; -+ struct path h_path = { -+ .dentry = wh -+ }; -+ struct au_branch *br; -+ struct au_wbr *wbr; -+ struct dentry *h_parent; -+ struct inode *h_dir, *delegated; -+ -+ h_parent = wh->d_parent; /* dir inode is locked */ -+ h_dir = d_inode(h_parent); -+ IMustLock(h_dir); -+ -+ br = au_sbr(sb, bindex); -+ h_path.mnt = au_br_mnt(br); -+ wbr = br->br_wbr; -+ wbr_wh_read_lock(wbr); -+ if (wbr->wbr_whbase) { -+ delegated = NULL; -+ err = vfsub_link(wbr->wbr_whbase, h_dir, &h_path, &delegated); -+ if (unlikely(err == -EWOULDBLOCK)) { -+ pr_warn("cannot retry for NFSv4 delegation" -+ " for an internal link\n"); -+ iput(delegated); -+ } -+ if (!err || err != -EMLINK) -+ goto out; -+ -+ /* link count full. re-initialize br_whbase. */ -+ kick_reinit_br_wh(sb, br); -+ } -+ -+ /* return this error in this context */ -+ err = vfsub_create(h_dir, &h_path, WH_MASK, /*want_excl*/true); -+ if (!err) -+ au_fhsm_wrote(sb, bindex, /*force*/0); -+ -+out: -+ wbr_wh_read_unlock(wbr); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * create or remove the diropq. -+ */ -+static struct dentry *do_diropq(struct dentry *dentry, aufs_bindex_t bindex, -+ unsigned int flags) -+{ -+ struct dentry *opq_dentry, *h_dentry; -+ struct super_block *sb; -+ struct au_branch *br; -+ int err; -+ -+ sb = dentry->d_sb; -+ br = au_sbr(sb, bindex); -+ h_dentry = au_h_dptr(dentry, bindex); -+ opq_dentry = vfsub_lkup_one(&diropq_name, h_dentry); -+ if (IS_ERR(opq_dentry)) -+ goto out; -+ -+ if (au_ftest_diropq(flags, CREATE)) { -+ err = link_or_create_wh(sb, bindex, opq_dentry); -+ if (!err) { -+ au_set_dbdiropq(dentry, bindex); -+ goto out; /* success */ -+ } -+ } else { -+ struct path tmp = { -+ .dentry = opq_dentry, -+ .mnt = au_br_mnt(br) -+ }; -+ err = do_unlink_wh(au_h_iptr(d_inode(dentry), bindex), &tmp); -+ if (!err) -+ au_set_dbdiropq(dentry, -1); -+ } -+ dput(opq_dentry); -+ opq_dentry = ERR_PTR(err); -+ -+out: -+ return opq_dentry; -+} -+ -+struct do_diropq_args { -+ struct dentry **errp; -+ struct dentry *dentry; -+ aufs_bindex_t bindex; -+ unsigned int flags; -+}; -+ -+static void call_do_diropq(void *args) -+{ -+ struct do_diropq_args *a = args; -+ *a->errp = do_diropq(a->dentry, a->bindex, a->flags); -+} -+ -+struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex, -+ unsigned int flags) -+{ -+ struct dentry *diropq, *h_dentry; -+ -+ h_dentry = au_h_dptr(dentry, bindex); -+ if (!au_test_h_perm_sio(d_inode(h_dentry), MAY_EXEC | MAY_WRITE)) -+ diropq = do_diropq(dentry, bindex, flags); -+ else { -+ int wkq_err; -+ struct do_diropq_args args = { -+ .errp = &diropq, -+ .dentry = dentry, -+ .bindex = bindex, -+ .flags = flags -+ }; -+ -+ wkq_err = au_wkq_wait(call_do_diropq, &args); -+ if (unlikely(wkq_err)) -+ diropq = ERR_PTR(wkq_err); -+ } -+ -+ return diropq; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * lookup whiteout dentry. -+ * @h_parent: lower parent dentry which must exist and be locked -+ * @base_name: name of dentry which will be whiteouted -+ * returns dentry for whiteout. -+ */ -+struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name, -+ struct au_branch *br) -+{ -+ int err; -+ struct qstr wh_name; -+ struct dentry *wh_dentry; -+ -+ err = au_wh_name_alloc(&wh_name, base_name); -+ wh_dentry = ERR_PTR(err); -+ if (!err) { -+ wh_dentry = vfsub_lkup_one(&wh_name, h_parent); -+ au_kfree_try_rcu(wh_name.name); -+ } -+ return wh_dentry; -+} -+ -+/* -+ * link/create a whiteout for @dentry on @bindex. -+ */ -+struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex, -+ struct dentry *h_parent) -+{ -+ struct dentry *wh_dentry; -+ struct super_block *sb; -+ int err; -+ -+ sb = dentry->d_sb; -+ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, au_sbr(sb, bindex)); -+ if (!IS_ERR(wh_dentry) && d_is_negative(wh_dentry)) { -+ err = link_or_create_wh(sb, bindex, wh_dentry); -+ if (!err) { -+ au_set_dbwh(dentry, bindex); -+ au_fhsm_wrote(sb, bindex, /*force*/0); -+ } else { -+ dput(wh_dentry); -+ wh_dentry = ERR_PTR(err); -+ } -+ } -+ -+ return wh_dentry; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* Delete all whiteouts in this directory on branch bindex. */ -+static int del_wh_children(struct dentry *h_dentry, struct au_nhash *whlist, -+ aufs_bindex_t bindex, struct au_branch *br) -+{ -+ int err; -+ unsigned long ul, n; -+ struct qstr wh_name; -+ char *p; -+ struct hlist_head *head; -+ struct au_vdir_wh *pos; -+ struct au_vdir_destr *str; -+ -+ err = -ENOMEM; -+ p = (void *)__get_free_page(GFP_NOFS); -+ wh_name.name = p; -+ if (unlikely(!wh_name.name)) -+ goto out; -+ -+ err = 0; -+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN); -+ p += AUFS_WH_PFX_LEN; -+ n = whlist->nh_num; -+ head = whlist->nh_head; -+ for (ul = 0; !err && ul < n; ul++, head++) { -+ hlist_for_each_entry(pos, head, wh_hash) { -+ if (pos->wh_bindex != bindex) -+ continue; -+ -+ str = &pos->wh_str; -+ if (str->len + AUFS_WH_PFX_LEN <= PATH_MAX) { -+ memcpy(p, str->name, str->len); -+ wh_name.len = AUFS_WH_PFX_LEN + str->len; -+ err = unlink_wh_name(h_dentry, &wh_name, br); -+ if (!err) -+ continue; -+ break; -+ } -+ AuIOErr("whiteout name too long %.*s\n", -+ str->len, str->name); -+ err = -EIO; -+ break; -+ } -+ } -+ free_page((unsigned long)wh_name.name); -+ -+out: -+ return err; -+} -+ -+struct del_wh_children_args { -+ int *errp; -+ struct dentry *h_dentry; -+ struct au_nhash *whlist; -+ aufs_bindex_t bindex; -+ struct au_branch *br; -+}; -+ -+static void call_del_wh_children(void *args) -+{ -+ struct del_wh_children_args *a = args; -+ *a->errp = del_wh_children(a->h_dentry, a->whlist, a->bindex, a->br); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp) -+{ -+ struct au_whtmp_rmdir *whtmp; -+ int err; -+ unsigned int rdhash; -+ -+ SiMustAnyLock(sb); -+ -+ whtmp = kzalloc(sizeof(*whtmp), gfp); -+ if (unlikely(!whtmp)) { -+ whtmp = ERR_PTR(-ENOMEM); -+ goto out; -+ } -+ -+ /* no estimation for dir size */ -+ rdhash = au_sbi(sb)->si_rdhash; -+ if (!rdhash) -+ rdhash = AUFS_RDHASH_DEF; -+ err = au_nhash_alloc(&whtmp->whlist, rdhash, gfp); -+ if (unlikely(err)) { -+ au_kfree_rcu(whtmp); -+ whtmp = ERR_PTR(err); -+ } -+ -+out: -+ return whtmp; -+} -+ -+void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp) -+{ -+ if (whtmp->br) -+ au_lcnt_dec(&whtmp->br->br_count); -+ dput(whtmp->wh_dentry); -+ iput(whtmp->dir); -+ au_nhash_wh_free(&whtmp->whlist); -+ au_kfree_rcu(whtmp); -+} -+ -+/* -+ * rmdir the whiteouted temporary named dir @h_dentry. -+ * @whlist: whiteouted children. -+ */ -+int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex, -+ struct dentry *wh_dentry, struct au_nhash *whlist) -+{ -+ int err; -+ unsigned int h_nlink; -+ struct path h_tmp; -+ struct inode *wh_inode, *h_dir; -+ struct au_branch *br; -+ -+ h_dir = d_inode(wh_dentry->d_parent); /* dir inode is locked */ -+ IMustLock(h_dir); -+ -+ br = au_sbr(dir->i_sb, bindex); -+ wh_inode = d_inode(wh_dentry); -+ inode_lock_nested(wh_inode, AuLsc_I_CHILD); -+ -+ /* -+ * someone else might change some whiteouts while we were sleeping. -+ * it means this whlist may have an obsoleted entry. -+ */ -+ if (!au_test_h_perm_sio(wh_inode, MAY_EXEC | MAY_WRITE)) -+ err = del_wh_children(wh_dentry, whlist, bindex, br); -+ else { -+ int wkq_err; -+ struct del_wh_children_args args = { -+ .errp = &err, -+ .h_dentry = wh_dentry, -+ .whlist = whlist, -+ .bindex = bindex, -+ .br = br -+ }; -+ -+ wkq_err = au_wkq_wait(call_del_wh_children, &args); -+ if (unlikely(wkq_err)) -+ err = wkq_err; -+ } -+ inode_unlock(wh_inode); -+ -+ if (!err) { -+ h_tmp.dentry = wh_dentry; -+ h_tmp.mnt = au_br_mnt(br); -+ h_nlink = h_dir->i_nlink; -+ err = vfsub_rmdir(h_dir, &h_tmp); -+ /* some fs doesn't change the parent nlink in some cases */ -+ h_nlink -= h_dir->i_nlink; -+ } -+ -+ if (!err) { -+ if (au_ibtop(dir) == bindex) { -+ /* todo: dir->i_mutex is necessary */ -+ au_cpup_attr_timesizes(dir); -+ if (h_nlink) -+ vfsub_drop_nlink(dir); -+ } -+ return 0; /* success */ -+ } -+ -+ pr_warn("failed removing %pd(%d), ignored\n", wh_dentry, err); -+ return err; -+} -+ -+static void call_rmdir_whtmp(void *args) -+{ -+ int err; -+ aufs_bindex_t bindex; -+ struct au_whtmp_rmdir *a = args; -+ struct super_block *sb; -+ struct dentry *h_parent; -+ struct inode *h_dir; -+ struct au_hinode *hdir; -+ -+ /* rmdir by nfsd may cause deadlock with this i_mutex */ -+ /* inode_lock(a->dir); */ -+ err = -EROFS; -+ sb = a->dir->i_sb; -+ si_read_lock(sb, !AuLock_FLUSH); -+ if (!au_br_writable(a->br->br_perm)) -+ goto out; -+ bindex = au_br_index(sb, a->br->br_id); -+ if (unlikely(bindex < 0)) -+ goto out; -+ -+ err = -EIO; -+ ii_write_lock_parent(a->dir); -+ h_parent = dget_parent(a->wh_dentry); -+ h_dir = d_inode(h_parent); -+ hdir = au_hi(a->dir, bindex); -+ err = vfsub_mnt_want_write(au_br_mnt(a->br)); -+ if (unlikely(err)) -+ goto out_mnt; -+ au_hn_inode_lock_nested(hdir, AuLsc_I_PARENT); -+ err = au_h_verify(a->wh_dentry, au_opt_udba(sb), h_dir, h_parent, -+ a->br); -+ if (!err) -+ err = au_whtmp_rmdir(a->dir, bindex, a->wh_dentry, &a->whlist); -+ au_hn_inode_unlock(hdir); -+ vfsub_mnt_drop_write(au_br_mnt(a->br)); -+ -+out_mnt: -+ dput(h_parent); -+ ii_write_unlock(a->dir); -+out: -+ /* inode_unlock(a->dir); */ -+ au_whtmp_rmdir_free(a); -+ si_read_unlock(sb); -+ au_nwt_done(&au_sbi(sb)->si_nowait); -+ if (unlikely(err)) -+ AuIOErr("err %d\n", err); -+} -+ -+void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex, -+ struct dentry *wh_dentry, struct au_whtmp_rmdir *args) -+{ -+ int wkq_err; -+ struct super_block *sb; -+ -+ IMustLock(dir); -+ -+ /* all post-process will be done in do_rmdir_whtmp(). */ -+ sb = dir->i_sb; -+ args->dir = au_igrab(dir); -+ args->br = au_sbr(sb, bindex); -+ au_lcnt_inc(&args->br->br_count); -+ args->wh_dentry = dget(wh_dentry); -+ wkq_err = au_wkq_nowait(call_rmdir_whtmp, args, sb, /*flags*/0); -+ if (unlikely(wkq_err)) { -+ pr_warn("rmdir error %pd (%d), ignored\n", wh_dentry, wkq_err); -+ au_whtmp_rmdir_free(args); -+ } -+} -diff -Nurp linux-5.10-rc6/fs/aufs/whout.h linux-5.10-rc6.aufs/fs/aufs/whout.h ---- linux-5.10-rc6/fs/aufs/whout.h 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/whout.h 2020-12-02 21:19:51.884036878 +0200 -@@ -0,0 +1,73 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * whiteout for logical deletion and opaque directory -+ */ -+ -+#ifndef __AUFS_WHOUT_H__ -+#define __AUFS_WHOUT_H__ -+ -+#ifdef __KERNEL__ -+ -+#include "dir.h" -+ -+/* whout.c */ -+int au_wh_name_alloc(struct qstr *wh, const struct qstr *name); -+int au_wh_test(struct dentry *h_parent, struct qstr *wh_name, int try_sio); -+int au_diropq_test(struct dentry *h_dentry); -+struct au_branch; -+struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br, -+ struct qstr *prefix); -+int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br); -+int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path, -+ struct dentry *dentry); -+int au_wh_init(struct au_branch *br, struct super_block *sb); -+ -+/* diropq flags */ -+#define AuDiropq_CREATE 1 -+#define au_ftest_diropq(flags, name) ((flags) & AuDiropq_##name) -+#define au_fset_diropq(flags, name) \ -+ do { (flags) |= AuDiropq_##name; } while (0) -+#define au_fclr_diropq(flags, name) \ -+ do { (flags) &= ~AuDiropq_##name; } while (0) -+ -+struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex, -+ unsigned int flags); -+struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name, -+ struct au_branch *br); -+struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex, -+ struct dentry *h_parent); -+ -+/* real rmdir for the whiteout-ed dir */ -+struct au_whtmp_rmdir { -+ struct inode *dir; -+ struct au_branch *br; -+ struct dentry *wh_dentry; -+ struct au_nhash whlist; -+}; -+ -+struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp); -+void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp); -+int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex, -+ struct dentry *wh_dentry, struct au_nhash *whlist); -+void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex, -+ struct dentry *wh_dentry, struct au_whtmp_rmdir *args); -+ -+/* ---------------------------------------------------------------------- */ -+ -+static inline struct dentry *au_diropq_create(struct dentry *dentry, -+ aufs_bindex_t bindex) -+{ -+ return au_diropq_sio(dentry, bindex, AuDiropq_CREATE); -+} -+ -+static inline int au_diropq_remove(struct dentry *dentry, aufs_bindex_t bindex) -+{ -+ return PTR_ERR(au_diropq_sio(dentry, bindex, !AuDiropq_CREATE)); -+} -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_WHOUT_H__ */ -diff -Nurp linux-5.10-rc6/fs/aufs/wkq.c linux-5.10-rc6.aufs/fs/aufs/wkq.c ---- linux-5.10-rc6/fs/aufs/wkq.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/wkq.c 2020-12-02 21:19:51.884036878 +0200 -@@ -0,0 +1,359 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * workqueue for asynchronous/super-io operations -+ * todo: try new credential scheme -+ */ -+ -+#include -+#include "aufs.h" -+ -+/* internal workqueue named AUFS_WKQ_NAME */ -+ -+static struct workqueue_struct *au_wkq; -+ -+struct au_wkinfo { -+ struct work_struct wk; -+ struct kobject *kobj; -+ -+ unsigned int flags; /* see wkq.h */ -+ -+ au_wkq_func_t func; -+ void *args; -+ -+#ifdef CONFIG_LOCKDEP -+ int dont_check; -+ struct held_lock **hlock; -+#endif -+ -+ struct completion *comp; -+}; -+ -+/* ---------------------------------------------------------------------- */ -+/* -+ * Aufs passes some operations to the workqueue such as the internal copyup. -+ * This scheme looks rather unnatural for LOCKDEP debugging feature, since the -+ * job run by workqueue depends upon the locks acquired in the other task. -+ * Delegating a small operation to the workqueue, aufs passes its lockdep -+ * information too. And the job in the workqueue restores the info in order to -+ * pretend as if it acquired those locks. This is just to make LOCKDEP work -+ * correctly and expectedly. -+ */ -+ -+#ifndef CONFIG_LOCKDEP -+AuStubInt0(au_wkq_lockdep_alloc, struct au_wkinfo *wkinfo); -+AuStubVoid(au_wkq_lockdep_free, struct au_wkinfo *wkinfo); -+AuStubVoid(au_wkq_lockdep_pre, struct au_wkinfo *wkinfo); -+AuStubVoid(au_wkq_lockdep_post, struct au_wkinfo *wkinfo); -+AuStubVoid(au_wkq_lockdep_init, struct au_wkinfo *wkinfo); -+#else -+static void au_wkq_lockdep_init(struct au_wkinfo *wkinfo) -+{ -+ wkinfo->hlock = NULL; -+ wkinfo->dont_check = 0; -+} -+ -+/* -+ * 1: matched -+ * 0: unmatched -+ */ -+static int au_wkq_lockdep_test(struct lock_class_key *key, const char *name) -+{ -+ static DEFINE_SPINLOCK(spin); -+ static struct { -+ char *name; -+ struct lock_class_key *key; -+ } a[] = { -+ { .name = "&sbinfo->si_rwsem" }, -+ { .name = "&finfo->fi_rwsem" }, -+ { .name = "&dinfo->di_rwsem" }, -+ { .name = "&iinfo->ii_rwsem" } -+ }; -+ static int set; -+ int i; -+ -+ /* lockless read from 'set.' see below */ -+ if (set == ARRAY_SIZE(a)) { -+ for (i = 0; i < ARRAY_SIZE(a); i++) -+ if (a[i].key == key) -+ goto match; -+ goto unmatch; -+ } -+ -+ spin_lock(&spin); -+ if (set) -+ for (i = 0; i < ARRAY_SIZE(a); i++) -+ if (a[i].key == key) { -+ spin_unlock(&spin); -+ goto match; -+ } -+ for (i = 0; i < ARRAY_SIZE(a); i++) { -+ if (a[i].key) { -+ if (unlikely(a[i].key == key)) { /* rare but possible */ -+ spin_unlock(&spin); -+ goto match; -+ } else -+ continue; -+ } -+ if (strstr(a[i].name, name)) { -+ /* -+ * the order of these three lines is important for the -+ * lockless read above. -+ */ -+ a[i].key = key; -+ spin_unlock(&spin); -+ set++; -+ /* AuDbg("%d, %s\n", set, name); */ -+ goto match; -+ } -+ } -+ spin_unlock(&spin); -+ goto unmatch; -+ -+match: -+ return 1; -+unmatch: -+ return 0; -+} -+ -+static int au_wkq_lockdep_alloc(struct au_wkinfo *wkinfo) -+{ -+ int err, n; -+ struct task_struct *curr; -+ struct held_lock **hl, *held_locks, *p; -+ -+ err = 0; -+ curr = current; -+ wkinfo->dont_check = lockdep_recursing(curr); -+ if (wkinfo->dont_check) -+ goto out; -+ n = curr->lockdep_depth; -+ if (!n) -+ goto out; -+ -+ err = -ENOMEM; -+ wkinfo->hlock = kmalloc_array(n + 1, sizeof(*wkinfo->hlock), GFP_NOFS); -+ if (unlikely(!wkinfo->hlock)) -+ goto out; -+ -+ err = 0; -+#if 0 /* left for debugging */ -+ if (0 && au_debug_test()) -+ lockdep_print_held_locks(curr); -+#endif -+ held_locks = curr->held_locks; -+ hl = wkinfo->hlock; -+ while (n--) { -+ p = held_locks++; -+ if (au_wkq_lockdep_test(p->instance->key, p->instance->name)) -+ *hl++ = p; -+ } -+ *hl = NULL; -+ -+out: -+ return err; -+} -+ -+static void au_wkq_lockdep_free(struct au_wkinfo *wkinfo) -+{ -+ au_kfree_try_rcu(wkinfo->hlock); -+} -+ -+static void au_wkq_lockdep_pre(struct au_wkinfo *wkinfo) -+{ -+ struct held_lock *p, **hl = wkinfo->hlock; -+ int subclass; -+ -+ if (wkinfo->dont_check) -+ lockdep_off(); -+ if (!hl) -+ return; -+ while ((p = *hl++)) { /* assignment */ -+ subclass = lockdep_hlock_class(p)->subclass; -+ /* AuDbg("%s, %d\n", p->instance->name, subclass); */ -+ if (p->read) -+ rwsem_acquire_read(p->instance, subclass, 0, -+ /*p->acquire_ip*/_RET_IP_); -+ else -+ rwsem_acquire(p->instance, subclass, 0, -+ /*p->acquire_ip*/_RET_IP_); -+ } -+} -+ -+static void au_wkq_lockdep_post(struct au_wkinfo *wkinfo) -+{ -+ struct held_lock *p, **hl = wkinfo->hlock; -+ -+ if (wkinfo->dont_check) -+ lockdep_on(); -+ if (!hl) -+ return; -+ while ((p = *hl++)) /* assignment */ -+ rwsem_release(p->instance, /*p->acquire_ip*/_RET_IP_); -+} -+#endif -+ -+static void wkq_func(struct work_struct *wk) -+{ -+ struct au_wkinfo *wkinfo = container_of(wk, struct au_wkinfo, wk); -+ -+ AuDebugOn(!uid_eq(current_fsuid(), GLOBAL_ROOT_UID)); -+ AuDebugOn(rlimit(RLIMIT_FSIZE) != RLIM_INFINITY); -+ -+ au_wkq_lockdep_pre(wkinfo); -+ wkinfo->func(wkinfo->args); -+ au_wkq_lockdep_post(wkinfo); -+ if (au_ftest_wkq(wkinfo->flags, WAIT)) -+ complete(wkinfo->comp); -+ else { -+ kobject_put(wkinfo->kobj); -+ module_put(THIS_MODULE); /* todo: ?? */ -+ au_kfree_rcu(wkinfo); -+ } -+} -+ -+/* -+ * Since struct completion is large, try allocating it dynamically. -+ */ -+#define AuWkqCompDeclare(name) struct completion *comp = NULL -+ -+static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp) -+{ -+ *comp = kmalloc(sizeof(**comp), GFP_NOFS); -+ if (*comp) { -+ init_completion(*comp); -+ wkinfo->comp = *comp; -+ return 0; -+ } -+ return -ENOMEM; -+} -+ -+static void au_wkq_comp_free(struct completion *comp) -+{ -+ au_kfree_rcu(comp); -+} -+ -+static void au_wkq_run(struct au_wkinfo *wkinfo) -+{ -+ if (au_ftest_wkq(wkinfo->flags, NEST)) { -+ if (au_wkq_test()) { -+ AuWarn1("wkq from wkq, unless silly-rename on NFS," -+ " due to a dead dir by UDBA," -+ " or async xino write?\n"); -+ AuDebugOn(au_ftest_wkq(wkinfo->flags, WAIT)); -+ } -+ } else -+ au_dbg_verify_kthread(); -+ -+ if (au_ftest_wkq(wkinfo->flags, WAIT)) { -+ INIT_WORK_ONSTACK(&wkinfo->wk, wkq_func); -+ queue_work(au_wkq, &wkinfo->wk); -+ } else { -+ INIT_WORK(&wkinfo->wk, wkq_func); -+ schedule_work(&wkinfo->wk); -+ } -+} -+ -+/* -+ * Be careful. It is easy to make deadlock happen. -+ * processA: lock, wkq and wait -+ * processB: wkq and wait, lock in wkq -+ * --> deadlock -+ */ -+int au_wkq_do_wait(unsigned int flags, au_wkq_func_t func, void *args) -+{ -+ int err; -+ AuWkqCompDeclare(comp); -+ struct au_wkinfo wkinfo = { -+ .flags = flags, -+ .func = func, -+ .args = args -+ }; -+ -+ err = au_wkq_comp_alloc(&wkinfo, &comp); -+ if (unlikely(err)) -+ goto out; -+ err = au_wkq_lockdep_alloc(&wkinfo); -+ if (unlikely(err)) -+ goto out_comp; -+ if (!err) { -+ au_wkq_run(&wkinfo); -+ /* no timeout, no interrupt */ -+ wait_for_completion(wkinfo.comp); -+ } -+ au_wkq_lockdep_free(&wkinfo); -+ -+out_comp: -+ au_wkq_comp_free(comp); -+out: -+ destroy_work_on_stack(&wkinfo.wk); -+ return err; -+} -+ -+/* -+ * Note: dget/dput() in func for aufs dentries are not supported. It will be a -+ * problem in a concurrent umounting. -+ */ -+int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb, -+ unsigned int flags) -+{ -+ int err; -+ struct au_wkinfo *wkinfo; -+ -+ atomic_inc(&au_sbi(sb)->si_nowait.nw_len); -+ -+ /* -+ * wkq_func() must free this wkinfo. -+ * it highly depends upon the implementation of workqueue. -+ */ -+ err = 0; -+ wkinfo = kmalloc(sizeof(*wkinfo), GFP_NOFS); -+ if (wkinfo) { -+ wkinfo->kobj = &au_sbi(sb)->si_kobj; -+ wkinfo->flags = flags & ~AuWkq_WAIT; -+ wkinfo->func = func; -+ wkinfo->args = args; -+ wkinfo->comp = NULL; -+ au_wkq_lockdep_init(wkinfo); -+ kobject_get(wkinfo->kobj); -+ __module_get(THIS_MODULE); /* todo: ?? */ -+ -+ au_wkq_run(wkinfo); -+ } else { -+ err = -ENOMEM; -+ au_nwt_done(&au_sbi(sb)->si_nowait); -+ } -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+void au_nwt_init(struct au_nowait_tasks *nwt) -+{ -+ atomic_set(&nwt->nw_len, 0); -+ /* smp_mb(); */ /* atomic_set */ -+ init_waitqueue_head(&nwt->nw_wq); -+} -+ -+void au_wkq_fin(void) -+{ -+ destroy_workqueue(au_wkq); -+} -+ -+int __init au_wkq_init(void) -+{ -+ int err; -+ -+ err = 0; -+ au_wkq = alloc_workqueue(AUFS_WKQ_NAME, 0, WQ_DFL_ACTIVE); -+ if (IS_ERR(au_wkq)) -+ err = PTR_ERR(au_wkq); -+ else if (!au_wkq) -+ err = -ENOMEM; -+ -+ return err; -+} -diff -Nurp linux-5.10-rc6/fs/aufs/wkq.h linux-5.10-rc6.aufs/fs/aufs/wkq.h ---- linux-5.10-rc6/fs/aufs/wkq.h 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/wkq.h 2020-12-02 21:19:51.884036878 +0200 -@@ -0,0 +1,76 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * workqueue for asynchronous/super-io operations -+ * todo: try new credentials management scheme -+ */ -+ -+#ifndef __AUFS_WKQ_H__ -+#define __AUFS_WKQ_H__ -+ -+#ifdef __KERNEL__ -+ -+#include -+ -+struct super_block; -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * in the next operation, wait for the 'nowait' tasks in system-wide workqueue -+ */ -+struct au_nowait_tasks { -+ atomic_t nw_len; -+ wait_queue_head_t nw_wq; -+}; -+ -+/* ---------------------------------------------------------------------- */ -+ -+typedef void (*au_wkq_func_t)(void *args); -+ -+/* wkq flags */ -+#define AuWkq_WAIT 1 -+#define AuWkq_NEST (1 << 1) -+#define au_ftest_wkq(flags, name) ((flags) & AuWkq_##name) -+#define au_fset_wkq(flags, name) \ -+ do { (flags) |= AuWkq_##name; } while (0) -+#define au_fclr_wkq(flags, name) \ -+ do { (flags) &= ~AuWkq_##name; } while (0) -+ -+/* wkq.c */ -+int au_wkq_do_wait(unsigned int flags, au_wkq_func_t func, void *args); -+int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb, -+ unsigned int flags); -+void au_nwt_init(struct au_nowait_tasks *nwt); -+int __init au_wkq_init(void); -+void au_wkq_fin(void); -+ -+/* ---------------------------------------------------------------------- */ -+ -+static inline int au_wkq_test(void) -+{ -+ return current->flags & PF_WQ_WORKER; -+} -+ -+static inline int au_wkq_wait(au_wkq_func_t func, void *args) -+{ -+ return au_wkq_do_wait(AuWkq_WAIT, func, args); -+} -+ -+static inline void au_nwt_done(struct au_nowait_tasks *nwt) -+{ -+ if (atomic_dec_and_test(&nwt->nw_len)) -+ wake_up_all(&nwt->nw_wq); -+} -+ -+static inline int au_nwt_flush(struct au_nowait_tasks *nwt) -+{ -+ wait_event(nwt->nw_wq, !atomic_read(&nwt->nw_len)); -+ return 0; -+} -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_WKQ_H__ */ -diff -Nurp linux-5.10-rc6/fs/aufs/xattr.c linux-5.10-rc6.aufs/fs/aufs/xattr.c ---- linux-5.10-rc6/fs/aufs/xattr.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/xattr.c 2020-12-02 21:19:51.884036878 +0200 -@@ -0,0 +1,343 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2014-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * handling xattr functions -+ */ -+ -+#include -+#include -+#include -+#include "aufs.h" -+ -+static int au_xattr_ignore(int err, char *name, unsigned int ignore_flags) -+{ -+ if (!ignore_flags) -+ goto out; -+ switch (err) { -+ case -ENOMEM: -+ case -EDQUOT: -+ goto out; -+ } -+ -+ if ((ignore_flags & AuBrAttr_ICEX) == AuBrAttr_ICEX) { -+ err = 0; -+ goto out; -+ } -+ -+#define cmp(brattr, prefix) do { \ -+ if (!strncmp(name, XATTR_##prefix##_PREFIX, \ -+ XATTR_##prefix##_PREFIX_LEN)) { \ -+ if (ignore_flags & AuBrAttr_ICEX_##brattr) \ -+ err = 0; \ -+ goto out; \ -+ } \ -+ } while (0) -+ -+ cmp(SEC, SECURITY); -+ cmp(SYS, SYSTEM); -+ cmp(TR, TRUSTED); -+ cmp(USR, USER); -+#undef cmp -+ -+ if (ignore_flags & AuBrAttr_ICEX_OTH) -+ err = 0; -+ -+out: -+ return err; -+} -+ -+static const int au_xattr_out_of_list = AuBrAttr_ICEX_OTH << 1; -+ -+static int au_do_cpup_xattr(struct dentry *h_dst, struct dentry *h_src, -+ char *name, char **buf, unsigned int ignore_flags, -+ unsigned int verbose) -+{ -+ int err; -+ ssize_t ssz; -+ struct inode *h_idst; -+ -+ ssz = vfs_getxattr_alloc(h_src, name, buf, 0, GFP_NOFS); -+ err = ssz; -+ if (unlikely(err <= 0)) { -+ if (err == -ENODATA -+ || (err == -EOPNOTSUPP -+ && ((ignore_flags & au_xattr_out_of_list) -+ || (au_test_nfs_noacl(d_inode(h_src)) -+ && (!strcmp(name, XATTR_NAME_POSIX_ACL_ACCESS) -+ || !strcmp(name, -+ XATTR_NAME_POSIX_ACL_DEFAULT)))) -+ )) -+ err = 0; -+ if (err && (verbose || au_debug_test())) -+ pr_err("%s, err %d\n", name, err); -+ goto out; -+ } -+ -+ /* unlock it temporary */ -+ h_idst = d_inode(h_dst); -+ inode_unlock(h_idst); -+ err = vfsub_setxattr(h_dst, name, *buf, ssz, /*flags*/0); -+ inode_lock_nested(h_idst, AuLsc_I_CHILD2); -+ if (unlikely(err)) { -+ if (verbose || au_debug_test()) -+ pr_err("%s, err %d\n", name, err); -+ err = au_xattr_ignore(err, name, ignore_flags); -+ } -+ -+out: -+ return err; -+} -+ -+int au_cpup_xattr(struct dentry *h_dst, struct dentry *h_src, int ignore_flags, -+ unsigned int verbose) -+{ -+ int err, unlocked, acl_access, acl_default; -+ ssize_t ssz; -+ struct inode *h_isrc, *h_idst; -+ char *value, *p, *o, *e; -+ -+ /* try stopping to update the source inode while we are referencing */ -+ /* there should not be the parent-child relationship between them */ -+ h_isrc = d_inode(h_src); -+ h_idst = d_inode(h_dst); -+ inode_unlock(h_idst); -+ inode_lock_shared_nested(h_isrc, AuLsc_I_CHILD); -+ inode_lock_nested(h_idst, AuLsc_I_CHILD2); -+ unlocked = 0; -+ -+ /* some filesystems don't list POSIX ACL, for example tmpfs */ -+ ssz = vfs_listxattr(h_src, NULL, 0); -+ err = ssz; -+ if (unlikely(err < 0)) { -+ AuTraceErr(err); -+ if (err == -ENODATA -+ || err == -EOPNOTSUPP) -+ err = 0; /* ignore */ -+ goto out; -+ } -+ -+ err = 0; -+ p = NULL; -+ o = NULL; -+ if (ssz) { -+ err = -ENOMEM; -+ p = kmalloc(ssz, GFP_NOFS); -+ o = p; -+ if (unlikely(!p)) -+ goto out; -+ err = vfs_listxattr(h_src, p, ssz); -+ } -+ inode_unlock_shared(h_isrc); -+ unlocked = 1; -+ AuDbg("err %d, ssz %zd\n", err, ssz); -+ if (unlikely(err < 0)) -+ goto out_free; -+ -+ err = 0; -+ e = p + ssz; -+ value = NULL; -+ acl_access = 0; -+ acl_default = 0; -+ while (!err && p < e) { -+ acl_access |= !strncmp(p, XATTR_NAME_POSIX_ACL_ACCESS, -+ sizeof(XATTR_NAME_POSIX_ACL_ACCESS) - 1); -+ acl_default |= !strncmp(p, XATTR_NAME_POSIX_ACL_DEFAULT, -+ sizeof(XATTR_NAME_POSIX_ACL_DEFAULT) -+ - 1); -+ err = au_do_cpup_xattr(h_dst, h_src, p, &value, ignore_flags, -+ verbose); -+ p += strlen(p) + 1; -+ } -+ AuTraceErr(err); -+ ignore_flags |= au_xattr_out_of_list; -+ if (!err && !acl_access) { -+ err = au_do_cpup_xattr(h_dst, h_src, -+ XATTR_NAME_POSIX_ACL_ACCESS, &value, -+ ignore_flags, verbose); -+ AuTraceErr(err); -+ } -+ if (!err && !acl_default) { -+ err = au_do_cpup_xattr(h_dst, h_src, -+ XATTR_NAME_POSIX_ACL_DEFAULT, &value, -+ ignore_flags, verbose); -+ AuTraceErr(err); -+ } -+ -+ au_kfree_try_rcu(value); -+ -+out_free: -+ au_kfree_try_rcu(o); -+out: -+ if (!unlocked) -+ inode_unlock_shared(h_isrc); -+ AuTraceErr(err); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int au_smack_reentering(struct super_block *sb) -+{ -+#if IS_ENABLED(CONFIG_SECURITY_SMACK) || IS_ENABLED(CONFIG_SECURITY_SELINUX) -+ /* -+ * as a part of lookup, smack_d_instantiate() is called, and it calls -+ * i_op->getxattr(). ouch. -+ */ -+ return si_pid_test(sb); -+#else -+ return 0; -+#endif -+} -+ -+enum { -+ AU_XATTR_LIST, -+ AU_XATTR_GET -+}; -+ -+struct au_lgxattr { -+ int type; -+ union { -+ struct { -+ char *list; -+ size_t size; -+ } list; -+ struct { -+ const char *name; -+ void *value; -+ size_t size; -+ } get; -+ } u; -+}; -+ -+static ssize_t au_lgxattr(struct dentry *dentry, struct inode *inode, -+ struct au_lgxattr *arg) -+{ -+ ssize_t err; -+ int reenter; -+ struct path h_path; -+ struct super_block *sb; -+ -+ sb = dentry->d_sb; -+ reenter = au_smack_reentering(sb); -+ if (!reenter) { -+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM); -+ if (unlikely(err)) -+ goto out; -+ } -+ err = au_h_path_getattr(dentry, inode, /*force*/1, &h_path, reenter); -+ if (unlikely(err)) -+ goto out_si; -+ if (unlikely(!h_path.dentry)) -+ /* illegally overlapped or something */ -+ goto out_di; /* pretending success */ -+ -+ /* always topmost entry only */ -+ switch (arg->type) { -+ case AU_XATTR_LIST: -+ err = vfs_listxattr(h_path.dentry, -+ arg->u.list.list, arg->u.list.size); -+ break; -+ case AU_XATTR_GET: -+ AuDebugOn(d_is_negative(h_path.dentry)); -+ err = vfs_getxattr(h_path.dentry, -+ arg->u.get.name, arg->u.get.value, -+ arg->u.get.size); -+ break; -+ } -+ -+out_di: -+ if (!reenter) -+ di_read_unlock(dentry, AuLock_IR); -+out_si: -+ if (!reenter) -+ si_read_unlock(sb); -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+ssize_t aufs_listxattr(struct dentry *dentry, char *list, size_t size) -+{ -+ struct au_lgxattr arg = { -+ .type = AU_XATTR_LIST, -+ .u.list = { -+ .list = list, -+ .size = size -+ }, -+ }; -+ -+ return au_lgxattr(dentry, /*inode*/NULL, &arg); -+} -+ -+static ssize_t au_getxattr(struct dentry *dentry, struct inode *inode, -+ const char *name, void *value, size_t size) -+{ -+ struct au_lgxattr arg = { -+ .type = AU_XATTR_GET, -+ .u.get = { -+ .name = name, -+ .value = value, -+ .size = size -+ }, -+ }; -+ -+ return au_lgxattr(dentry, inode, &arg); -+} -+ -+static int au_setxattr(struct dentry *dentry, struct inode *inode, -+ const char *name, const void *value, size_t size, -+ int flags) -+{ -+ struct au_sxattr arg = { -+ .type = AU_XATTR_SET, -+ .u.set = { -+ .name = name, -+ .value = value, -+ .size = size, -+ .flags = flags -+ }, -+ }; -+ -+ return au_sxattr(dentry, inode, &arg); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int au_xattr_get(const struct xattr_handler *handler, -+ struct dentry *dentry, struct inode *inode, -+ const char *name, void *buffer, size_t size) -+{ -+ return au_getxattr(dentry, inode, name, buffer, size); -+} -+ -+static int au_xattr_set(const struct xattr_handler *handler, -+ struct dentry *dentry, struct inode *inode, -+ const char *name, const void *value, size_t size, -+ int flags) -+{ -+ return au_setxattr(dentry, inode, name, value, size, flags); -+} -+ -+static const struct xattr_handler au_xattr_handler = { -+ .name = "", -+ .prefix = "", -+ .get = au_xattr_get, -+ .set = au_xattr_set -+}; -+ -+static const struct xattr_handler *au_xattr_handlers[] = { -+#ifdef CONFIG_FS_POSIX_ACL -+ &posix_acl_access_xattr_handler, -+ &posix_acl_default_xattr_handler, -+#endif -+ &au_xattr_handler, /* must be last */ -+ NULL -+}; -+ -+void au_xattr_init(struct super_block *sb) -+{ -+ sb->s_xattr = au_xattr_handlers; -+} -diff -Nurp linux-5.10-rc6/fs/aufs/xino.c linux-5.10-rc6.aufs/fs/aufs/xino.c ---- linux-5.10-rc6/fs/aufs/xino.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/fs/aufs/xino.c 2020-12-02 21:19:51.884036878 +0200 -@@ -0,0 +1,1953 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+/* -+ * external inode number translation table and bitmap -+ * -+ * things to consider -+ * - the lifetime -+ * + au_xino object -+ * + XINO files (xino, xib, xigen) -+ * + dynamic debugfs entries (xiN) -+ * + static debugfs entries (xib, xigen) -+ * + static sysfs entry (xi_path) -+ * - several entry points to handle them. -+ * + mount(2) without xino option (default) -+ * + mount(2) with xino option -+ * + mount(2) with noxino option -+ * + umount(2) -+ * + remount with add/del branches -+ * + remount with xino/noxino options -+ */ -+ -+#include -+#include -+#include "aufs.h" -+ -+static aufs_bindex_t sbr_find_shared(struct super_block *sb, aufs_bindex_t btop, -+ aufs_bindex_t bbot, -+ struct super_block *h_sb) -+{ -+ /* todo: try binary-search if the branches are many */ -+ for (; btop <= bbot; btop++) -+ if (h_sb == au_sbr_sb(sb, btop)) -+ return btop; -+ return -1; -+} -+ -+/* -+ * find another branch who is on the same filesystem of the specified -+ * branch{@btgt}. search until @bbot. -+ */ -+static aufs_bindex_t is_sb_shared(struct super_block *sb, aufs_bindex_t btgt, -+ aufs_bindex_t bbot) -+{ -+ aufs_bindex_t bindex; -+ struct super_block *tgt_sb; -+ -+ tgt_sb = au_sbr_sb(sb, btgt); -+ bindex = sbr_find_shared(sb, /*btop*/0, btgt - 1, tgt_sb); -+ if (bindex < 0) -+ bindex = sbr_find_shared(sb, btgt + 1, bbot, tgt_sb); -+ -+ return bindex; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * stop unnecessary notify events at creating xino files -+ */ -+ -+aufs_bindex_t au_xi_root(struct super_block *sb, struct dentry *dentry) -+{ -+ aufs_bindex_t bfound, bindex, bbot; -+ struct dentry *parent; -+ struct au_branch *br; -+ -+ bfound = -1; -+ parent = dentry->d_parent; /* safe d_parent access */ -+ bbot = au_sbbot(sb); -+ for (bindex = 0; bindex <= bbot; bindex++) { -+ br = au_sbr(sb, bindex); -+ if (au_br_dentry(br) == parent) { -+ bfound = bindex; -+ break; -+ } -+ } -+ -+ AuDbg("bfound b%d\n", bfound); -+ return bfound; -+} -+ -+struct au_xino_lock_dir { -+ struct au_hinode *hdir; -+ struct dentry *parent; -+ struct inode *dir; -+}; -+ -+static struct dentry *au_dget_parent_lock(struct dentry *dentry, -+ unsigned int lsc) -+{ -+ struct dentry *parent; -+ struct inode *dir; -+ -+ parent = dget_parent(dentry); -+ dir = d_inode(parent); -+ inode_lock_nested(dir, lsc); -+#if 0 /* it should not happen */ -+ spin_lock(&dentry->d_lock); -+ if (unlikely(dentry->d_parent != parent)) { -+ spin_unlock(&dentry->d_lock); -+ inode_unlock(dir); -+ dput(parent); -+ parent = NULL; -+ goto out; -+ } -+ spin_unlock(&dentry->d_lock); -+ -+out: -+#endif -+ return parent; -+} -+ -+static void au_xino_lock_dir(struct super_block *sb, struct path *xipath, -+ struct au_xino_lock_dir *ldir) -+{ -+ aufs_bindex_t bindex; -+ -+ ldir->hdir = NULL; -+ bindex = au_xi_root(sb, xipath->dentry); -+ if (bindex >= 0) { -+ /* rw branch root */ -+ ldir->hdir = au_hi(d_inode(sb->s_root), bindex); -+ au_hn_inode_lock_nested(ldir->hdir, AuLsc_I_PARENT); -+ } else { -+ /* other */ -+ ldir->parent = au_dget_parent_lock(xipath->dentry, -+ AuLsc_I_PARENT); -+ ldir->dir = d_inode(ldir->parent); -+ } -+} -+ -+static void au_xino_unlock_dir(struct au_xino_lock_dir *ldir) -+{ -+ if (ldir->hdir) -+ au_hn_inode_unlock(ldir->hdir); -+ else { -+ inode_unlock(ldir->dir); -+ dput(ldir->parent); -+ } -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * create and set a new xino file -+ */ -+struct file *au_xino_create(struct super_block *sb, char *fpath, int silent, -+ int wbrtop) -+{ -+ struct file *file; -+ struct dentry *h_parent, *d; -+ struct inode *h_dir, *inode; -+ int err; -+ static DEFINE_MUTEX(mtx); -+ -+ /* -+ * at mount-time, and the xino file is the default path, -+ * hnotify is disabled so we have no notify events to ignore. -+ * when a user specified the xino, we cannot get au_hdir to be ignored. -+ */ -+ if (!wbrtop) -+ mutex_lock(&mtx); -+ file = vfsub_filp_open(fpath, O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE -+ /* | __FMODE_NONOTIFY */, -+ 0666); -+ if (IS_ERR(file)) { -+ if (!wbrtop) -+ mutex_unlock(&mtx); -+ if (!silent) -+ pr_err("open %s(%ld)\n", fpath, PTR_ERR(file)); -+ return file; -+ } -+ -+ /* keep file count */ -+ err = 0; -+ d = file->f_path.dentry; -+ h_parent = au_dget_parent_lock(d, AuLsc_I_PARENT); -+ if (!wbrtop) -+ mutex_unlock(&mtx); -+ /* mnt_want_write() is unnecessary here */ -+ h_dir = d_inode(h_parent); -+ inode = file_inode(file); -+ /* no delegation since it is just created */ -+ if (inode->i_nlink) -+ err = vfsub_unlink(h_dir, &file->f_path, /*delegated*/NULL, -+ /*force*/0); -+ inode_unlock(h_dir); -+ dput(h_parent); -+ if (unlikely(err)) { -+ if (!silent) -+ pr_err("unlink %s(%d)\n", fpath, err); -+ goto out; -+ } -+ -+ err = -EINVAL; -+ if (unlikely(sb == d->d_sb)) { -+ if (!silent) -+ pr_err("%s must be outside\n", fpath); -+ goto out; -+ } -+ if (unlikely(au_test_fs_bad_xino(d->d_sb))) { -+ if (!silent) -+ pr_err("xino doesn't support %s(%s)\n", -+ fpath, au_sbtype(d->d_sb)); -+ goto out; -+ } -+ return file; /* success */ -+ -+out: -+ fput(file); -+ file = ERR_PTR(err); -+ return file; -+} -+ -+/* -+ * create a new xinofile at the same place/path as @base. -+ */ -+struct file *au_xino_create2(struct super_block *sb, struct path *base, -+ struct file *copy_src) -+{ -+ struct file *file; -+ struct dentry *dentry, *parent; -+ struct inode *dir, *delegated; -+ struct qstr *name; -+ struct path path; -+ int err, do_unlock; -+ struct au_xino_lock_dir ldir; -+ -+ do_unlock = 1; -+ au_xino_lock_dir(sb, base, &ldir); -+ dentry = base->dentry; -+ parent = dentry->d_parent; /* dir inode is locked */ -+ dir = d_inode(parent); -+ IMustLock(dir); -+ -+ name = &dentry->d_name; -+ path.dentry = vfsub_lookup_one_len(name->name, parent, name->len); -+ if (IS_ERR(path.dentry)) { -+ file = (void *)path.dentry; -+ pr_err("%pd lookup err %ld\n", dentry, PTR_ERR(path.dentry)); -+ goto out; -+ } -+ -+ /* no need to mnt_want_write() since we call dentry_open() later */ -+ err = vfs_create(dir, path.dentry, 0666, NULL); -+ if (unlikely(err)) { -+ file = ERR_PTR(err); -+ pr_err("%pd create err %d\n", dentry, err); -+ goto out_dput; -+ } -+ -+ path.mnt = base->mnt; -+ file = vfsub_dentry_open(&path, -+ O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE -+ /* | __FMODE_NONOTIFY */); -+ if (IS_ERR(file)) { -+ pr_err("%pd open err %ld\n", dentry, PTR_ERR(file)); -+ goto out_dput; -+ } -+ -+ delegated = NULL; -+ err = vfsub_unlink(dir, &file->f_path, &delegated, /*force*/0); -+ au_xino_unlock_dir(&ldir); -+ do_unlock = 0; -+ if (unlikely(err == -EWOULDBLOCK)) { -+ pr_warn("cannot retry for NFSv4 delegation" -+ " for an internal unlink\n"); -+ iput(delegated); -+ } -+ if (unlikely(err)) { -+ pr_err("%pd unlink err %d\n", dentry, err); -+ goto out_fput; -+ } -+ -+ if (copy_src) { -+ /* no one can touch copy_src xino */ -+ err = au_copy_file(file, copy_src, vfsub_f_size_read(copy_src)); -+ if (unlikely(err)) { -+ pr_err("%pd copy err %d\n", dentry, err); -+ goto out_fput; -+ } -+ } -+ goto out_dput; /* success */ -+ -+out_fput: -+ fput(file); -+ file = ERR_PTR(err); -+out_dput: -+ dput(path.dentry); -+out: -+ if (do_unlock) -+ au_xino_unlock_dir(&ldir); -+ return file; -+} -+ -+struct file *au_xino_file1(struct au_xino *xi) -+{ -+ struct file *file; -+ unsigned int u, nfile; -+ -+ file = NULL; -+ nfile = xi->xi_nfile; -+ for (u = 0; u < nfile; u++) { -+ file = xi->xi_file[u]; -+ if (file) -+ break; -+ } -+ -+ return file; -+} -+ -+static int au_xino_file_set(struct au_xino *xi, int idx, struct file *file) -+{ -+ int err; -+ struct file *f; -+ void *p; -+ -+ if (file) -+ get_file(file); -+ -+ err = 0; -+ f = NULL; -+ if (idx < xi->xi_nfile) { -+ f = xi->xi_file[idx]; -+ if (f) -+ fput(f); -+ } else { -+ p = au_kzrealloc(xi->xi_file, -+ sizeof(*xi->xi_file) * xi->xi_nfile, -+ sizeof(*xi->xi_file) * (idx + 1), -+ GFP_NOFS, /*may_shrink*/0); -+ if (p) { -+ MtxMustLock(&xi->xi_mtx); -+ xi->xi_file = p; -+ xi->xi_nfile = idx + 1; -+ } else { -+ err = -ENOMEM; -+ if (file) -+ fput(file); -+ goto out; -+ } -+ } -+ xi->xi_file[idx] = file; -+ -+out: -+ return err; -+} -+ -+/* -+ * if @xinew->xi is not set, then create new xigen file. -+ */ -+struct file *au_xi_new(struct super_block *sb, struct au_xi_new *xinew) -+{ -+ struct file *file; -+ int err; -+ -+ SiMustAnyLock(sb); -+ -+ file = au_xino_create2(sb, xinew->base, xinew->copy_src); -+ if (IS_ERR(file)) { -+ err = PTR_ERR(file); -+ pr_err("%s[%d], err %d\n", -+ xinew->xi ? "xino" : "xigen", -+ xinew->idx, err); -+ goto out; -+ } -+ -+ if (xinew->xi) -+ err = au_xino_file_set(xinew->xi, xinew->idx, file); -+ else { -+ BUG(); -+ /* todo: make xigen file an array */ -+ /* err = au_xigen_file_set(sb, xinew->idx, file); */ -+ } -+ fput(file); -+ if (unlikely(err)) -+ file = ERR_PTR(err); -+ -+out: -+ return file; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * truncate xino files -+ */ -+static int au_xino_do_trunc(struct super_block *sb, aufs_bindex_t bindex, -+ int idx, struct kstatfs *st) -+{ -+ int err; -+ blkcnt_t blocks; -+ struct file *file, *new_xino; -+ struct au_xi_new xinew = { -+ .idx = idx -+ }; -+ -+ err = 0; -+ xinew.xi = au_sbr(sb, bindex)->br_xino; -+ file = au_xino_file(xinew.xi, idx); -+ if (!file) -+ goto out; -+ -+ xinew.base = &file->f_path; -+ err = vfs_statfs(xinew.base, st); -+ if (unlikely(err)) { -+ AuErr1("statfs err %d, ignored\n", err); -+ err = 0; -+ goto out; -+ } -+ -+ blocks = file_inode(file)->i_blocks; -+ pr_info("begin truncating xino(b%d-%d), ib%llu, %llu/%llu free blks\n", -+ bindex, idx, (u64)blocks, st->f_bfree, st->f_blocks); -+ -+ xinew.copy_src = file; -+ new_xino = au_xi_new(sb, &xinew); -+ if (IS_ERR(new_xino)) { -+ err = PTR_ERR(new_xino); -+ pr_err("xino(b%d-%d), err %d, ignored\n", bindex, idx, err); -+ goto out; -+ } -+ -+ err = vfs_statfs(&new_xino->f_path, st); -+ if (!err) -+ pr_info("end truncating xino(b%d-%d), ib%llu, %llu/%llu free blks\n", -+ bindex, idx, (u64)file_inode(new_xino)->i_blocks, -+ st->f_bfree, st->f_blocks); -+ else { -+ AuErr1("statfs err %d, ignored\n", err); -+ err = 0; -+ } -+ -+out: -+ return err; -+} -+ -+int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex, int idx_begin) -+{ -+ int err, i; -+ unsigned long jiffy; -+ aufs_bindex_t bbot; -+ struct kstatfs *st; -+ struct au_branch *br; -+ struct au_xino *xi; -+ -+ err = -ENOMEM; -+ st = kmalloc(sizeof(*st), GFP_NOFS); -+ if (unlikely(!st)) -+ goto out; -+ -+ err = -EINVAL; -+ bbot = au_sbbot(sb); -+ if (unlikely(bindex < 0 || bbot < bindex)) -+ goto out_st; -+ -+ err = 0; -+ jiffy = jiffies; -+ br = au_sbr(sb, bindex); -+ xi = br->br_xino; -+ for (i = idx_begin; !err && i < xi->xi_nfile; i++) -+ err = au_xino_do_trunc(sb, bindex, i, st); -+ if (!err) -+ au_sbi(sb)->si_xino_jiffy = jiffy; -+ -+out_st: -+ au_kfree_rcu(st); -+out: -+ return err; -+} -+ -+struct xino_do_trunc_args { -+ struct super_block *sb; -+ struct au_branch *br; -+ int idx; -+}; -+ -+static void xino_do_trunc(void *_args) -+{ -+ struct xino_do_trunc_args *args = _args; -+ struct super_block *sb; -+ struct au_branch *br; -+ struct inode *dir; -+ int err, idx; -+ aufs_bindex_t bindex; -+ -+ err = 0; -+ sb = args->sb; -+ dir = d_inode(sb->s_root); -+ br = args->br; -+ idx = args->idx; -+ -+ si_noflush_write_lock(sb); -+ ii_read_lock_parent(dir); -+ bindex = au_br_index(sb, br->br_id); -+ err = au_xino_trunc(sb, bindex, idx); -+ ii_read_unlock(dir); -+ if (unlikely(err)) -+ pr_warn("err b%d, (%d)\n", bindex, err); -+ atomic_dec(&br->br_xino->xi_truncating); -+ au_lcnt_dec(&br->br_count); -+ si_write_unlock(sb); -+ au_nwt_done(&au_sbi(sb)->si_nowait); -+ au_kfree_rcu(args); -+} -+ -+/* -+ * returns the index in the xi_file array whose corresponding file is necessary -+ * to truncate, or -1 which means no need to truncate. -+ */ -+static int xino_trunc_test(struct super_block *sb, struct au_branch *br) -+{ -+ int err; -+ unsigned int u; -+ struct kstatfs st; -+ struct au_sbinfo *sbinfo; -+ struct au_xino *xi; -+ struct file *file; -+ -+ /* todo: si_xino_expire and the ratio should be customizable */ -+ sbinfo = au_sbi(sb); -+ if (time_before(jiffies, -+ sbinfo->si_xino_jiffy + sbinfo->si_xino_expire)) -+ return -1; -+ -+ /* truncation border */ -+ xi = br->br_xino; -+ for (u = 0; u < xi->xi_nfile; u++) { -+ file = au_xino_file(xi, u); -+ if (!file) -+ continue; -+ -+ err = vfs_statfs(&file->f_path, &st); -+ if (unlikely(err)) { -+ AuErr1("statfs err %d, ignored\n", err); -+ return -1; -+ } -+ if (div64_u64(st.f_bfree * 100, st.f_blocks) -+ >= AUFS_XINO_DEF_TRUNC) -+ return u; -+ } -+ -+ return -1; -+} -+ -+static void xino_try_trunc(struct super_block *sb, struct au_branch *br) -+{ -+ int idx; -+ struct xino_do_trunc_args *args; -+ int wkq_err; -+ -+ idx = xino_trunc_test(sb, br); -+ if (idx < 0) -+ return; -+ -+ if (atomic_inc_return(&br->br_xino->xi_truncating) > 1) -+ goto out; -+ -+ /* lock and kfree() will be called in trunc_xino() */ -+ args = kmalloc(sizeof(*args), GFP_NOFS); -+ if (unlikely(!args)) { -+ AuErr1("no memory\n"); -+ goto out; -+ } -+ -+ au_lcnt_inc(&br->br_count); -+ args->sb = sb; -+ args->br = br; -+ args->idx = idx; -+ wkq_err = au_wkq_nowait(xino_do_trunc, args, sb, /*flags*/0); -+ if (!wkq_err) -+ return; /* success */ -+ -+ pr_err("wkq %d\n", wkq_err); -+ au_lcnt_dec(&br->br_count); -+ au_kfree_rcu(args); -+ -+out: -+ atomic_dec(&br->br_xino->xi_truncating); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct au_xi_calc { -+ int idx; -+ loff_t pos; -+}; -+ -+static void au_xi_calc(struct super_block *sb, ino_t h_ino, -+ struct au_xi_calc *calc) -+{ -+ loff_t maxent; -+ -+ maxent = au_xi_maxent(sb); -+ calc->idx = div64_u64_rem(h_ino, maxent, &calc->pos); -+ calc->pos *= sizeof(ino_t); -+} -+ -+static int au_xino_do_new_async(struct super_block *sb, struct au_branch *br, -+ struct au_xi_calc *calc) -+{ -+ int err; -+ struct file *file; -+ struct au_xino *xi = br->br_xino; -+ struct au_xi_new xinew = { -+ .xi = xi -+ }; -+ -+ SiMustAnyLock(sb); -+ -+ err = 0; -+ if (!xi) -+ goto out; -+ -+ mutex_lock(&xi->xi_mtx); -+ file = au_xino_file(xi, calc->idx); -+ if (file) -+ goto out_mtx; -+ -+ file = au_xino_file(xi, /*idx*/-1); -+ AuDebugOn(!file); -+ xinew.idx = calc->idx; -+ xinew.base = &file->f_path; -+ /* xinew.copy_src = NULL; */ -+ file = au_xi_new(sb, &xinew); -+ if (IS_ERR(file)) -+ err = PTR_ERR(file); -+ -+out_mtx: -+ mutex_unlock(&xi->xi_mtx); -+out: -+ return err; -+} -+ -+struct au_xino_do_new_async_args { -+ struct super_block *sb; -+ struct au_branch *br; -+ struct au_xi_calc calc; -+ ino_t ino; -+}; -+ -+struct au_xi_writing { -+ struct hlist_bl_node node; -+ ino_t h_ino, ino; -+}; -+ -+static int au_xino_do_write(vfs_writef_t write, struct file *file, -+ struct au_xi_calc *calc, ino_t ino); -+ -+static void au_xino_call_do_new_async(void *args) -+{ -+ struct au_xino_do_new_async_args *a = args; -+ struct au_branch *br; -+ struct super_block *sb; -+ struct au_sbinfo *sbi; -+ struct inode *root; -+ struct file *file; -+ struct au_xi_writing *del, *p; -+ struct hlist_bl_head *hbl; -+ struct hlist_bl_node *pos; -+ int err; -+ -+ br = a->br; -+ sb = a->sb; -+ sbi = au_sbi(sb); -+ si_noflush_read_lock(sb); -+ root = d_inode(sb->s_root); -+ ii_read_lock_child(root); -+ err = au_xino_do_new_async(sb, br, &a->calc); -+ if (unlikely(err)) { -+ AuIOErr("err %d\n", err); -+ goto out; -+ } -+ -+ file = au_xino_file(br->br_xino, a->calc.idx); -+ AuDebugOn(!file); -+ err = au_xino_do_write(sbi->si_xwrite, file, &a->calc, a->ino); -+ if (unlikely(err)) { -+ AuIOErr("err %d\n", err); -+ goto out; -+ } -+ -+ del = NULL; -+ hbl = &br->br_xino->xi_writing; -+ hlist_bl_lock(hbl); -+ au_hbl_for_each(pos, hbl) { -+ p = container_of(pos, struct au_xi_writing, node); -+ if (p->ino == a->ino) { -+ del = p; -+ hlist_bl_del(&p->node); -+ break; -+ } -+ } -+ hlist_bl_unlock(hbl); -+ au_kfree_rcu(del); -+ -+out: -+ au_lcnt_dec(&br->br_count); -+ ii_read_unlock(root); -+ si_read_unlock(sb); -+ au_nwt_done(&sbi->si_nowait); -+ au_kfree_rcu(a); -+} -+ -+/* -+ * create a new xino file asynchronously -+ */ -+static int au_xino_new_async(struct super_block *sb, struct au_branch *br, -+ struct au_xi_calc *calc, ino_t ino) -+{ -+ int err; -+ struct au_xino_do_new_async_args *arg; -+ -+ err = -ENOMEM; -+ arg = kmalloc(sizeof(*arg), GFP_NOFS); -+ if (unlikely(!arg)) -+ goto out; -+ -+ arg->sb = sb; -+ arg->br = br; -+ arg->calc = *calc; -+ arg->ino = ino; -+ au_lcnt_inc(&br->br_count); -+ err = au_wkq_nowait(au_xino_call_do_new_async, arg, sb, AuWkq_NEST); -+ if (unlikely(err)) { -+ pr_err("wkq %d\n", err); -+ au_lcnt_dec(&br->br_count); -+ au_kfree_rcu(arg); -+ } -+ -+out: -+ return err; -+} -+ -+/* -+ * read @ino from xinofile for the specified branch{@sb, @bindex} -+ * at the position of @h_ino. -+ */ -+int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, -+ ino_t *ino) -+{ -+ int err; -+ ssize_t sz; -+ struct au_xi_calc calc; -+ struct au_sbinfo *sbinfo; -+ struct file *file; -+ struct au_xino *xi; -+ struct hlist_bl_head *hbl; -+ struct hlist_bl_node *pos; -+ struct au_xi_writing *p; -+ -+ *ino = 0; -+ if (!au_opt_test(au_mntflags(sb), XINO)) -+ return 0; /* no xino */ -+ -+ err = 0; -+ au_xi_calc(sb, h_ino, &calc); -+ xi = au_sbr(sb, bindex)->br_xino; -+ file = au_xino_file(xi, calc.idx); -+ if (!file) { -+ hbl = &xi->xi_writing; -+ hlist_bl_lock(hbl); -+ au_hbl_for_each(pos, hbl) { -+ p = container_of(pos, struct au_xi_writing, node); -+ if (p->h_ino == h_ino) { -+ AuDbg("hi%llu, i%llu, found\n", -+ (u64)p->h_ino, (u64)p->ino); -+ *ino = p->ino; -+ break; -+ } -+ } -+ hlist_bl_unlock(hbl); -+ return 0; -+ } else if (vfsub_f_size_read(file) < calc.pos + sizeof(*ino)) -+ return 0; /* no xino */ -+ -+ sbinfo = au_sbi(sb); -+ sz = xino_fread(sbinfo->si_xread, file, ino, sizeof(*ino), &calc.pos); -+ if (sz == sizeof(*ino)) -+ return 0; /* success */ -+ -+ err = sz; -+ if (unlikely(sz >= 0)) { -+ err = -EIO; -+ AuIOErr("xino read error (%zd)\n", sz); -+ } -+ return err; -+} -+ -+static int au_xino_do_write(vfs_writef_t write, struct file *file, -+ struct au_xi_calc *calc, ino_t ino) -+{ -+ ssize_t sz; -+ -+ sz = xino_fwrite(write, file, &ino, sizeof(ino), &calc->pos); -+ if (sz == sizeof(ino)) -+ return 0; /* success */ -+ -+ AuIOErr("write failed (%zd)\n", sz); -+ return -EIO; -+} -+ -+/* -+ * write @ino to the xinofile for the specified branch{@sb, @bindex} -+ * at the position of @h_ino. -+ * even if @ino is zero, it is written to the xinofile and means no entry. -+ * if the size of the xino file on a specific filesystem exceeds the watermark, -+ * try truncating it. -+ */ -+int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, -+ ino_t ino) -+{ -+ int err; -+ unsigned int mnt_flags; -+ struct au_xi_calc calc; -+ struct file *file; -+ struct au_branch *br; -+ struct au_xino *xi; -+ struct au_xi_writing *p; -+ -+ SiMustAnyLock(sb); -+ -+ mnt_flags = au_mntflags(sb); -+ if (!au_opt_test(mnt_flags, XINO)) -+ return 0; -+ -+ au_xi_calc(sb, h_ino, &calc); -+ br = au_sbr(sb, bindex); -+ xi = br->br_xino; -+ file = au_xino_file(xi, calc.idx); -+ if (!file) { -+ /* store the inum pair into the list */ -+ p = kmalloc(sizeof(*p), GFP_NOFS | __GFP_NOFAIL); -+ p->h_ino = h_ino; -+ p->ino = ino; -+ au_hbl_add(&p->node, &xi->xi_writing); -+ -+ /* create and write a new xino file asynchronously */ -+ err = au_xino_new_async(sb, br, &calc, ino); -+ if (!err) -+ return 0; /* success */ -+ goto out; -+ } -+ -+ err = au_xino_do_write(au_sbi(sb)->si_xwrite, file, &calc, ino); -+ if (!err) { -+ br = au_sbr(sb, bindex); -+ if (au_opt_test(mnt_flags, TRUNC_XINO) -+ && au_test_fs_trunc_xino(au_br_sb(br))) -+ xino_try_trunc(sb, br); -+ return 0; /* success */ -+ } -+ -+out: -+ AuIOErr("write failed (%d)\n", err); -+ return -EIO; -+} -+ -+static ssize_t xino_fread_wkq(vfs_readf_t func, struct file *file, void *buf, -+ size_t size, loff_t *pos); -+ -+/* todo: unnecessary to support mmap_sem since kernel-space? */ -+ssize_t xino_fread(vfs_readf_t func, struct file *file, void *kbuf, size_t size, -+ loff_t *pos) -+{ -+ ssize_t err; -+ mm_segment_t oldfs; -+ union { -+ void *k; -+ char __user *u; -+ } buf; -+ int i; -+ const int prevent_endless = 10; -+ -+ i = 0; -+ buf.k = kbuf; -+ oldfs = get_fs(); -+ set_fs(KERNEL_DS); -+ do { -+ err = func(file, buf.u, size, pos); -+ if (err == -EINTR -+ && !au_wkq_test() -+ && fatal_signal_pending(current)) { -+ set_fs(oldfs); -+ err = xino_fread_wkq(func, file, kbuf, size, pos); -+ BUG_ON(err == -EINTR); -+ oldfs = get_fs(); -+ set_fs(KERNEL_DS); -+ } -+ } while (i++ < prevent_endless -+ && (err == -EAGAIN || err == -EINTR)); -+ set_fs(oldfs); -+ -+#if 0 /* reserved for future use */ -+ if (err > 0) -+ fsnotify_access(file->f_path.dentry); -+#endif -+ -+ return err; -+} -+ -+struct xino_fread_args { -+ ssize_t *errp; -+ vfs_readf_t func; -+ struct file *file; -+ void *buf; -+ size_t size; -+ loff_t *pos; -+}; -+ -+static void call_xino_fread(void *args) -+{ -+ struct xino_fread_args *a = args; -+ *a->errp = xino_fread(a->func, a->file, a->buf, a->size, a->pos); -+} -+ -+static ssize_t xino_fread_wkq(vfs_readf_t func, struct file *file, void *buf, -+ size_t size, loff_t *pos) -+{ -+ ssize_t err; -+ int wkq_err; -+ struct xino_fread_args args = { -+ .errp = &err, -+ .func = func, -+ .file = file, -+ .buf = buf, -+ .size = size, -+ .pos = pos -+ }; -+ -+ wkq_err = au_wkq_wait(call_xino_fread, &args); -+ if (unlikely(wkq_err)) -+ err = wkq_err; -+ -+ return err; -+} -+ -+static ssize_t xino_fwrite_wkq(vfs_writef_t func, struct file *file, void *buf, -+ size_t size, loff_t *pos); -+ -+static ssize_t do_xino_fwrite(vfs_writef_t func, struct file *file, void *kbuf, -+ size_t size, loff_t *pos) -+{ -+ ssize_t err; -+ mm_segment_t oldfs; -+ union { -+ void *k; -+ const char __user *u; -+ } buf; -+ int i; -+ const int prevent_endless = 10; -+ -+ i = 0; -+ buf.k = kbuf; -+ oldfs = get_fs(); -+ set_fs(KERNEL_DS); -+ do { -+ err = func(file, buf.u, size, pos); -+ if (err == -EINTR -+ && !au_wkq_test() -+ && fatal_signal_pending(current)) { -+ set_fs(oldfs); -+ err = xino_fwrite_wkq(func, file, kbuf, size, pos); -+ BUG_ON(err == -EINTR); -+ oldfs = get_fs(); -+ set_fs(KERNEL_DS); -+ } -+ } while (i++ < prevent_endless -+ && (err == -EAGAIN || err == -EINTR)); -+ set_fs(oldfs); -+ -+#if 0 /* reserved for future use */ -+ if (err > 0) -+ fsnotify_modify(file->f_path.dentry); -+#endif -+ -+ return err; -+} -+ -+struct do_xino_fwrite_args { -+ ssize_t *errp; -+ vfs_writef_t func; -+ struct file *file; -+ void *buf; -+ size_t size; -+ loff_t *pos; -+}; -+ -+static void call_do_xino_fwrite(void *args) -+{ -+ struct do_xino_fwrite_args *a = args; -+ *a->errp = do_xino_fwrite(a->func, a->file, a->buf, a->size, a->pos); -+} -+ -+static ssize_t xino_fwrite_wkq(vfs_writef_t func, struct file *file, void *buf, -+ size_t size, loff_t *pos) -+{ -+ ssize_t err; -+ int wkq_err; -+ struct do_xino_fwrite_args args = { -+ .errp = &err, -+ .func = func, -+ .file = file, -+ .buf = buf, -+ .size = size, -+ .pos = pos -+ }; -+ -+ /* -+ * it breaks RLIMIT_FSIZE and normal user's limit, -+ * users should care about quota and real 'filesystem full.' -+ */ -+ wkq_err = au_wkq_wait(call_do_xino_fwrite, &args); -+ if (unlikely(wkq_err)) -+ err = wkq_err; -+ -+ return err; -+} -+ -+ssize_t xino_fwrite(vfs_writef_t func, struct file *file, void *buf, -+ size_t size, loff_t *pos) -+{ -+ ssize_t err; -+ -+ if (rlimit(RLIMIT_FSIZE) == RLIM_INFINITY) { -+ lockdep_off(); -+ err = do_xino_fwrite(func, file, buf, size, pos); -+ lockdep_on(); -+ } else { -+ lockdep_off(); -+ err = xino_fwrite_wkq(func, file, buf, size, pos); -+ lockdep_on(); -+ } -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * inode number bitmap -+ */ -+static const int page_bits = (int)PAGE_SIZE * BITS_PER_BYTE; -+static ino_t xib_calc_ino(unsigned long pindex, int bit) -+{ -+ ino_t ino; -+ -+ AuDebugOn(bit < 0 || page_bits <= bit); -+ ino = AUFS_FIRST_INO + pindex * page_bits + bit; -+ return ino; -+} -+ -+static void xib_calc_bit(ino_t ino, unsigned long *pindex, int *bit) -+{ -+ AuDebugOn(ino < AUFS_FIRST_INO); -+ ino -= AUFS_FIRST_INO; -+ *pindex = ino / page_bits; -+ *bit = ino % page_bits; -+} -+ -+static int xib_pindex(struct super_block *sb, unsigned long pindex) -+{ -+ int err; -+ loff_t pos; -+ ssize_t sz; -+ struct au_sbinfo *sbinfo; -+ struct file *xib; -+ unsigned long *p; -+ -+ sbinfo = au_sbi(sb); -+ MtxMustLock(&sbinfo->si_xib_mtx); -+ AuDebugOn(pindex > ULONG_MAX / PAGE_SIZE -+ || !au_opt_test(sbinfo->si_mntflags, XINO)); -+ -+ if (pindex == sbinfo->si_xib_last_pindex) -+ return 0; -+ -+ xib = sbinfo->si_xib; -+ p = sbinfo->si_xib_buf; -+ pos = sbinfo->si_xib_last_pindex; -+ pos *= PAGE_SIZE; -+ sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos); -+ if (unlikely(sz != PAGE_SIZE)) -+ goto out; -+ -+ pos = pindex; -+ pos *= PAGE_SIZE; -+ if (vfsub_f_size_read(xib) >= pos + PAGE_SIZE) -+ sz = xino_fread(sbinfo->si_xread, xib, p, PAGE_SIZE, &pos); -+ else { -+ memset(p, 0, PAGE_SIZE); -+ sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos); -+ } -+ if (sz == PAGE_SIZE) { -+ sbinfo->si_xib_last_pindex = pindex; -+ return 0; /* success */ -+ } -+ -+out: -+ AuIOErr1("write failed (%zd)\n", sz); -+ err = sz; -+ if (sz >= 0) -+ err = -EIO; -+ return err; -+} -+ -+static void au_xib_clear_bit(struct inode *inode) -+{ -+ int err, bit; -+ unsigned long pindex; -+ struct super_block *sb; -+ struct au_sbinfo *sbinfo; -+ -+ AuDebugOn(inode->i_nlink); -+ -+ sb = inode->i_sb; -+ xib_calc_bit(inode->i_ino, &pindex, &bit); -+ AuDebugOn(page_bits <= bit); -+ sbinfo = au_sbi(sb); -+ mutex_lock(&sbinfo->si_xib_mtx); -+ err = xib_pindex(sb, pindex); -+ if (!err) { -+ clear_bit(bit, sbinfo->si_xib_buf); -+ sbinfo->si_xib_next_bit = bit; -+ } -+ mutex_unlock(&sbinfo->si_xib_mtx); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * truncate a xino bitmap file -+ */ -+ -+/* todo: slow */ -+static int do_xib_restore(struct super_block *sb, struct file *file, void *page) -+{ -+ int err, bit; -+ ssize_t sz; -+ unsigned long pindex; -+ loff_t pos, pend; -+ struct au_sbinfo *sbinfo; -+ vfs_readf_t func; -+ ino_t *ino; -+ unsigned long *p; -+ -+ err = 0; -+ sbinfo = au_sbi(sb); -+ MtxMustLock(&sbinfo->si_xib_mtx); -+ p = sbinfo->si_xib_buf; -+ func = sbinfo->si_xread; -+ pend = vfsub_f_size_read(file); -+ pos = 0; -+ while (pos < pend) { -+ sz = xino_fread(func, file, page, PAGE_SIZE, &pos); -+ err = sz; -+ if (unlikely(sz <= 0)) -+ goto out; -+ -+ err = 0; -+ for (ino = page; sz > 0; ino++, sz -= sizeof(ino)) { -+ if (unlikely(*ino < AUFS_FIRST_INO)) -+ continue; -+ -+ xib_calc_bit(*ino, &pindex, &bit); -+ AuDebugOn(page_bits <= bit); -+ err = xib_pindex(sb, pindex); -+ if (!err) -+ set_bit(bit, p); -+ else -+ goto out; -+ } -+ } -+ -+out: -+ return err; -+} -+ -+static int xib_restore(struct super_block *sb) -+{ -+ int err, i; -+ unsigned int nfile; -+ aufs_bindex_t bindex, bbot; -+ void *page; -+ struct au_branch *br; -+ struct au_xino *xi; -+ struct file *file; -+ -+ err = -ENOMEM; -+ page = (void *)__get_free_page(GFP_NOFS); -+ if (unlikely(!page)) -+ goto out; -+ -+ err = 0; -+ bbot = au_sbbot(sb); -+ for (bindex = 0; !err && bindex <= bbot; bindex++) -+ if (!bindex || is_sb_shared(sb, bindex, bindex - 1) < 0) { -+ br = au_sbr(sb, bindex); -+ xi = br->br_xino; -+ nfile = xi->xi_nfile; -+ for (i = 0; i < nfile; i++) { -+ file = au_xino_file(xi, i); -+ if (file) -+ err = do_xib_restore(sb, file, page); -+ } -+ } else -+ AuDbg("skip shared b%d\n", bindex); -+ free_page((unsigned long)page); -+ -+out: -+ return err; -+} -+ -+int au_xib_trunc(struct super_block *sb) -+{ -+ int err; -+ ssize_t sz; -+ loff_t pos; -+ struct au_sbinfo *sbinfo; -+ unsigned long *p; -+ struct file *file; -+ -+ SiMustWriteLock(sb); -+ -+ err = 0; -+ sbinfo = au_sbi(sb); -+ if (!au_opt_test(sbinfo->si_mntflags, XINO)) -+ goto out; -+ -+ file = sbinfo->si_xib; -+ if (vfsub_f_size_read(file) <= PAGE_SIZE) -+ goto out; -+ -+ file = au_xino_create2(sb, &sbinfo->si_xib->f_path, NULL); -+ err = PTR_ERR(file); -+ if (IS_ERR(file)) -+ goto out; -+ fput(sbinfo->si_xib); -+ sbinfo->si_xib = file; -+ -+ p = sbinfo->si_xib_buf; -+ memset(p, 0, PAGE_SIZE); -+ pos = 0; -+ sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xib, p, PAGE_SIZE, &pos); -+ if (unlikely(sz != PAGE_SIZE)) { -+ err = sz; -+ AuIOErr("err %d\n", err); -+ if (sz >= 0) -+ err = -EIO; -+ goto out; -+ } -+ -+ mutex_lock(&sbinfo->si_xib_mtx); -+ /* mnt_want_write() is unnecessary here */ -+ err = xib_restore(sb); -+ mutex_unlock(&sbinfo->si_xib_mtx); -+ -+out: -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct au_xino *au_xino_alloc(unsigned int nfile) -+{ -+ struct au_xino *xi; -+ -+ xi = kzalloc(sizeof(*xi), GFP_NOFS); -+ if (unlikely(!xi)) -+ goto out; -+ xi->xi_nfile = nfile; -+ xi->xi_file = kcalloc(nfile, sizeof(*xi->xi_file), GFP_NOFS); -+ if (unlikely(!xi->xi_file)) -+ goto out_free; -+ -+ xi->xi_nondir.total = 8; /* initial size */ -+ xi->xi_nondir.array = kcalloc(xi->xi_nondir.total, sizeof(ino_t), -+ GFP_NOFS); -+ if (unlikely(!xi->xi_nondir.array)) -+ goto out_file; -+ -+ spin_lock_init(&xi->xi_nondir.spin); -+ init_waitqueue_head(&xi->xi_nondir.wqh); -+ mutex_init(&xi->xi_mtx); -+ INIT_HLIST_BL_HEAD(&xi->xi_writing); -+ atomic_set(&xi->xi_truncating, 0); -+ kref_init(&xi->xi_kref); -+ goto out; /* success */ -+ -+out_file: -+ au_kfree_try_rcu(xi->xi_file); -+out_free: -+ au_kfree_rcu(xi); -+ xi = NULL; -+out: -+ return xi; -+} -+ -+static int au_xino_init(struct au_branch *br, int idx, struct file *file) -+{ -+ int err; -+ struct au_xino *xi; -+ -+ err = 0; -+ xi = au_xino_alloc(idx + 1); -+ if (unlikely(!xi)) { -+ err = -ENOMEM; -+ goto out; -+ } -+ -+ if (file) -+ get_file(file); -+ xi->xi_file[idx] = file; -+ AuDebugOn(br->br_xino); -+ br->br_xino = xi; -+ -+out: -+ return err; -+} -+ -+static void au_xino_release(struct kref *kref) -+{ -+ struct au_xino *xi; -+ int i; -+ unsigned long ul; -+ struct hlist_bl_head *hbl; -+ struct hlist_bl_node *pos, *n; -+ struct au_xi_writing *p; -+ -+ xi = container_of(kref, struct au_xino, xi_kref); -+ for (i = 0; i < xi->xi_nfile; i++) -+ if (xi->xi_file[i]) -+ fput(xi->xi_file[i]); -+ for (i = xi->xi_nondir.total - 1; i >= 0; i--) -+ AuDebugOn(xi->xi_nondir.array[i]); -+ mutex_destroy(&xi->xi_mtx); -+ hbl = &xi->xi_writing; -+ ul = au_hbl_count(hbl); -+ if (unlikely(ul)) { -+ pr_warn("xi_writing %lu\n", ul); -+ hlist_bl_lock(hbl); -+ hlist_bl_for_each_entry_safe(p, pos, n, hbl, node) { -+ hlist_bl_del(&p->node); -+ /* kmemleak reported au_kfree_rcu() doesn't free it */ -+ kfree(p); -+ } -+ hlist_bl_unlock(hbl); -+ } -+ au_kfree_try_rcu(xi->xi_file); -+ au_kfree_try_rcu(xi->xi_nondir.array); -+ au_kfree_rcu(xi); -+} -+ -+int au_xino_put(struct au_branch *br) -+{ -+ int ret; -+ struct au_xino *xi; -+ -+ ret = 0; -+ xi = br->br_xino; -+ if (xi) { -+ br->br_xino = NULL; -+ ret = kref_put(&xi->xi_kref, au_xino_release); -+ } -+ -+ return ret; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * xino mount option handlers -+ */ -+ -+/* xino bitmap */ -+static void xino_clear_xib(struct super_block *sb) -+{ -+ struct au_sbinfo *sbinfo; -+ -+ SiMustWriteLock(sb); -+ -+ sbinfo = au_sbi(sb); -+ /* unnecessary to clear sbinfo->si_xread and ->si_xwrite */ -+ if (sbinfo->si_xib) -+ fput(sbinfo->si_xib); -+ sbinfo->si_xib = NULL; -+ if (sbinfo->si_xib_buf) -+ free_page((unsigned long)sbinfo->si_xib_buf); -+ sbinfo->si_xib_buf = NULL; -+} -+ -+static int au_xino_set_xib(struct super_block *sb, struct path *path) -+{ -+ int err; -+ loff_t pos; -+ struct au_sbinfo *sbinfo; -+ struct file *file; -+ struct super_block *xi_sb; -+ -+ SiMustWriteLock(sb); -+ -+ sbinfo = au_sbi(sb); -+ file = au_xino_create2(sb, path, sbinfo->si_xib); -+ err = PTR_ERR(file); -+ if (IS_ERR(file)) -+ goto out; -+ if (sbinfo->si_xib) -+ fput(sbinfo->si_xib); -+ sbinfo->si_xib = file; -+ sbinfo->si_xread = vfs_readf(file); -+ sbinfo->si_xwrite = vfs_writef(file); -+ xi_sb = file_inode(file)->i_sb; -+ sbinfo->si_ximaxent = xi_sb->s_maxbytes; -+ if (unlikely(sbinfo->si_ximaxent < PAGE_SIZE)) { -+ err = -EIO; -+ pr_err("s_maxbytes(%llu) on %s is too small\n", -+ (u64)sbinfo->si_ximaxent, au_sbtype(xi_sb)); -+ goto out_unset; -+ } -+ sbinfo->si_ximaxent /= sizeof(ino_t); -+ -+ err = -ENOMEM; -+ if (!sbinfo->si_xib_buf) -+ sbinfo->si_xib_buf = (void *)get_zeroed_page(GFP_NOFS); -+ if (unlikely(!sbinfo->si_xib_buf)) -+ goto out_unset; -+ -+ sbinfo->si_xib_last_pindex = 0; -+ sbinfo->si_xib_next_bit = 0; -+ if (vfsub_f_size_read(file) < PAGE_SIZE) { -+ pos = 0; -+ err = xino_fwrite(sbinfo->si_xwrite, file, sbinfo->si_xib_buf, -+ PAGE_SIZE, &pos); -+ if (unlikely(err != PAGE_SIZE)) -+ goto out_free; -+ } -+ err = 0; -+ goto out; /* success */ -+ -+out_free: -+ if (sbinfo->si_xib_buf) -+ free_page((unsigned long)sbinfo->si_xib_buf); -+ sbinfo->si_xib_buf = NULL; -+ if (err >= 0) -+ err = -EIO; -+out_unset: -+ fput(sbinfo->si_xib); -+ sbinfo->si_xib = NULL; -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+/* xino for each branch */ -+static void xino_clear_br(struct super_block *sb) -+{ -+ aufs_bindex_t bindex, bbot; -+ struct au_branch *br; -+ -+ bbot = au_sbbot(sb); -+ for (bindex = 0; bindex <= bbot; bindex++) { -+ br = au_sbr(sb, bindex); -+ AuDebugOn(!br); -+ au_xino_put(br); -+ } -+} -+ -+static void au_xino_set_br_shared(struct super_block *sb, struct au_branch *br, -+ aufs_bindex_t bshared) -+{ -+ struct au_branch *brshared; -+ -+ brshared = au_sbr(sb, bshared); -+ AuDebugOn(!brshared->br_xino); -+ AuDebugOn(!brshared->br_xino->xi_file); -+ if (br->br_xino != brshared->br_xino) { -+ au_xino_get(brshared); -+ au_xino_put(br); -+ br->br_xino = brshared->br_xino; -+ } -+} -+ -+struct au_xino_do_set_br { -+ vfs_writef_t writef; -+ struct au_branch *br; -+ ino_t h_ino; -+ aufs_bindex_t bshared; -+}; -+ -+static int au_xino_do_set_br(struct super_block *sb, struct path *path, -+ struct au_xino_do_set_br *args) -+{ -+ int err; -+ struct au_xi_calc calc; -+ struct file *file; -+ struct au_branch *br; -+ struct au_xi_new xinew = { -+ .base = path -+ }; -+ -+ br = args->br; -+ xinew.xi = br->br_xino; -+ au_xi_calc(sb, args->h_ino, &calc); -+ xinew.copy_src = au_xino_file(xinew.xi, calc.idx); -+ if (args->bshared >= 0) -+ /* shared xino */ -+ au_xino_set_br_shared(sb, br, args->bshared); -+ else if (!xinew.xi) { -+ /* new xino */ -+ err = au_xino_init(br, calc.idx, xinew.copy_src); -+ if (unlikely(err)) -+ goto out; -+ } -+ -+ /* force re-creating */ -+ xinew.xi = br->br_xino; -+ xinew.idx = calc.idx; -+ mutex_lock(&xinew.xi->xi_mtx); -+ file = au_xi_new(sb, &xinew); -+ mutex_unlock(&xinew.xi->xi_mtx); -+ err = PTR_ERR(file); -+ if (IS_ERR(file)) -+ goto out; -+ AuDebugOn(!file); -+ -+ err = au_xino_do_write(args->writef, file, &calc, AUFS_ROOT_INO); -+ if (unlikely(err)) -+ au_xino_put(br); -+ -+out: -+ AuTraceErr(err); -+ return err; -+} -+ -+static int au_xino_set_br(struct super_block *sb, struct path *path) -+{ -+ int err; -+ aufs_bindex_t bindex, bbot; -+ struct au_xino_do_set_br args; -+ struct inode *inode; -+ -+ SiMustWriteLock(sb); -+ -+ bbot = au_sbbot(sb); -+ inode = d_inode(sb->s_root); -+ args.writef = au_sbi(sb)->si_xwrite; -+ for (bindex = 0; bindex <= bbot; bindex++) { -+ args.h_ino = au_h_iptr(inode, bindex)->i_ino; -+ args.br = au_sbr(sb, bindex); -+ args.bshared = is_sb_shared(sb, bindex, bindex - 1); -+ err = au_xino_do_set_br(sb, path, &args); -+ if (unlikely(err)) -+ break; -+ } -+ -+ AuTraceErr(err); -+ return err; -+} -+ -+void au_xino_clr(struct super_block *sb) -+{ -+ struct au_sbinfo *sbinfo; -+ -+ au_xigen_clr(sb); -+ xino_clear_xib(sb); -+ xino_clear_br(sb); -+ dbgaufs_brs_del(sb, 0); -+ sbinfo = au_sbi(sb); -+ /* lvalue, do not call au_mntflags() */ -+ au_opt_clr(sbinfo->si_mntflags, XINO); -+} -+ -+int au_xino_set(struct super_block *sb, struct au_opt_xino *xiopt, int remount) -+{ -+ int err, skip; -+ struct dentry *dentry, *parent, *cur_dentry, *cur_parent; -+ struct qstr *dname, *cur_name; -+ struct file *cur_xino; -+ struct au_sbinfo *sbinfo; -+ struct path *path, *cur_path; -+ -+ SiMustWriteLock(sb); -+ -+ err = 0; -+ sbinfo = au_sbi(sb); -+ path = &xiopt->file->f_path; -+ dentry = path->dentry; -+ parent = dget_parent(dentry); -+ if (remount) { -+ skip = 0; -+ cur_xino = sbinfo->si_xib; -+ if (cur_xino) { -+ cur_path = &cur_xino->f_path; -+ cur_dentry = cur_path->dentry; -+ cur_parent = dget_parent(cur_dentry); -+ cur_name = &cur_dentry->d_name; -+ dname = &dentry->d_name; -+ skip = (cur_parent == parent -+ && au_qstreq(dname, cur_name)); -+ dput(cur_parent); -+ } -+ if (skip) -+ goto out; -+ } -+ -+ au_opt_set(sbinfo->si_mntflags, XINO); -+ err = au_xino_set_xib(sb, path); -+ /* si_x{read,write} are set */ -+ if (!err) -+ err = au_xigen_set(sb, path); -+ if (!err) -+ err = au_xino_set_br(sb, path); -+ if (!err) { -+ dbgaufs_brs_add(sb, 0, /*topdown*/1); -+ goto out; /* success */ -+ } -+ -+ /* reset all */ -+ AuIOErr("failed setting xino(%d).\n", err); -+ au_xino_clr(sb); -+ -+out: -+ dput(parent); -+ return err; -+} -+ -+/* -+ * create a xinofile at the default place/path. -+ */ -+struct file *au_xino_def(struct super_block *sb) -+{ -+ struct file *file; -+ char *page, *p; -+ struct au_branch *br; -+ struct super_block *h_sb; -+ struct path path; -+ aufs_bindex_t bbot, bindex, bwr; -+ -+ br = NULL; -+ bbot = au_sbbot(sb); -+ bwr = -1; -+ for (bindex = 0; bindex <= bbot; bindex++) { -+ br = au_sbr(sb, bindex); -+ if (au_br_writable(br->br_perm) -+ && !au_test_fs_bad_xino(au_br_sb(br))) { -+ bwr = bindex; -+ break; -+ } -+ } -+ -+ if (bwr >= 0) { -+ file = ERR_PTR(-ENOMEM); -+ page = (void *)__get_free_page(GFP_NOFS); -+ if (unlikely(!page)) -+ goto out; -+ path.mnt = au_br_mnt(br); -+ path.dentry = au_h_dptr(sb->s_root, bwr); -+ p = d_path(&path, page, PATH_MAX - sizeof(AUFS_XINO_FNAME)); -+ file = (void *)p; -+ if (!IS_ERR(p)) { -+ strcat(p, "/" AUFS_XINO_FNAME); -+ AuDbg("%s\n", p); -+ file = au_xino_create(sb, p, /*silent*/0, /*wbrtop*/1); -+ } -+ free_page((unsigned long)page); -+ } else { -+ file = au_xino_create(sb, AUFS_XINO_DEFPATH, /*silent*/0, -+ /*wbrtop*/0); -+ if (IS_ERR(file)) -+ goto out; -+ h_sb = file->f_path.dentry->d_sb; -+ if (unlikely(au_test_fs_bad_xino(h_sb))) { -+ pr_err("xino doesn't support %s(%s)\n", -+ AUFS_XINO_DEFPATH, au_sbtype(h_sb)); -+ fput(file); -+ file = ERR_PTR(-EINVAL); -+ } -+ } -+ -+out: -+ return file; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * initialize the xinofile for the specified branch @br -+ * at the place/path where @base_file indicates. -+ * test whether another branch is on the same filesystem or not, -+ * if found then share the xinofile with another branch. -+ */ -+int au_xino_init_br(struct super_block *sb, struct au_branch *br, ino_t h_ino, -+ struct path *base) -+{ -+ int err; -+ struct au_xino_do_set_br args = { -+ .h_ino = h_ino, -+ .br = br -+ }; -+ -+ args.writef = au_sbi(sb)->si_xwrite; -+ args.bshared = sbr_find_shared(sb, /*btop*/0, au_sbbot(sb), -+ au_br_sb(br)); -+ err = au_xino_do_set_br(sb, base, &args); -+ if (unlikely(err)) -+ au_xino_put(br); -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * get an unused inode number from bitmap -+ */ -+ino_t au_xino_new_ino(struct super_block *sb) -+{ -+ ino_t ino; -+ unsigned long *p, pindex, ul, pend; -+ struct au_sbinfo *sbinfo; -+ struct file *file; -+ int free_bit, err; -+ -+ if (!au_opt_test(au_mntflags(sb), XINO)) -+ return iunique(sb, AUFS_FIRST_INO); -+ -+ sbinfo = au_sbi(sb); -+ mutex_lock(&sbinfo->si_xib_mtx); -+ p = sbinfo->si_xib_buf; -+ free_bit = sbinfo->si_xib_next_bit; -+ if (free_bit < page_bits && !test_bit(free_bit, p)) -+ goto out; /* success */ -+ free_bit = find_first_zero_bit(p, page_bits); -+ if (free_bit < page_bits) -+ goto out; /* success */ -+ -+ pindex = sbinfo->si_xib_last_pindex; -+ for (ul = pindex - 1; ul < ULONG_MAX; ul--) { -+ err = xib_pindex(sb, ul); -+ if (unlikely(err)) -+ goto out_err; -+ free_bit = find_first_zero_bit(p, page_bits); -+ if (free_bit < page_bits) -+ goto out; /* success */ -+ } -+ -+ file = sbinfo->si_xib; -+ pend = vfsub_f_size_read(file) / PAGE_SIZE; -+ for (ul = pindex + 1; ul <= pend; ul++) { -+ err = xib_pindex(sb, ul); -+ if (unlikely(err)) -+ goto out_err; -+ free_bit = find_first_zero_bit(p, page_bits); -+ if (free_bit < page_bits) -+ goto out; /* success */ -+ } -+ BUG(); -+ -+out: -+ set_bit(free_bit, p); -+ sbinfo->si_xib_next_bit = free_bit + 1; -+ pindex = sbinfo->si_xib_last_pindex; -+ mutex_unlock(&sbinfo->si_xib_mtx); -+ ino = xib_calc_ino(pindex, free_bit); -+ AuDbg("i%lu\n", (unsigned long)ino); -+ return ino; -+out_err: -+ mutex_unlock(&sbinfo->si_xib_mtx); -+ AuDbg("i0\n"); -+ return 0; -+} -+ -+/* for s_op->delete_inode() */ -+void au_xino_delete_inode(struct inode *inode, const int unlinked) -+{ -+ int err; -+ unsigned int mnt_flags; -+ aufs_bindex_t bindex, bbot, bi; -+ unsigned char try_trunc; -+ struct au_iinfo *iinfo; -+ struct super_block *sb; -+ struct au_hinode *hi; -+ struct inode *h_inode; -+ struct au_branch *br; -+ vfs_writef_t xwrite; -+ struct au_xi_calc calc; -+ struct file *file; -+ -+ AuDebugOn(au_is_bad_inode(inode)); -+ -+ sb = inode->i_sb; -+ mnt_flags = au_mntflags(sb); -+ if (!au_opt_test(mnt_flags, XINO) -+ || inode->i_ino == AUFS_ROOT_INO) -+ return; -+ -+ if (unlinked) { -+ au_xigen_inc(inode); -+ au_xib_clear_bit(inode); -+ } -+ -+ iinfo = au_ii(inode); -+ bindex = iinfo->ii_btop; -+ if (bindex < 0) -+ return; -+ -+ xwrite = au_sbi(sb)->si_xwrite; -+ try_trunc = !!au_opt_test(mnt_flags, TRUNC_XINO); -+ hi = au_hinode(iinfo, bindex); -+ bbot = iinfo->ii_bbot; -+ for (; bindex <= bbot; bindex++, hi++) { -+ h_inode = hi->hi_inode; -+ if (!h_inode -+ || (!unlinked && h_inode->i_nlink)) -+ continue; -+ -+ /* inode may not be revalidated */ -+ bi = au_br_index(sb, hi->hi_id); -+ if (bi < 0) -+ continue; -+ -+ br = au_sbr(sb, bi); -+ au_xi_calc(sb, h_inode->i_ino, &calc); -+ file = au_xino_file(br->br_xino, calc.idx); -+ if (IS_ERR_OR_NULL(file)) -+ continue; -+ -+ err = au_xino_do_write(xwrite, file, &calc, /*ino*/0); -+ if (!err && try_trunc -+ && au_test_fs_trunc_xino(au_br_sb(br))) -+ xino_try_trunc(sb, br); -+ } -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int au_xinondir_find(struct au_xino *xi, ino_t h_ino) -+{ -+ int found, total, i; -+ -+ found = -1; -+ total = xi->xi_nondir.total; -+ for (i = 0; i < total; i++) { -+ if (xi->xi_nondir.array[i] != h_ino) -+ continue; -+ found = i; -+ break; -+ } -+ -+ return found; -+} -+ -+static int au_xinondir_expand(struct au_xino *xi) -+{ -+ int err, sz; -+ ino_t *p; -+ -+ BUILD_BUG_ON(KMALLOC_MAX_SIZE > INT_MAX); -+ -+ err = -ENOMEM; -+ sz = xi->xi_nondir.total * sizeof(ino_t); -+ if (unlikely(sz > KMALLOC_MAX_SIZE / 2)) -+ goto out; -+ p = au_kzrealloc(xi->xi_nondir.array, sz, sz << 1, GFP_ATOMIC, -+ /*may_shrink*/0); -+ if (p) { -+ xi->xi_nondir.array = p; -+ xi->xi_nondir.total <<= 1; -+ AuDbg("xi_nondir.total %d\n", xi->xi_nondir.total); -+ err = 0; -+ } -+ -+out: -+ return err; -+} -+ -+void au_xinondir_leave(struct super_block *sb, aufs_bindex_t bindex, -+ ino_t h_ino, int idx) -+{ -+ struct au_xino *xi; -+ -+ AuDebugOn(!au_opt_test(au_mntflags(sb), XINO)); -+ xi = au_sbr(sb, bindex)->br_xino; -+ AuDebugOn(idx < 0 || xi->xi_nondir.total <= idx); -+ -+ spin_lock(&xi->xi_nondir.spin); -+ AuDebugOn(xi->xi_nondir.array[idx] != h_ino); -+ xi->xi_nondir.array[idx] = 0; -+ spin_unlock(&xi->xi_nondir.spin); -+ wake_up_all(&xi->xi_nondir.wqh); -+} -+ -+int au_xinondir_enter(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, -+ int *idx) -+{ -+ int err, found, empty; -+ struct au_xino *xi; -+ -+ err = 0; -+ *idx = -1; -+ if (!au_opt_test(au_mntflags(sb), XINO)) -+ goto out; /* no xino */ -+ -+ xi = au_sbr(sb, bindex)->br_xino; -+ -+again: -+ spin_lock(&xi->xi_nondir.spin); -+ found = au_xinondir_find(xi, h_ino); -+ if (found == -1) { -+ empty = au_xinondir_find(xi, /*h_ino*/0); -+ if (empty == -1) { -+ empty = xi->xi_nondir.total; -+ err = au_xinondir_expand(xi); -+ if (unlikely(err)) -+ goto out_unlock; -+ } -+ xi->xi_nondir.array[empty] = h_ino; -+ *idx = empty; -+ } else { -+ spin_unlock(&xi->xi_nondir.spin); -+ wait_event(xi->xi_nondir.wqh, -+ xi->xi_nondir.array[found] != h_ino); -+ goto again; -+ } -+ -+out_unlock: -+ spin_unlock(&xi->xi_nondir.spin); -+out: -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+int au_xino_path(struct seq_file *seq, struct file *file) -+{ -+ int err; -+ -+ err = au_seq_path(seq, &file->f_path); -+ if (unlikely(err)) -+ goto out; -+ -+#define Deleted "\\040(deleted)" -+ seq->count -= sizeof(Deleted) - 1; -+ AuDebugOn(memcmp(seq->buf + seq->count, Deleted, -+ sizeof(Deleted) - 1)); -+#undef Deleted -+ -+out: -+ return err; -+} -diff -Nurp linux-5.10-rc6/fs/dcache.c linux-5.10-rc6.aufs/fs/dcache.c ---- linux-5.10-rc6/fs/dcache.c 2020-10-12 00:15:50.000000000 +0300 -+++ linux-5.10-rc6.aufs/fs/dcache.c 2020-12-02 21:19:51.885036923 +0200 -@@ -1285,7 +1285,7 @@ enum d_walk_ret { - * - * The @enter() callbacks are called with d_lock held. - */ --static void d_walk(struct dentry *parent, void *data, -+void d_walk(struct dentry *parent, void *data, - enum d_walk_ret (*enter)(void *, struct dentry *)) - { - struct dentry *this_parent; -@@ -1390,6 +1390,7 @@ rename_retry: - seq = 1; - goto again; - } -+EXPORT_SYMBOL_GPL(d_walk); - - struct check_mount { - struct vfsmount *mnt; -@@ -2935,6 +2936,7 @@ void d_exchange(struct dentry *dentry1, - - write_sequnlock(&rename_lock); - } -+EXPORT_SYMBOL_GPL(d_exchange); - - /** - * d_ancestor - search for an ancestor -diff -Nurp linux-5.10-rc6/fs/exec.c linux-5.10-rc6.aufs/fs/exec.c ---- linux-5.10-rc6/fs/exec.c 2020-12-02 21:18:30.978421631 +0200 -+++ linux-5.10-rc6.aufs/fs/exec.c 2020-12-02 21:19:51.885036923 +0200 -@@ -113,6 +113,7 @@ bool path_noexec(const struct path *path - return (path->mnt->mnt_flags & MNT_NOEXEC) || - (path->mnt->mnt_sb->s_iflags & SB_I_NOEXEC); - } -+EXPORT_SYMBOL_GPL(path_noexec); - - #ifdef CONFIG_USELIB - /* -diff -Nurp linux-5.10-rc6/fs/fcntl.c linux-5.10-rc6.aufs/fs/fcntl.c ---- linux-5.10-rc6/fs/fcntl.c 2020-10-12 00:15:50.000000000 +0300 -+++ linux-5.10-rc6.aufs/fs/fcntl.c 2020-12-02 21:19:51.885036923 +0200 -@@ -32,7 +32,7 @@ - - #define SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | O_DIRECT | O_NOATIME) - --static int setfl(int fd, struct file * filp, unsigned long arg) -+int setfl(int fd, struct file *filp, unsigned long arg) - { - struct inode * inode = file_inode(filp); - int error = 0; -@@ -63,6 +63,8 @@ static int setfl(int fd, struct file * f - - if (filp->f_op->check_flags) - error = filp->f_op->check_flags(arg); -+ if (!error && filp->f_op->setfl) -+ error = filp->f_op->setfl(filp, arg); - if (error) - return error; - -@@ -83,6 +85,7 @@ static int setfl(int fd, struct file * f - out: - return error; - } -+EXPORT_SYMBOL_GPL(setfl); - - static void f_modown(struct file *filp, struct pid *pid, enum pid_type type, - int force) -diff -Nurp linux-5.10-rc6/fs/file_table.c linux-5.10-rc6.aufs/fs/file_table.c ---- linux-5.10-rc6/fs/file_table.c 2020-12-02 21:18:30.986421988 +0200 -+++ linux-5.10-rc6.aufs/fs/file_table.c 2020-12-02 21:19:51.885036923 +0200 -@@ -162,6 +162,7 @@ over: - } - return ERR_PTR(-ENFILE); - } -+EXPORT_SYMBOL_GPL(alloc_empty_file); - - /* - * Variant of alloc_empty_file() that doesn't check and modify nr_files. -@@ -376,6 +377,7 @@ void __fput_sync(struct file *file) - } - - EXPORT_SYMBOL(fput); -+EXPORT_SYMBOL_GPL(__fput_sync); - - void __init files_init(void) - { -diff -Nurp linux-5.10-rc6/fs/inode.c linux-5.10-rc6.aufs/fs/inode.c ---- linux-5.10-rc6/fs/inode.c 2020-12-02 21:18:30.990422167 +0200 -+++ linux-5.10-rc6.aufs/fs/inode.c 2020-12-02 21:19:51.885036923 +0200 -@@ -1770,12 +1770,13 @@ EXPORT_SYMBOL(generic_update_time); - * This does the actual work of updating an inodes time or version. Must have - * had called mnt_want_write() before calling this. - */ --static int update_time(struct inode *inode, struct timespec64 *time, int flags) -+int update_time(struct inode *inode, struct timespec64 *time, int flags) - { - if (inode->i_op->update_time) - return inode->i_op->update_time(inode, time, flags); - return generic_update_time(inode, time, flags); - } -+EXPORT_SYMBOL_GPL(update_time); - - /** - * touch_atime - update the access time -diff -Nurp linux-5.10-rc6/fs/Kconfig linux-5.10-rc6.aufs/fs/Kconfig ---- linux-5.10-rc6/fs/Kconfig 2020-10-12 00:15:50.000000000 +0300 -+++ linux-5.10-rc6.aufs/fs/Kconfig 2020-12-02 21:19:51.879036653 +0200 -@@ -288,6 +288,7 @@ source "fs/sysv/Kconfig" - source "fs/ufs/Kconfig" - source "fs/erofs/Kconfig" - source "fs/vboxsf/Kconfig" -+source "fs/aufs/Kconfig" - - endif # MISC_FILESYSTEMS - -diff -Nurp linux-5.10-rc6/fs/Makefile linux-5.10-rc6.aufs/fs/Makefile ---- linux-5.10-rc6/fs/Makefile 2020-12-02 21:18:30.963420960 +0200 -+++ linux-5.10-rc6.aufs/fs/Makefile 2020-12-02 21:19:51.879036653 +0200 -@@ -136,3 +136,4 @@ obj-$(CONFIG_EFIVAR_FS) += efivarfs/ - obj-$(CONFIG_EROFS_FS) += erofs/ - obj-$(CONFIG_VBOXSF_FS) += vboxsf/ - obj-$(CONFIG_ZONEFS_FS) += zonefs/ -+obj-$(CONFIG_AUFS_FS) += aufs/ -diff -Nurp linux-5.10-rc6/fs/namespace.c linux-5.10-rc6.aufs/fs/namespace.c ---- linux-5.10-rc6/fs/namespace.c 2020-12-02 21:18:30.993422301 +0200 -+++ linux-5.10-rc6.aufs/fs/namespace.c 2020-12-02 21:19:51.885036923 +0200 -@@ -431,6 +431,7 @@ void __mnt_drop_write(struct vfsmount *m - mnt_dec_writers(real_mount(mnt)); - preempt_enable(); - } -+EXPORT_SYMBOL_GPL(__mnt_drop_write); - - /** - * mnt_drop_write - give up write access to a mount -@@ -792,6 +793,13 @@ static inline int check_mnt(struct mount - return mnt->mnt_ns == current->nsproxy->mnt_ns; - } - -+/* for aufs, CONFIG_AUFS_BR_FUSE */ -+int is_current_mnt_ns(struct vfsmount *mnt) -+{ -+ return check_mnt(real_mount(mnt)); -+} -+EXPORT_SYMBOL_GPL(is_current_mnt_ns); -+ - /* - * vfsmount lock must be held for write - */ -@@ -1955,6 +1963,7 @@ int iterate_mounts(int (*f)(struct vfsmo - } - return 0; - } -+EXPORT_SYMBOL_GPL(iterate_mounts); - - static void lock_mnt_tree(struct mount *mnt) - { -diff -Nurp linux-5.10-rc6/fs/notify/group.c linux-5.10-rc6.aufs/fs/notify/group.c ---- linux-5.10-rc6/fs/notify/group.c 2020-10-12 00:15:50.000000000 +0300 -+++ linux-5.10-rc6.aufs/fs/notify/group.c 2020-12-02 21:19:51.885036923 +0200 -@@ -100,6 +100,7 @@ void fsnotify_get_group(struct fsnotify_ - { - refcount_inc(&group->refcnt); - } -+EXPORT_SYMBOL_GPL(fsnotify_get_group); - - /* - * Drop a reference to a group. Free it if it's through. -diff -Nurp linux-5.10-rc6/fs/open.c linux-5.10-rc6.aufs/fs/open.c ---- linux-5.10-rc6/fs/open.c 2020-10-12 00:15:50.000000000 +0300 -+++ linux-5.10-rc6.aufs/fs/open.c 2020-12-02 21:19:51.885036923 +0200 -@@ -65,6 +65,7 @@ int do_truncate(struct dentry *dentry, l - inode_unlock(dentry->d_inode); - return ret; - } -+EXPORT_SYMBOL_GPL(do_truncate); - - long vfs_truncate(const struct path *path, loff_t length) - { -diff -Nurp linux-5.10-rc6/fs/proc/base.c linux-5.10-rc6.aufs/fs/proc/base.c ---- linux-5.10-rc6/fs/proc/base.c 2020-12-02 21:18:31.000422613 +0200 -+++ linux-5.10-rc6.aufs/fs/proc/base.c 2020-12-02 21:19:51.885036923 +0200 -@@ -2184,7 +2184,7 @@ static int map_files_get_link(struct den - rc = -ENOENT; - vma = find_exact_vma(mm, vm_start, vm_end); - if (vma && vma->vm_file) { -- *path = vma->vm_file->f_path; -+ *path = vma_pr_or_file(vma)->f_path; - path_get(path); - rc = 0; - } -diff -Nurp linux-5.10-rc6/fs/proc/nommu.c linux-5.10-rc6.aufs/fs/proc/nommu.c ---- linux-5.10-rc6/fs/proc/nommu.c 2020-10-12 00:15:50.000000000 +0300 -+++ linux-5.10-rc6.aufs/fs/proc/nommu.c 2020-12-02 21:19:51.885036923 +0200 -@@ -40,7 +40,10 @@ static int nommu_region_show(struct seq_ - file = region->vm_file; - - if (file) { -- struct inode *inode = file_inode(region->vm_file); -+ struct inode *inode; -+ -+ file = vmr_pr_or_file(region); -+ inode = file_inode(file); - dev = inode->i_sb->s_dev; - ino = inode->i_ino; - } -diff -Nurp linux-5.10-rc6/fs/proc/task_mmu.c linux-5.10-rc6.aufs/fs/proc/task_mmu.c ---- linux-5.10-rc6/fs/proc/task_mmu.c 2020-12-02 21:18:31.000422613 +0200 -+++ linux-5.10-rc6.aufs/fs/proc/task_mmu.c 2020-12-02 21:19:51.885036923 +0200 -@@ -280,7 +280,10 @@ show_map_vma(struct seq_file *m, struct - const char *name = NULL; - - if (file) { -- struct inode *inode = file_inode(vma->vm_file); -+ struct inode *inode; -+ -+ file = vma_pr_or_file(vma); -+ inode = file_inode(file); - dev = inode->i_sb->s_dev; - ino = inode->i_ino; - pgoff = ((loff_t)vma->vm_pgoff) << PAGE_SHIFT; -@@ -1851,7 +1854,7 @@ static int show_numa_map(struct seq_file - struct proc_maps_private *proc_priv = &numa_priv->proc_maps; - struct vm_area_struct *vma = v; - struct numa_maps *md = &numa_priv->md; -- struct file *file = vma->vm_file; -+ struct file *file = vma_pr_or_file(vma); - struct mm_struct *mm = vma->vm_mm; - struct mempolicy *pol; - char buffer[64]; -diff -Nurp linux-5.10-rc6/fs/proc/task_nommu.c linux-5.10-rc6.aufs/fs/proc/task_nommu.c ---- linux-5.10-rc6/fs/proc/task_nommu.c 2020-10-12 00:15:50.000000000 +0300 -+++ linux-5.10-rc6.aufs/fs/proc/task_nommu.c 2020-12-02 21:19:51.885036923 +0200 -@@ -155,7 +155,10 @@ static int nommu_vma_show(struct seq_fil - file = vma->vm_file; - - if (file) { -- struct inode *inode = file_inode(vma->vm_file); -+ struct inode *inode; -+ -+ file = vma_pr_or_file(vma); -+ inode = file_inode(file); - dev = inode->i_sb->s_dev; - ino = inode->i_ino; - pgoff = (loff_t)vma->vm_pgoff << PAGE_SHIFT; -diff -Nurp linux-5.10-rc6/fs/read_write.c linux-5.10-rc6.aufs/fs/read_write.c ---- linux-5.10-rc6/fs/read_write.c 2020-12-02 21:18:31.001422659 +0200 -+++ linux-5.10-rc6.aufs/fs/read_write.c 2020-12-02 21:19:51.886036968 +0200 -@@ -503,6 +503,7 @@ ssize_t vfs_read(struct file *file, char - inc_syscr(current); - return ret; - } -+EXPORT_SYMBOL_GPL(vfs_read); - - static ssize_t new_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos) - { -@@ -523,6 +524,30 @@ static ssize_t new_sync_write(struct fil - } - - /* caller is responsible for file_start_write/file_end_write */ -+vfs_readf_t vfs_readf(struct file *file) -+{ -+ const struct file_operations *fop = file->f_op; -+ -+ if (fop->read) -+ return fop->read; -+ if (fop->read_iter) -+ return new_sync_read; -+ return ERR_PTR(-ENOSYS); /* doesn't have ->read(|_iter)() op */ -+} -+EXPORT_SYMBOL_GPL(vfs_readf); -+ -+vfs_writef_t vfs_writef(struct file *file) -+{ -+ const struct file_operations *fop = file->f_op; -+ -+ if (fop->write) -+ return fop->write; -+ if (fop->write_iter) -+ return new_sync_write; -+ return ERR_PTR(-ENOSYS); /* doesn't have ->write(|_iter)() op */ -+} -+EXPORT_SYMBOL_GPL(vfs_writef); -+ - ssize_t __kernel_write(struct file *file, const void *buf, size_t count, loff_t *pos) - { - struct kvec iov = { -@@ -613,6 +638,7 @@ ssize_t vfs_write(struct file *file, con - file_end_write(file); - return ret; - } -+EXPORT_SYMBOL_GPL(vfs_write); - - /* file_ppos returns &file->f_pos or NULL if file is stream */ - static inline loff_t *file_ppos(struct file *file) -diff -Nurp linux-5.10-rc6/fs/splice.c linux-5.10-rc6.aufs/fs/splice.c ---- linux-5.10-rc6/fs/splice.c 2020-12-02 21:18:31.002422703 +0200 -+++ linux-5.10-rc6.aufs/fs/splice.c 2020-12-02 21:19:51.886036968 +0200 -@@ -756,8 +756,8 @@ static int warn_unsupported(struct file - /* - * 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) - { - if (unlikely(!out->f_op->splice_write)) - return warn_unsupported(out, "write"); -@@ -767,9 +767,9 @@ static long do_splice_from(struct pipe_i - /* - * Attempt to initiate a splice from a file to a pipe. - */ --static long do_splice_to(struct file *in, loff_t *ppos, -- struct pipe_inode_info *pipe, size_t len, -- unsigned int flags) -+long do_splice_to(struct file *in, loff_t *ppos, -+ struct pipe_inode_info *pipe, size_t len, -+ unsigned int flags) - { - int ret; - -@@ -787,6 +787,7 @@ static long do_splice_to(struct file *in - return warn_unsupported(in, "read"); - return in->f_op->splice_read(in, ppos, pipe, len, flags); - } -+EXPORT_SYMBOL_GPL(do_splice_from); - - /** - * splice_direct_to_actor - splices data directly between two non-pipes -@@ -933,6 +934,7 @@ static int direct_splice_actor(struct pi - return do_splice_from(pipe, file, sd->opos, sd->total_len, - sd->flags); - } -+EXPORT_SYMBOL_GPL(do_splice_to); - - /** - * do_splice_direct - splices data directly between two files -diff -Nurp linux-5.10-rc6/fs/sync.c linux-5.10-rc6.aufs/fs/sync.c ---- linux-5.10-rc6/fs/sync.c 2020-10-12 00:15:50.000000000 +0300 -+++ linux-5.10-rc6.aufs/fs/sync.c 2020-12-02 21:19:51.886036968 +0200 -@@ -28,7 +28,7 @@ - * wait == 1 case since in that case write_inode() functions do - * sync_dirty_buffer() and thus effectively write one block at a time. - */ --static int __sync_filesystem(struct super_block *sb, int wait) -+int __sync_filesystem(struct super_block *sb, int wait) - { - if (wait) - sync_inodes_sb(sb); -@@ -39,6 +39,7 @@ static int __sync_filesystem(struct supe - sb->s_op->sync_fs(sb, wait); - return __sync_blockdev(sb->s_bdev, wait); - } -+EXPORT_SYMBOL_GPL(__sync_filesystem); - - /* - * Write out and wait upon all dirty data associated with this -diff -Nurp linux-5.10-rc6/fs/xattr.c linux-5.10-rc6.aufs/fs/xattr.c ---- linux-5.10-rc6/fs/xattr.c 2020-12-02 21:18:31.004422793 +0200 -+++ linux-5.10-rc6.aufs/fs/xattr.c 2020-12-02 21:19:51.886036968 +0200 -@@ -360,6 +360,7 @@ vfs_getxattr_alloc(struct dentry *dentry - *xattr_value = value; - return error; - } -+EXPORT_SYMBOL_GPL(vfs_getxattr_alloc); - - ssize_t - __vfs_getxattr(struct dentry *dentry, struct inode *inode, const char *name, -diff -Nurp linux-5.10-rc6/include/linux/fs.h linux-5.10-rc6.aufs/include/linux/fs.h ---- linux-5.10-rc6/include/linux/fs.h 2020-12-02 21:18:31.018423418 +0200 -+++ linux-5.10-rc6.aufs/include/linux/fs.h 2020-12-02 21:19:51.886036968 +0200 -@@ -1332,6 +1332,7 @@ extern void fasync_free(struct fasync_st - /* can be called from interrupts */ - extern void kill_fasync(struct fasync_struct **, int, int); - -+extern int setfl(int fd, struct file *filp, unsigned long arg); - extern void __f_setown(struct file *filp, struct pid *, enum pid_type, int force); - extern int f_setown(struct file *filp, unsigned long arg, int force); - extern void f_delown(struct file *filp); -@@ -1843,6 +1844,7 @@ struct file_operations { - ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int); - unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); - int (*check_flags)(int); -+ int (*setfl)(struct file *, unsigned long); - int (*flock) (struct file *, int, struct file_lock *); - ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int); - ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int); -@@ -1908,6 +1910,12 @@ static inline int call_mmap(struct file - return file->f_op->mmap(file, vma); - } - -+typedef ssize_t (*vfs_readf_t)(struct file *, char __user *, size_t, loff_t *); -+typedef ssize_t (*vfs_writef_t)(struct file *, const char __user *, size_t, -+ loff_t *); -+vfs_readf_t vfs_readf(struct file *file); -+vfs_writef_t vfs_writef(struct file *file); -+ - extern ssize_t vfs_read(struct file *, char __user *, size_t, loff_t *); - extern ssize_t vfs_write(struct file *, const char __user *, size_t, loff_t *); - extern ssize_t vfs_copy_file_range(struct file *, loff_t , struct file *, -@@ -2328,6 +2336,7 @@ extern int current_umask(void); - extern void ihold(struct inode * inode); - extern void iput(struct inode *); - extern int generic_update_time(struct inode *, struct timespec64 *, int); -+extern int update_time(struct inode *, struct timespec64 *, int); - - /* /sys/fs */ - extern struct kobject *fs_kobj; -@@ -2564,6 +2573,7 @@ static inline bool sb_is_blkdev_sb(struc - } - - void emergency_thaw_all(void); -+extern int __sync_filesystem(struct super_block *, int); - extern int sync_filesystem(struct super_block *); - extern const struct file_operations def_blk_fops; - extern const struct file_operations def_chr_fops; -diff -Nurp linux-5.10-rc6/include/linux/lockdep.h linux-5.10-rc6.aufs/include/linux/lockdep.h ---- linux-5.10-rc6/include/linux/lockdep.h 2020-12-02 21:18:31.021423552 +0200 -+++ linux-5.10-rc6.aufs/include/linux/lockdep.h 2020-12-02 21:19:51.886036968 +0200 -@@ -241,6 +241,8 @@ static inline int lockdep_match_key(stru - return lock->key == key; - } - -+struct lock_class *lockdep_hlock_class(struct held_lock *hlock); -+ - /* - * Acquire a lock. - * -@@ -375,6 +377,7 @@ static inline void lockdep_unregister_ke - - #define lockdep_depth(tsk) (0) - -+#define lockdep_is_held(lock) (1) - #define lockdep_is_held_type(l, r) (1) - - #define lockdep_assert_held(l) do { (void)(l); } while (0) -diff -Nurp linux-5.10-rc6/include/linux/mm.h linux-5.10-rc6.aufs/include/linux/mm.h ---- linux-5.10-rc6/include/linux/mm.h 2020-12-02 21:18:31.023423642 +0200 -+++ linux-5.10-rc6.aufs/include/linux/mm.h 2020-12-02 21:19:51.886036968 +0200 -@@ -1712,6 +1712,28 @@ static inline void unmap_shared_mapping_ - unmap_mapping_range(mapping, holebegin, holelen, 0); - } - -+extern void vma_do_file_update_time(struct vm_area_struct *, const char[], int); -+extern struct file *vma_do_pr_or_file(struct vm_area_struct *, const char[], -+ int); -+extern void vma_do_get_file(struct vm_area_struct *, const char[], int); -+extern void vma_do_fput(struct vm_area_struct *, const char[], int); -+ -+#define vma_file_update_time(vma) vma_do_file_update_time(vma, __func__, \ -+ __LINE__) -+#define vma_pr_or_file(vma) vma_do_pr_or_file(vma, __func__, \ -+ __LINE__) -+#define vma_get_file(vma) vma_do_get_file(vma, __func__, __LINE__) -+#define vma_fput(vma) vma_do_fput(vma, __func__, __LINE__) -+ -+#ifndef CONFIG_MMU -+extern struct file *vmr_do_pr_or_file(struct vm_region *, const char[], int); -+extern void vmr_do_fput(struct vm_region *, const char[], int); -+ -+#define vmr_pr_or_file(region) vmr_do_pr_or_file(region, __func__, \ -+ __LINE__) -+#define vmr_fput(region) vmr_do_fput(region, __func__, __LINE__) -+#endif /* !CONFIG_MMU */ -+ - extern int access_process_vm(struct task_struct *tsk, unsigned long addr, - void *buf, int len, unsigned int gup_flags); - extern int access_remote_vm(struct mm_struct *mm, unsigned long addr, -diff -Nurp linux-5.10-rc6/include/linux/mm_types.h linux-5.10-rc6.aufs/include/linux/mm_types.h ---- linux-5.10-rc6/include/linux/mm_types.h 2020-12-02 21:18:31.023423642 +0200 -+++ linux-5.10-rc6.aufs/include/linux/mm_types.h 2020-12-02 21:19:51.886036968 +0200 -@@ -280,6 +280,7 @@ struct vm_region { - unsigned long vm_top; /* region allocated to here */ - unsigned long vm_pgoff; /* the offset in vm_file corresponding to vm_start */ - struct file *vm_file; /* the backing file or NULL */ -+ struct file *vm_prfile; /* the virtual backing file or NULL */ - - int vm_usage; /* region usage count (access under nommu_region_sem) */ - bool vm_icache_flushed : 1; /* true if the icache has been flushed for -@@ -359,6 +360,7 @@ struct vm_area_struct { - unsigned long vm_pgoff; /* Offset (within vm_file) in PAGE_SIZE - units */ - struct file * vm_file; /* File we map to (can be NULL). */ -+ struct file *vm_prfile; /* shadow of vm_file */ - void * vm_private_data; /* was vm_pte (shared mem) */ - - #ifdef CONFIG_SWAP -diff -Nurp linux-5.10-rc6/include/linux/mnt_namespace.h linux-5.10-rc6.aufs/include/linux/mnt_namespace.h ---- linux-5.10-rc6/include/linux/mnt_namespace.h 2020-10-12 00:15:50.000000000 +0300 -+++ linux-5.10-rc6.aufs/include/linux/mnt_namespace.h 2020-12-02 21:19:51.886036968 +0200 -@@ -7,12 +7,15 @@ struct mnt_namespace; - struct fs_struct; - struct user_namespace; - struct ns_common; -+struct vfsmount; - - extern struct mnt_namespace *copy_mnt_ns(unsigned long, struct mnt_namespace *, - struct user_namespace *, struct fs_struct *); - extern void put_mnt_ns(struct mnt_namespace *ns); - extern struct ns_common *from_mnt_ns(struct mnt_namespace *); - -+extern int is_current_mnt_ns(struct vfsmount *mnt); -+ - extern const struct file_operations proc_mounts_operations; - extern const struct file_operations proc_mountinfo_operations; - extern const struct file_operations proc_mountstats_operations; -diff -Nurp linux-5.10-rc6/include/linux/splice.h linux-5.10-rc6.aufs/include/linux/splice.h ---- linux-5.10-rc6/include/linux/splice.h 2020-12-02 21:18:31.030423955 +0200 -+++ linux-5.10-rc6.aufs/include/linux/splice.h 2020-12-02 21:19:51.886036968 +0200 -@@ -93,4 +93,10 @@ extern void splice_shrink_spd(struct spl - - extern const struct pipe_buf_operations page_cache_pipe_buf_ops; - extern const struct pipe_buf_operations default_pipe_buf_ops; -+ -+extern long do_splice_from(struct pipe_inode_info *pipe, struct file *out, -+ loff_t *ppos, size_t len, unsigned int flags); -+extern long do_splice_to(struct file *in, loff_t *ppos, -+ struct pipe_inode_info *pipe, size_t len, -+ unsigned int flags); - #endif -diff -Nurp linux-5.10-rc6/include/uapi/linux/aufs_type.h linux-5.10-rc6.aufs/include/uapi/linux/aufs_type.h ---- linux-5.10-rc6/include/uapi/linux/aufs_type.h 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/include/uapi/linux/aufs_type.h 2020-12-02 21:19:51.886036968 +0200 -@@ -0,0 +1,439 @@ -+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -+/* -+ * Copyright (C) 2005-2020 Junjiro R. Okajima -+ */ -+ -+#ifndef __AUFS_TYPE_H__ -+#define __AUFS_TYPE_H__ -+ -+#define AUFS_NAME "aufs" -+ -+#ifdef __KERNEL__ -+/* -+ * define it before including all other headers. -+ * sched.h may use pr_* macros before defining "current", so define the -+ * no-current version first, and re-define later. -+ */ -+#define pr_fmt(fmt) AUFS_NAME " %s:%d: " fmt, __func__, __LINE__ -+#include -+#undef pr_fmt -+#define pr_fmt(fmt) \ -+ AUFS_NAME " %s:%d:%.*s[%d]: " fmt, __func__, __LINE__, \ -+ (int)sizeof(current->comm), current->comm, current->pid -+#include -+#else -+#include -+#include -+#include -+#endif /* __KERNEL__ */ -+ -+#define AUFS_VERSION "5.7" -+ -+/* todo? move this to linux-2.6.19/include/magic.h */ -+#define AUFS_SUPER_MAGIC ('a' << 24 | 'u' << 16 | 'f' << 8 | 's') -+ -+/* ---------------------------------------------------------------------- */ -+ -+#ifdef __KERNEL__ -+#ifdef CONFIG_AUFS_BRANCH_MAX_127 -+typedef int8_t aufs_bindex_t; -+#define AUFS_BRANCH_MAX 127 -+#else -+typedef int16_t aufs_bindex_t; -+#ifdef CONFIG_AUFS_BRANCH_MAX_511 -+#define AUFS_BRANCH_MAX 511 -+#elif defined(CONFIG_AUFS_BRANCH_MAX_1023) -+#define AUFS_BRANCH_MAX 1023 -+#elif defined(CONFIG_AUFS_BRANCH_MAX_32767) -+#define AUFS_BRANCH_MAX 32767 -+#endif -+#endif -+ -+#ifndef AUFS_BRANCH_MAX -+#error unknown CONFIG_AUFS_BRANCH_MAX value -+#endif -+#endif /* __KERNEL__ */ -+ -+/* ---------------------------------------------------------------------- */ -+ -+#define AUFS_FSTYPE AUFS_NAME -+ -+#define AUFS_ROOT_INO 2 -+#define AUFS_FIRST_INO 11 -+ -+#define AUFS_WH_PFX ".wh." -+#define AUFS_WH_PFX_LEN ((int)sizeof(AUFS_WH_PFX) - 1) -+#define AUFS_WH_TMP_LEN 4 -+/* a limit for rmdir/rename a dir and copyup */ -+#define AUFS_MAX_NAMELEN (NAME_MAX \ -+ - AUFS_WH_PFX_LEN * 2 /* doubly whiteouted */\ -+ - 1 /* dot */\ -+ - AUFS_WH_TMP_LEN) /* hex */ -+#define AUFS_XINO_FNAME "." AUFS_NAME ".xino" -+#define AUFS_XINO_DEFPATH "/tmp/" AUFS_XINO_FNAME -+#define AUFS_XINO_DEF_SEC 30 /* seconds */ -+#define AUFS_XINO_DEF_TRUNC 45 /* percentage */ -+#define AUFS_DIRWH_DEF 3 -+#define AUFS_RDCACHE_DEF 10 /* seconds */ -+#define AUFS_RDCACHE_MAX 3600 /* seconds */ -+#define AUFS_RDBLK_DEF 512 /* bytes */ -+#define AUFS_RDHASH_DEF 32 -+#define AUFS_WKQ_NAME AUFS_NAME "d" -+#define AUFS_MFS_DEF_SEC 30 /* seconds */ -+#define AUFS_MFS_MAX_SEC 3600 /* seconds */ -+#define AUFS_FHSM_CACHE_DEF_SEC 30 /* seconds */ -+#define AUFS_PLINK_WARN 50 /* number of plinks in a single bucket */ -+ -+/* pseudo-link maintenace under /proc */ -+#define AUFS_PLINK_MAINT_NAME "plink_maint" -+#define AUFS_PLINK_MAINT_DIR "fs/" AUFS_NAME -+#define AUFS_PLINK_MAINT_PATH AUFS_PLINK_MAINT_DIR "/" AUFS_PLINK_MAINT_NAME -+ -+/* dirren, renamed dir */ -+#define AUFS_DR_INFO_PFX AUFS_WH_PFX ".dr." -+#define AUFS_DR_BRHINO_NAME AUFS_WH_PFX "hino" -+/* whiteouted doubly */ -+#define AUFS_WH_DR_INFO_PFX AUFS_WH_PFX AUFS_DR_INFO_PFX -+#define AUFS_WH_DR_BRHINO AUFS_WH_PFX AUFS_DR_BRHINO_NAME -+ -+#define AUFS_DIROPQ_NAME AUFS_WH_PFX ".opq" /* whiteouted doubly */ -+#define AUFS_WH_DIROPQ AUFS_WH_PFX AUFS_DIROPQ_NAME -+ -+#define AUFS_BASE_NAME AUFS_WH_PFX AUFS_NAME -+#define AUFS_PLINKDIR_NAME AUFS_WH_PFX "plnk" -+#define AUFS_ORPHDIR_NAME AUFS_WH_PFX "orph" -+ -+/* doubly whiteouted */ -+#define AUFS_WH_BASE AUFS_WH_PFX AUFS_BASE_NAME -+#define AUFS_WH_PLINKDIR AUFS_WH_PFX AUFS_PLINKDIR_NAME -+#define AUFS_WH_ORPHDIR AUFS_WH_PFX AUFS_ORPHDIR_NAME -+ -+/* branch permissions and attributes */ -+#define AUFS_BRPERM_RW "rw" -+#define AUFS_BRPERM_RO "ro" -+#define AUFS_BRPERM_RR "rr" -+#define AUFS_BRATTR_COO_REG "coo_reg" -+#define AUFS_BRATTR_COO_ALL "coo_all" -+#define AUFS_BRATTR_FHSM "fhsm" -+#define AUFS_BRATTR_UNPIN "unpin" -+#define AUFS_BRATTR_ICEX "icex" -+#define AUFS_BRATTR_ICEX_SEC "icexsec" -+#define AUFS_BRATTR_ICEX_SYS "icexsys" -+#define AUFS_BRATTR_ICEX_TR "icextr" -+#define AUFS_BRATTR_ICEX_USR "icexusr" -+#define AUFS_BRATTR_ICEX_OTH "icexoth" -+#define AUFS_BRRATTR_WH "wh" -+#define AUFS_BRWATTR_NLWH "nolwh" -+#define AUFS_BRWATTR_MOO "moo" -+ -+#define AuBrPerm_RW 1 /* writable, hardlinkable wh */ -+#define AuBrPerm_RO (1 << 1) /* readonly */ -+#define AuBrPerm_RR (1 << 2) /* natively readonly */ -+#define AuBrPerm_Mask (AuBrPerm_RW | AuBrPerm_RO | AuBrPerm_RR) -+ -+#define AuBrAttr_COO_REG (1 << 3) /* copy-up on open */ -+#define AuBrAttr_COO_ALL (1 << 4) -+#define AuBrAttr_COO_Mask (AuBrAttr_COO_REG | AuBrAttr_COO_ALL) -+ -+#define AuBrAttr_FHSM (1 << 5) /* file-based hsm */ -+#define AuBrAttr_UNPIN (1 << 6) /* rename-able top dir of -+ branch. meaningless since -+ linux-3.18-rc1 */ -+ -+/* ignore error in copying XATTR */ -+#define AuBrAttr_ICEX_SEC (1 << 7) -+#define AuBrAttr_ICEX_SYS (1 << 8) -+#define AuBrAttr_ICEX_TR (1 << 9) -+#define AuBrAttr_ICEX_USR (1 << 10) -+#define AuBrAttr_ICEX_OTH (1 << 11) -+#define AuBrAttr_ICEX (AuBrAttr_ICEX_SEC \ -+ | AuBrAttr_ICEX_SYS \ -+ | AuBrAttr_ICEX_TR \ -+ | AuBrAttr_ICEX_USR \ -+ | AuBrAttr_ICEX_OTH) -+ -+#define AuBrRAttr_WH (1 << 12) /* whiteout-able */ -+#define AuBrRAttr_Mask AuBrRAttr_WH -+ -+#define AuBrWAttr_NoLinkWH (1 << 13) /* un-hardlinkable whiteouts */ -+#define AuBrWAttr_MOO (1 << 14) /* move-up on open */ -+#define AuBrWAttr_Mask (AuBrWAttr_NoLinkWH | AuBrWAttr_MOO) -+ -+#define AuBrAttr_CMOO_Mask (AuBrAttr_COO_Mask | AuBrWAttr_MOO) -+ -+/* #warning test userspace */ -+#ifdef __KERNEL__ -+#ifndef CONFIG_AUFS_FHSM -+#undef AuBrAttr_FHSM -+#define AuBrAttr_FHSM 0 -+#endif -+#ifndef CONFIG_AUFS_XATTR -+#undef AuBrAttr_ICEX -+#define AuBrAttr_ICEX 0 -+#undef AuBrAttr_ICEX_SEC -+#define AuBrAttr_ICEX_SEC 0 -+#undef AuBrAttr_ICEX_SYS -+#define AuBrAttr_ICEX_SYS 0 -+#undef AuBrAttr_ICEX_TR -+#define AuBrAttr_ICEX_TR 0 -+#undef AuBrAttr_ICEX_USR -+#define AuBrAttr_ICEX_USR 0 -+#undef AuBrAttr_ICEX_OTH -+#define AuBrAttr_ICEX_OTH 0 -+#endif -+#endif -+ -+/* the longest combination */ -+/* AUFS_BRATTR_ICEX and AUFS_BRATTR_ICEX_TR don't affect here */ -+#define AuBrPermStrSz sizeof(AUFS_BRPERM_RW \ -+ "+" AUFS_BRATTR_COO_REG \ -+ "+" AUFS_BRATTR_FHSM \ -+ "+" AUFS_BRATTR_UNPIN \ -+ "+" AUFS_BRATTR_ICEX_SEC \ -+ "+" AUFS_BRATTR_ICEX_SYS \ -+ "+" AUFS_BRATTR_ICEX_USR \ -+ "+" AUFS_BRATTR_ICEX_OTH \ -+ "+" AUFS_BRWATTR_NLWH) -+ -+typedef struct { -+ char a[AuBrPermStrSz]; -+} au_br_perm_str_t; -+ -+static inline int au_br_writable(int brperm) -+{ -+ return brperm & AuBrPerm_RW; -+} -+ -+static inline int au_br_whable(int brperm) -+{ -+ return brperm & (AuBrPerm_RW | AuBrRAttr_WH); -+} -+ -+static inline int au_br_wh_linkable(int brperm) -+{ -+ return !(brperm & AuBrWAttr_NoLinkWH); -+} -+ -+static inline int au_br_cmoo(int brperm) -+{ -+ return brperm & AuBrAttr_CMOO_Mask; -+} -+ -+static inline int au_br_fhsm(int brperm) -+{ -+ return brperm & AuBrAttr_FHSM; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* ioctl */ -+enum { -+ /* readdir in userspace */ -+ AuCtl_RDU, -+ AuCtl_RDU_INO, -+ -+ AuCtl_WBR_FD, /* pathconf wrapper */ -+ AuCtl_IBUSY, /* busy inode */ -+ AuCtl_MVDOWN, /* move-down */ -+ AuCtl_BR, /* info about branches */ -+ AuCtl_FHSM_FD /* connection for fhsm */ -+}; -+ -+/* borrowed from linux/include/linux/kernel.h */ -+#ifndef ALIGN -+#ifdef _GNU_SOURCE -+#define ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a)-1) -+#else -+#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) -+#endif -+#define __ALIGN_MASK(x, mask) (((x)+(mask))&~(mask)) -+#endif -+ -+/* borrowed from linux/include/linux/compiler-gcc3.h */ -+#ifndef __aligned -+#define __aligned(x) __attribute__((aligned(x))) -+#endif -+ -+#ifdef __KERNEL__ -+#ifndef __packed -+#define __packed __attribute__((packed)) -+#endif -+#endif -+ -+struct au_rdu_cookie { -+ uint64_t h_pos; -+ int16_t bindex; -+ uint8_t flags; -+ uint8_t pad; -+ uint32_t generation; -+} __aligned(8); -+ -+struct au_rdu_ent { -+ uint64_t ino; -+ int16_t bindex; -+ uint8_t type; -+ uint8_t nlen; -+ uint8_t wh; -+ char name[]; -+} __aligned(8); -+ -+static inline int au_rdu_len(int nlen) -+{ -+ /* include the terminating NULL */ -+ return ALIGN(sizeof(struct au_rdu_ent) + nlen + 1, -+ sizeof(uint64_t)); -+} -+ -+union au_rdu_ent_ul { -+ struct au_rdu_ent __user *e; -+ uint64_t ul; -+}; -+ -+enum { -+ AufsCtlRduV_SZ, -+ AufsCtlRduV_End -+}; -+ -+struct aufs_rdu { -+ /* input */ -+ union { -+ uint64_t sz; /* AuCtl_RDU */ -+ uint64_t nent; /* AuCtl_RDU_INO */ -+ }; -+ union au_rdu_ent_ul ent; -+ uint16_t verify[AufsCtlRduV_End]; -+ -+ /* input/output */ -+ uint32_t blk; -+ -+ /* output */ -+ union au_rdu_ent_ul tail; -+ /* number of entries which were added in a single call */ -+ uint64_t rent; -+ uint8_t full; -+ uint8_t shwh; -+ -+ struct au_rdu_cookie cookie; -+} __aligned(8); -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* dirren. the branch is identified by the filename who contains this */ -+struct au_drinfo { -+ uint64_t ino; -+ union { -+ uint8_t oldnamelen; -+ uint64_t _padding; -+ }; -+ uint8_t oldname[]; -+} __aligned(8); -+ -+struct au_drinfo_fdata { -+ uint32_t magic; -+ struct au_drinfo drinfo; -+} __aligned(8); -+ -+#define AUFS_DRINFO_MAGIC_V1 ('a' << 24 | 'd' << 16 | 'r' << 8 | 0x01) -+/* future */ -+#define AUFS_DRINFO_MAGIC_V2 ('a' << 24 | 'd' << 16 | 'r' << 8 | 0x02) -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct aufs_wbr_fd { -+ uint32_t oflags; -+ int16_t brid; -+} __aligned(8); -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct aufs_ibusy { -+ uint64_t ino, h_ino; -+ int16_t bindex; -+} __aligned(8); -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* error code for move-down */ -+/* the actual message strings are implemented in aufs-util.git */ -+enum { -+ EAU_MVDOWN_OPAQUE = 1, -+ EAU_MVDOWN_WHITEOUT, -+ EAU_MVDOWN_UPPER, -+ EAU_MVDOWN_BOTTOM, -+ EAU_MVDOWN_NOUPPER, -+ EAU_MVDOWN_NOLOWERBR, -+ EAU_Last -+}; -+ -+/* flags for move-down */ -+#define AUFS_MVDOWN_DMSG 1 -+#define AUFS_MVDOWN_OWLOWER (1 << 1) /* overwrite lower */ -+#define AUFS_MVDOWN_KUPPER (1 << 2) /* keep upper */ -+#define AUFS_MVDOWN_ROLOWER (1 << 3) /* do even if lower is RO */ -+#define AUFS_MVDOWN_ROLOWER_R (1 << 4) /* did on lower RO */ -+#define AUFS_MVDOWN_ROUPPER (1 << 5) /* do even if upper is RO */ -+#define AUFS_MVDOWN_ROUPPER_R (1 << 6) /* did on upper RO */ -+#define AUFS_MVDOWN_BRID_UPPER (1 << 7) /* upper brid */ -+#define AUFS_MVDOWN_BRID_LOWER (1 << 8) /* lower brid */ -+#define AUFS_MVDOWN_FHSM_LOWER (1 << 9) /* find fhsm attr for lower */ -+#define AUFS_MVDOWN_STFS (1 << 10) /* req. stfs */ -+#define AUFS_MVDOWN_STFS_FAILED (1 << 11) /* output: stfs is unusable */ -+#define AUFS_MVDOWN_BOTTOM (1 << 12) /* output: no more lowers */ -+ -+/* index for move-down */ -+enum { -+ AUFS_MVDOWN_UPPER, -+ AUFS_MVDOWN_LOWER, -+ AUFS_MVDOWN_NARRAY -+}; -+ -+/* -+ * additional info of move-down -+ * number of free blocks and inodes. -+ * subset of struct kstatfs, but smaller and always 64bit. -+ */ -+struct aufs_stfs { -+ uint64_t f_blocks; -+ uint64_t f_bavail; -+ uint64_t f_files; -+ uint64_t f_ffree; -+}; -+ -+struct aufs_stbr { -+ int16_t brid; /* optional input */ -+ int16_t bindex; /* output */ -+ struct aufs_stfs stfs; /* output when AUFS_MVDOWN_STFS set */ -+} __aligned(8); -+ -+struct aufs_mvdown { -+ uint32_t flags; /* input/output */ -+ struct aufs_stbr stbr[AUFS_MVDOWN_NARRAY]; /* input/output */ -+ int8_t au_errno; /* output */ -+} __aligned(8); -+ -+/* ---------------------------------------------------------------------- */ -+ -+union aufs_brinfo { -+ /* PATH_MAX may differ between kernel-space and user-space */ -+ char _spacer[4096]; -+ struct { -+ int16_t id; -+ int perm; -+ char path[]; -+ }; -+} __aligned(8); -+ -+/* ---------------------------------------------------------------------- */ -+ -+#define AuCtlType 'A' -+#define AUFS_CTL_RDU _IOWR(AuCtlType, AuCtl_RDU, struct aufs_rdu) -+#define AUFS_CTL_RDU_INO _IOWR(AuCtlType, AuCtl_RDU_INO, struct aufs_rdu) -+#define AUFS_CTL_WBR_FD _IOW(AuCtlType, AuCtl_WBR_FD, \ -+ struct aufs_wbr_fd) -+#define AUFS_CTL_IBUSY _IOWR(AuCtlType, AuCtl_IBUSY, struct aufs_ibusy) -+#define AUFS_CTL_MVDOWN _IOWR(AuCtlType, AuCtl_MVDOWN, \ -+ struct aufs_mvdown) -+#define AUFS_CTL_BRINFO _IOW(AuCtlType, AuCtl_BR, union aufs_brinfo) -+#define AUFS_CTL_FHSM_FD _IOW(AuCtlType, AuCtl_FHSM_FD, int) -+ -+#endif /* __AUFS_TYPE_H__ */ -diff -Nurp linux-5.10-rc6/kernel/fork.c linux-5.10-rc6.aufs/kernel/fork.c ---- linux-5.10-rc6/kernel/fork.c 2020-12-02 21:18:31.051424893 +0200 -+++ linux-5.10-rc6.aufs/kernel/fork.c 2020-12-02 21:19:51.887037013 +0200 -@@ -554,7 +554,7 @@ static __latent_entropy int dup_mmap(str - struct inode *inode = file_inode(file); - struct address_space *mapping = file->f_mapping; - -- get_file(file); -+ vma_get_file(tmp); - if (tmp->vm_flags & VM_DENYWRITE) - put_write_access(inode); - i_mmap_lock_write(mapping); -diff -Nurp linux-5.10-rc6/kernel/locking/lockdep.c linux-5.10-rc6.aufs/kernel/locking/lockdep.c ---- linux-5.10-rc6/kernel/locking/lockdep.c 2020-12-02 21:18:31.053424982 +0200 -+++ linux-5.10-rc6.aufs/kernel/locking/lockdep.c 2020-12-02 21:19:51.887037013 +0200 -@@ -188,7 +188,7 @@ static - struct lock_class lock_classes[MAX_LOCKDEP_KEYS]; - static DECLARE_BITMAP(lock_classes_in_use, MAX_LOCKDEP_KEYS); - --static inline struct lock_class *hlock_class(struct held_lock *hlock) -+inline struct lock_class *lockdep_hlock_class(struct held_lock *hlock) - { - unsigned int class_idx = hlock->class_idx; - -@@ -209,6 +209,8 @@ static inline struct lock_class *hlock_c - */ - return lock_classes + class_idx; - } -+EXPORT_SYMBOL_GPL(lockdep_hlock_class); -+#define hlock_class(hlock) lockdep_hlock_class(hlock) - - #ifdef CONFIG_LOCK_STAT - static DEFINE_PER_CPU(struct lock_class_stats[MAX_LOCKDEP_KEYS], cpu_lock_stats); -diff -Nurp linux-5.10-rc6/kernel/task_work.c linux-5.10-rc6.aufs/kernel/task_work.c ---- linux-5.10-rc6/kernel/task_work.c 2020-12-02 21:18:31.060425295 +0200 -+++ linux-5.10-rc6.aufs/kernel/task_work.c 2020-12-02 21:19:51.887037013 +0200 -@@ -154,3 +154,4 @@ void task_work_run(void) - } while (work); - } - } -+EXPORT_SYMBOL_GPL(task_work_run); -diff -Nurp linux-5.10-rc6/MAINTAINERS linux-5.10-rc6.aufs/MAINTAINERS ---- linux-5.10-rc6/MAINTAINERS 2020-12-02 21:18:30.241388699 +0200 -+++ linux-5.10-rc6.aufs/MAINTAINERS 2020-12-02 21:19:51.879036653 +0200 -@@ -3001,6 +3001,19 @@ F: include/linux/audit.h - F: include/uapi/linux/audit.h - F: kernel/audit* - -+AUFS (advanced multi layered unification filesystem) FILESYSTEM -+M: "J. R. Okajima" -+L: aufs-users@lists.sourceforge.net (members only) -+L: linux-unionfs@vger.kernel.org -+W: http://aufs.sourceforge.net -+T: git://github.com/sfjro/aufs4-linux.git -+S: Supported -+F: Documentation/filesystems/aufs/ -+F: Documentation/ABI/testing/debugfs-aufs -+F: Documentation/ABI/testing/sysfs-aufs -+F: fs/aufs/ -+F: include/uapi/linux/aufs_type.h -+ - AUXILIARY DISPLAY DRIVERS - M: Miguel Ojeda Sandonis - S: Maintained -diff -Nurp linux-5.10-rc6/mm/filemap.c linux-5.10-rc6.aufs/mm/filemap.c ---- linux-5.10-rc6/mm/filemap.c 2020-12-02 21:18:31.071425787 +0200 -+++ linux-5.10-rc6.aufs/mm/filemap.c 2020-12-02 21:19:51.887037013 +0200 -@@ -2909,7 +2909,7 @@ vm_fault_t filemap_page_mkwrite(struct v - vm_fault_t ret = VM_FAULT_LOCKED; - - sb_start_pagefault(inode->i_sb); -- file_update_time(vmf->vma->vm_file); -+ vma_file_update_time(vmf->vma); - lock_page(page); - if (page->mapping != inode->i_mapping) { - unlock_page(page); -diff -Nurp linux-5.10-rc6/mm/Makefile linux-5.10-rc6.aufs/mm/Makefile ---- linux-5.10-rc6/mm/Makefile 2020-12-02 21:18:31.070425741 +0200 -+++ linux-5.10-rc6.aufs/mm/Makefile 2020-12-02 21:19:51.887037013 +0200 -@@ -52,7 +52,7 @@ obj-y := filemap.o mempool.o oom_kill. - mm_init.o percpu.o slab_common.o \ - compaction.o vmacache.o \ - interval_tree.o list_lru.o workingset.o \ -- debug.o gup.o $(mmu-y) -+ prfile.o debug.o gup.o $(mmu-y) - - # Give 'page_alloc' its own module-parameter namespace - page-alloc-y := page_alloc.o -diff -Nurp linux-5.10-rc6/mm/mmap.c linux-5.10-rc6.aufs/mm/mmap.c ---- linux-5.10-rc6/mm/mmap.c 2020-12-02 21:18:31.074425920 +0200 -+++ linux-5.10-rc6.aufs/mm/mmap.c 2020-12-02 21:19:51.887037013 +0200 -@@ -179,7 +179,7 @@ static struct vm_area_struct *remove_vma - if (vma->vm_ops && vma->vm_ops->close) - vma->vm_ops->close(vma); - if (vma->vm_file) -- fput(vma->vm_file); -+ vma_fput(vma); - mpol_put(vma_policy(vma)); - vm_area_free(vma); - return next; -@@ -951,7 +951,7 @@ again: - if (remove_next) { - if (file) { - uprobe_munmap(next, next->vm_start, next->vm_end); -- fput(file); -+ vma_fput(vma); - } - if (next->anon_vma) - anon_vma_merge(vma, next); -@@ -1899,8 +1899,8 @@ out: - return addr; - - unmap_and_free_vma: -+ vma_fput(vma); - vma->vm_file = NULL; -- fput(file); - - /* Undo any partial mapping done by a device driver. */ - unmap_region(mm, vma, prev, vma->vm_start, vma->vm_end); -@@ -2759,7 +2759,7 @@ int __split_vma(struct mm_struct *mm, st - goto out_free_mpol; - - if (new->vm_file) -- get_file(new->vm_file); -+ vma_get_file(new); - - if (new->vm_ops && new->vm_ops->open) - new->vm_ops->open(new); -@@ -2778,7 +2778,7 @@ int __split_vma(struct mm_struct *mm, st - if (new->vm_ops && new->vm_ops->close) - new->vm_ops->close(new); - if (new->vm_file) -- fput(new->vm_file); -+ vma_fput(new); - unlink_anon_vmas(new); - out_free_mpol: - mpol_put(vma_policy(new)); -@@ -2971,7 +2971,7 @@ SYSCALL_DEFINE5(remap_file_pages, unsign - struct vm_area_struct *vma; - unsigned long populate = 0; - unsigned long ret = -EINVAL; -- struct file *file; -+ struct file *file, *prfile; - - pr_warn_once("%s (%d) uses deprecated remap_file_pages() syscall. See Documentation/vm/remap_file_pages.rst.\n", - current->comm, current->pid); -@@ -3046,10 +3046,27 @@ SYSCALL_DEFINE5(remap_file_pages, unsign - } - } - -- file = get_file(vma->vm_file); -+ vma_get_file(vma); -+ file = vma->vm_file; -+ prfile = vma->vm_prfile; - ret = do_mmap(vma->vm_file, start, size, - prot, flags, pgoff, &populate, NULL); -+ if (!IS_ERR_VALUE(ret) && file && prfile) { -+ struct vm_area_struct *new_vma; -+ -+ new_vma = find_vma(mm, ret); -+ if (!new_vma->vm_prfile) -+ new_vma->vm_prfile = prfile; -+ if (new_vma != vma) -+ get_file(prfile); -+ } -+ /* -+ * two fput()s instead of vma_fput(vma), -+ * coz vma may not be available anymore. -+ */ - fput(file); -+ if (prfile) -+ fput(prfile); - out: - mmap_write_unlock(mm); - if (populate) -@@ -3336,7 +3353,7 @@ struct vm_area_struct *copy_vma(struct v - if (anon_vma_clone(new_vma, vma)) - goto out_free_mempol; - if (new_vma->vm_file) -- get_file(new_vma->vm_file); -+ vma_get_file(new_vma); - if (new_vma->vm_ops && new_vma->vm_ops->open) - new_vma->vm_ops->open(new_vma); - vma_link(mm, new_vma, prev, rb_link, rb_parent); -diff -Nurp linux-5.10-rc6/mm/nommu.c linux-5.10-rc6.aufs/mm/nommu.c ---- linux-5.10-rc6/mm/nommu.c 2020-12-02 21:18:31.074425920 +0200 -+++ linux-5.10-rc6.aufs/mm/nommu.c 2020-12-02 21:19:51.888037058 +0200 -@@ -533,7 +533,7 @@ static void __put_nommu_region(struct vm - up_write(&nommu_region_sem); - - if (region->vm_file) -- fput(region->vm_file); -+ vmr_fput(region); - - /* IO memory and memory shared directly out of the pagecache - * from ramfs/tmpfs mustn't be released here */ -@@ -665,7 +665,7 @@ static void delete_vma(struct mm_struct - if (vma->vm_ops && vma->vm_ops->close) - vma->vm_ops->close(vma); - if (vma->vm_file) -- fput(vma->vm_file); -+ vma_fput(vma); - put_nommu_region(vma->vm_region); - vm_area_free(vma); - } -@@ -1188,7 +1188,7 @@ unsigned long do_mmap(struct file *file, - goto error_just_free; - } - } -- fput(region->vm_file); -+ vmr_fput(region); - kmem_cache_free(vm_region_jar, region); - region = pregion; - result = start; -@@ -1265,10 +1265,10 @@ error_just_free: - up_write(&nommu_region_sem); - error: - if (region->vm_file) -- fput(region->vm_file); -+ vmr_fput(region); - kmem_cache_free(vm_region_jar, region); - if (vma->vm_file) -- fput(vma->vm_file); -+ vma_fput(vma); - vm_area_free(vma); - return ret; - -diff -Nurp linux-5.10-rc6/mm/prfile.c linux-5.10-rc6.aufs/mm/prfile.c ---- linux-5.10-rc6/mm/prfile.c 1970-01-01 02:00:00.000000000 +0200 -+++ linux-5.10-rc6.aufs/mm/prfile.c 2020-12-02 21:19:51.888037058 +0200 -@@ -0,0 +1,86 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Mainly for aufs which mmap(2) different file and wants to print different -+ * path in /proc/PID/maps. -+ * Call these functions via macros defined in linux/mm.h. -+ * -+ * See Documentation/filesystems/aufs/design/06mmap.txt -+ * -+ * Copyright (c) 2014-2020 Junjro R. Okajima -+ * Copyright (c) 2014 Ian Campbell -+ */ -+ -+#include -+#include -+#include -+ -+/* #define PRFILE_TRACE */ -+static inline void prfile_trace(struct file *f, struct file *pr, -+ const char func[], int line, const char func2[]) -+{ -+#ifdef PRFILE_TRACE -+ if (pr) -+ pr_info("%s:%d: %s, %pD2\n", func, line, func2, f); -+#endif -+} -+ -+void vma_do_file_update_time(struct vm_area_struct *vma, const char func[], -+ int line) -+{ -+ struct file *f = vma->vm_file, *pr = vma->vm_prfile; -+ -+ prfile_trace(f, pr, func, line, __func__); -+ file_update_time(f); -+ if (f && pr) -+ file_update_time(pr); -+} -+ -+struct file *vma_do_pr_or_file(struct vm_area_struct *vma, const char func[], -+ int line) -+{ -+ struct file *f = vma->vm_file, *pr = vma->vm_prfile; -+ -+ prfile_trace(f, pr, func, line, __func__); -+ return (f && pr) ? pr : f; -+} -+ -+void vma_do_get_file(struct vm_area_struct *vma, const char func[], int line) -+{ -+ struct file *f = vma->vm_file, *pr = vma->vm_prfile; -+ -+ prfile_trace(f, pr, func, line, __func__); -+ get_file(f); -+ if (f && pr) -+ get_file(pr); -+} -+ -+void vma_do_fput(struct vm_area_struct *vma, const char func[], int line) -+{ -+ struct file *f = vma->vm_file, *pr = vma->vm_prfile; -+ -+ prfile_trace(f, pr, func, line, __func__); -+ fput(f); -+ if (f && pr) -+ fput(pr); -+} -+ -+#ifndef CONFIG_MMU -+struct file *vmr_do_pr_or_file(struct vm_region *region, const char func[], -+ int line) -+{ -+ struct file *f = region->vm_file, *pr = region->vm_prfile; -+ -+ prfile_trace(f, pr, func, line, __func__); -+ return (f && pr) ? pr : f; -+} -+ -+void vmr_do_fput(struct vm_region *region, const char func[], int line) -+{ -+ struct file *f = region->vm_file, *pr = region->vm_prfile; -+ -+ prfile_trace(f, pr, func, line, __func__); -+ fput(f); -+ if (f && pr) -+ fput(pr); -+} -+#endif /* !CONFIG_MMU */ -diff -Nurp linux-5.10-rc6/security/security.c linux-5.10-rc6.aufs/security/security.c ---- linux-5.10-rc6/security/security.c 2020-12-02 21:18:31.125428199 +0200 -+++ linux-5.10-rc6.aufs/security/security.c 2020-12-02 21:19:51.888037058 +0200 -@@ -1093,6 +1093,7 @@ int security_path_rmdir(const struct pat - return 0; - return call_int_hook(path_rmdir, 0, dir, dentry); - } -+EXPORT_SYMBOL_GPL(security_path_rmdir); - - int security_path_unlink(const struct path *dir, struct dentry *dentry) - { -@@ -1109,6 +1110,7 @@ int security_path_symlink(const struct p - return 0; - return call_int_hook(path_symlink, 0, dir, dentry, old_name); - } -+EXPORT_SYMBOL_GPL(security_path_symlink); - - int security_path_link(struct dentry *old_dentry, const struct path *new_dir, - struct dentry *new_dentry) -@@ -1117,6 +1119,7 @@ int security_path_link(struct dentry *ol - return 0; - return call_int_hook(path_link, 0, old_dentry, new_dir, new_dentry); - } -+EXPORT_SYMBOL_GPL(security_path_link); - - int security_path_rename(const struct path *old_dir, struct dentry *old_dentry, - const struct path *new_dir, struct dentry *new_dentry, -@@ -1144,6 +1147,7 @@ int security_path_truncate(const struct - return 0; - return call_int_hook(path_truncate, 0, path); - } -+EXPORT_SYMBOL_GPL(security_path_truncate); - - int security_path_chmod(const struct path *path, umode_t mode) - { -@@ -1151,6 +1155,7 @@ int security_path_chmod(const struct pat - return 0; - return call_int_hook(path_chmod, 0, path, mode); - } -+EXPORT_SYMBOL_GPL(security_path_chmod); - - int security_path_chown(const struct path *path, kuid_t uid, kgid_t gid) - { -@@ -1158,6 +1163,7 @@ int security_path_chown(const struct pat - return 0; - return call_int_hook(path_chown, 0, path, uid, gid); - } -+EXPORT_SYMBOL_GPL(security_path_chown); - - int security_path_chroot(const struct path *path) - { -@@ -1258,6 +1264,7 @@ int security_inode_permission(struct ino - return 0; - return call_int_hook(inode_permission, 0, inode, mask); - } -+EXPORT_SYMBOL_GPL(security_inode_permission); - - int security_inode_setattr(struct dentry *dentry, struct iattr *attr) - { -@@ -1450,6 +1457,7 @@ int security_file_permission(struct file - - return fsnotify_perm(file, mask); - } -+EXPORT_SYMBOL_GPL(security_file_permission); - - int security_file_alloc(struct file *file) - { diff --git a/kernel/kernel/pspec.xml b/kernel/kernel/pspec.xml index 76376fe7..b2c95bec 100644 --- a/kernel/kernel/pspec.xml +++ b/kernel/kernel/pspec.xml @@ -33,12 +33,13 @@ - patches/linux/patch-5.10.15.xz + patches/linux/patch-5.10.19.xz patches/mageia/fs-aufs5.10.patch patches/mageia/fs-aufs5.10-symbol-exports.patch patches/mageia/fs-aufs5.10-tristate.patch patches/mageia/CVE-2019-12379.patch + patches/mageia/CVE-2020-16119-DCCP-CCID-structure-use-after-free.patch patches/mageia/3rd-3rdparty-tree.patch patches/mageia/3rd-3rdparty-merge.patch @@ -141,6 +142,17 @@ + + 2021-03-01 + 5.10.19 + Version bump + security + + systemRestart + + Mustafa Cinasal + muscnsl@gmail.com + 2021-02-11 5.10.15

    ^)!|TjuJH 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%0AbY{6$Gmku{&K7#Gvh% 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%0DAF9HI4M#8kR%=?rsFOBV^l=8A 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ˊ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

  • mn4kk0)6uN#0Y$6EIPgCR%N$z53A`8 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%0D%%%FD~ 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%0A=T_{C1&b9)f8ty~tQjxUB<}$VAp0 zSiO@!0Ai@3Pa_`c#^cc0Vu~;2Vw_v%CoeBW?&`eA9TZ;%ifK)(6i?O(+VE)yc$}pO zT#PHl3;Fr^@n-Zqy6URnnWWCF4baR3K^?GGc^jNWf(cx{kedetnDuCNp9!H(8P{6c znfzi7CWc07Lpxl@E|L!c8o#mZB{&WVG9~3XoY^J$I7b{bP2LS0_*e4+Wm0}~chg&n zHcienM8INPI!H0*=rGmBixKiVk$ySYpPi!M`?)zJex!+S6`xfIs=w9aFD68swM7y1 zm7n`^Wel%JOrG(bAe(m?t4M;d_CnuB3QIkRN@rd+csJ$!FUD!Qy_hRUC{1;FuRuQO z&ukp}WSDY*4He#t)!1yIpV78MRY`K%8{+3>skk3}kH;-)coY3@;#41}^(AE-N4vf; z*acm;k-%zsRoo1_q-bqKX&^k^G4fxeH#t%zep#`;0sw;IaP&Ptq!fCye{W32(%K4} z!kza-uK}Frq!dQ4**arf0v1TzV7s5rXJ=LM4A;W5<}hbBXy)wamTt;3ylYWDg%fQEu&p1ShUyTg9TL zL_Y=AKe^sAf?Ih78LSmy(=y=>%p!J7lReIJ)iU6+T5VKR+elNhyU`pwJ(dc)`%o07b^5S&%e6-@|(*vid1^TcqX-mmB zFt}LG>?^QFBYpGaEN(Qo*;93Y>pHq>hq|B=M&3AKN`KFNR|X49{47Jf5oO#!PnMfE zEaFv6L}pU`=rbeGZ?Y-FMdYVJz`ii^-?$f~bjfjPvCnL*RlQq?%p`_0AC)aLXhWdz)MCor!iL3Y+GE~(=_Iqn34fI2?}_N0pALH zWz32jAzZcJsm3yuRNMt+!61al4%g7D{@uz$ZOwi;8Kri|cNcA$npz)>I#22JwK`5d zX-%^WNL9{Ism0Pcg8;5% zSNs+Pw)&ala0js zy3mI%&^^`6Z@<2?cY)(So&IKROIi57?`Pt1t>+L$LpU{`XNx} zG0~Sm*HhI^!sSTw`8qt|XXfl`S5`Mk%V`y(RLDwk4Szqn(h}D$K3n+*@(|pN!ZDsl zX!tB+Y@nysOA_v68O+%3T74ws*%1xJ)kas7*2)J%?;Nm_)(`WiSvIyTq$POp`Qf++ z(!&8fm$<+*uO_6lyz`)VrjOwqoTx!b}sVF zW#`{if@TqT;@_^w`HqyEBdkni3-YDMGQOdg1y6UFH=9?8{ z&^N3G5pXr||Iy`aWw;>sy$ykaapC#1odhvv$|YqrdpU6;Jrjyg+IMatFj4V9CdV`N zmR1DwWU8JWt1@hiOA*s#y2x=#c&s1JW?cVWR~7x)%9XoprQc>`@IU9qky5-m&-t%V z%-rc-c;|Hit-Y8qchxO`Fh zVKE{9n>NFG*)^D!^X|{MoQX0XoL7)5hUL62+E5R=mX3e89A{N^eT!3exgqhS)JmQ( z#-H5gg1Z26!JB;d*WE?sO@g1bPt>1sL1exi{sYB1Rj<2f<}7*-YT7*W0(u+aSX?s8 zPPMlG?N`$)DrJ(PT-~nt&A4XjBAXTli%%6hRoknCY3!~u|j?Ef5Zu^-uH@GW-?v>f%nV3@0#1szO6 zz5_KjX7RCE88Sa@KF#F;sf)Lz=G`Ir^p3mLFb|XU+NGcwPKVC%9CwTtF^C% zD>kHc*7!U@>W?J#v?>nA`B8DVz4bkHSd(p?{~|-=VSOHdIx|En$OU)83yQyueU-jJ z8sHSwqt*=5iEgM~B3DLtg);P=` zSftc$-zTMLKgB)mOvR~@QVBxebi(V1qq!lP^;dba+y728U;b5iGRhcjxaN82-aEekL%rRwB{yaW z>0Z;>Zv>)Me;Z<4+Vfpf3K01PNx{y884c=;a_5L9UO@!f08#z70xow+zc`pQoW<|n zyw=nTnjvbAx>hoC%(!D!I$H;1{>|xv?`(EnYhkQaNUri}9u*_(V4*A!V z5B-il|M5Ru@spj)3lM%Q%(x*Be_7nH_vr()5n-k;$SrK=1A)I)05(RJXHEB(4Q`;J zk$HX_NGv-i;^sFYlHxD-%BWP+-UH>78+=fpfGGhAI~zu2M7jJ75ahQS+xRL+pF4cS z^xH=0#VFfY(Wgjo8fpYY+!G_NcMZ(=M6l@^$h_hrq}Kc--5~&4#_OXJsB(0 z!09R8VPrLw2C$hjDr)(cFuHmOgs9ZwH=yO}b13Lcn<>X6*jt;*J}E<5+%H|@vHvi9 z1t9DMNO;Tv!U=eV0aQA{(WDff+|c3*%2E_aa=GKprsYz_%d*xgt`9wbo9+6{UQ2-a zCcs3BrJ`JBeOU-t*kSJhAw?)Ie!ss=Epy67B>4(Mn+F^$;(sPhQ5N_#w8i5gXRYE% zMY0r*o@8``QseBz=xlCZq`;S5Zz#J$G+ovjDxlt>%~X=Eo$}fSR5??4||Y2u@RfYDuGu3IL>^u z)~w;of@6x?S;nX)Azf99hz~4L;ByfLK}|){%)Qoz;Cfcz#YZtC`1mQsP=iFu0W@?1 z(L56iURQfkWXQ}%l%7|yV?g+}z_Q%NA`4XuCtVjv_52OMYRd^_H;zNSekf%S(%b&V zKY3i%*ZJ+f>Ti$_58G%lC)-0$lo{b|rk&r^%^}xHgit~00(wv=umH|kv98cE)+LRi zpLthHs|RF}l4&e`{*7S)t|QUVK99A1W&-8A_iCO5F2r0hDh}4n@6DoqP);S$<9at) z2(3Jd!D18Xt;bOw45GL2@}SvP3kG3ce?z_k<>8D)Kza^_7BN{t-uZkNYXex?V}AVy zzxVmQ&C|7jyZFCuk;T(cW1L9 z%HVnvNxgSR_uC7-?^K$M(M9$_d_E>RS9Ku@5#@ANSWv-Cj?k(<#X^s?fEZzC;&Il@ zmvekmWCl9K|M@sJl<!0mO0rX$AI~^lsGVo)Zy8TO2=y`DaErKP zw$C?dWvg&-FpeT2Cp!J-dQ_8AUDmjV6l#giZ|Hth(C=rM3Zj>WMJn2^4U$Y*g~MiH zCxAJ(%u3ysii0UU-$kE8;-bIWbj+!8&Xv*W!P@wB88>~8SZoi)0mlpg|=84~vo1Ifu`rxM$5KDu* z7nlji?*SU=vTMzj*8R|FanG)&1}Z8dYNZsOAAwQMWdUer2(+&{|WXyOm=K)$ajH$dj?nqW z-TT%Q6>gq|{k}dx-rf%Cx8O^qPyz%-#YVQ;d?jxfT7SfZ5Pf1Z&^1UQTuSp;{}t+Gy+L&=EpR=3b+W6 zKDDdKiqayxj#$^OuI2&Fz@kn#D$X>MmnX2QqmbrQDVKSZJtGp+5mzLU59Sy656-w5 z#~C*1!eY?gaVwJq{*()PLT=wdRW>msz`IADB2+9J8GB(2O(H;G0SYyMX>oLQ?Y*P3 zCQghP^ydI{;p!W6NZ4-Y67qa~iqMBEJ z3+Qayy4&6Ek%W$YDPLH3FsL*;cEOEEeN<3Uh&!9}1q%^d14Jw$godyU%hETkb#mzZ zyqxcNfY8e#+~JAO~=zY?=H zkXdQoMW$?sJ3fJzE#%4Q${a;OUHKhEQ|{fvX56ymh^d&6eRJ&aF7iCUd*=<@b0&b| zju;+mkI&MYX4XH5k8}j8$ZaE&uba^6s#j;6lauxMo+45TMN-QpjRoZrao5%@);sik z#ua$mLAXqVT1>m}jAK9|r>-XE+Qt~pjPkOcf!-MN@(h#T$xVU5rr`q0&>`-2AOGm( zMa4}RADQCS9UYw%)DumT?^+~sG(Etzp_(EEEmW=7WFoKT3FwTh-R+)mmB|W%I@Fjc zip|VWrPyk(=zs-R+nV}h3&zq!I>#b_XlM^;;{cavUvCR;n89EkpCKlEYEu!;Z3I*9Pv zEX-w-v9~*1?hHYTP)&KkZjlOMuy{=L?7QRX>^vMo$c^|0Dt=c5Fa9|usjh`@9Et~w4MIRyk_3e? zSY90Y<;T=`LiH;-VcB}L1PRtp8}zJ$$mU8Kagh&t^b#NZdEbQv8m-eT>fVd<&^ znBWhd6&UOeeKw6^Hb+UItxOCONwun22-|1`f!Kt;65doJIf5>*P)B&Rlv>(trhG_> zyDzh#L(!z!91^CI=Ms&rE|)ZnL5Z$q7iQbVYQrn1o@xdDT5m5ZU_L%!#@l=K!I4qL z&Eo22s41g#b~K#)24fdJy14r!6UM5;0UQy>R><7p+S1ODptprLyOipUu z8yAq(v(Pa$qEZSid42lsZe9Hl%KNW>$o5uoBqc-tk&GF88fHFudM6S8rn%yZeVp z+2z%U0mJd|XEMWvJ+C%jN5OUrjiV8GmtF&0I=ihA5Dj7VQ!AoF;0j=9`_V6SHiH+* z_}0|tm0jrN2YU9}DHZ~%!%onB@1eZl_K#CKa@0T?!_z(sQnXBb;R9tL0k?yj1p;dV zx|$~M-qU;k;yR6!>u9`u!V!vUdvW^HdF zfY_kvSelgB)ao1JS3Fk`7@gG#ccQFGU1fY(m`}w}00F9(HRLx1U9|Wy&N^r^l$$MF zqnjGo->m-_AVKDE>*ImqTZA)aOR}i(OM2bE{4uJF%W}e%GPVtyx#=v&NF zEe`S8>{wC}o^MkR=bhWE#uLB(%A6zEVhcLoJX?%V&EQm;!`z};?7tk#ra6Ht7T!2_ z{98jOgr1yW){(CisE%&|FepO+@NQf=O;RC*hZ2KPhVGS&AA?)+WuyYrpz#A0Ilh^yMO*zWD=g(AylI& zw=XI9Hgw#UEE<*;qQc5lx(KvRK7Ln3KjoNU0Ce;bd3X{10}+e7yFiS z0#t_tqJ1y7eus=(8Jo$zH{}bf!az%9U%9hl-$txFU!k$8zSd^y%vMl&#H-BgTTH#W zGj}Udgl^~hiJ5Vq>Xxwd7ZM?3z5>Fy8=B6KeV-z9tD|4DEV(fIs!tC`<+~TASrkK7 zPa7%YL>zEtxt||EgKCgQbg7O8nkAMT&c+Q<LtVr&9xQxY+Y?iDIhcJTKl6 z{^LP;f*xzM;F|QHdCFmt{j}~^F%C%36dAplTX^Xh42J-GvH?O%0T{DbA{8$@-o9Oe zE8Pk-jhs9z^0|n(%E&vIHr7Fk!og&;y>v7IV7edm06Rd$zbWT``>k9G%5x&jFlChd z01L>)XUY!mUidjy62B@I=uW!Ld;fj{a)m5cYGYJ9|8`>p`ZV!`vVf3n3W@9f1idVR z+D8#qUZixIoiG2pK@N_EOlkxf^j*AGcS+4Vgg!7f6}G27m@uU;&*V}+F)FSi(Vmb_ zp!D#)R(h@6{0hKA4f6RO-y_4{ciEg3fYkrhhznisy45z>GAF?%H>>9$K-GF>7Xc7O z-2#(45|iQ!3I}SiL=iG;(5>QlC!1VNsO+{pi>#1(;37%~ke-ssE_5-S@mmwe|jXKLQNCEMt z53<%7l$1v6O><$Gzjg0w^IgeurfZngOKm>nw#p+gz`9PQ@@j%r5iK)bBJ z{${|}Mpu4_w^+xU7_LvMpkn_m2GwGsNM5j*GC{8yBA7*@N0gDp5N+I#mj)>X_R^6m zKj+4Pv20hpid}&5_Zydyq6j&^y|8y)UTl^~RxCe3ulQ^LIv!7XG!on%7m|;?jP}G( zCQfiO!569-=!c_Hf4Vs_rk<%*w#!t~C<~ctyb8xk zD&*#SPf(fVj(!Vd-u+WimL3jQnu>cXuqG1%J{HI3WE#3C=>xeO0;xW$Gcp_DS=$Qa zbqsoI1(0eO#-!Uj>t()$Bv8c4n<{y^rgvb?Kpz;+Ey$N?)U^n|Mmq8RrzWo7A7|w#+11Msg$gRxTL(r!)E$HTlS}fg> z=hw_v=1s9;uRv46*sxMJy-HRy-U0C8JvxQBc&)+B+~Fy*s8T9ngynrxW~ zlOODVnZu4wm9~%4T!(W(SeEM?%2MfUycETAG*dy)8Y?Kv&dhE(NEy-dX%sryTzZLbk$>~62IuOyCC@G|h}op1AiO;@Zk>0p^SF*txb^KcsT-RW)$RxGk})HN zUO1EEqPs6L_lwB9Ea9W`_XD3pftzw6ckT?jykJWyg%z#;A5eP|*lU|UmKo5@blhPk zH%;dE2A!Io^RyD3aHss5k{aBWUybx%MRc6j2Dgj_qYZ)DCzMzUv+i-Q$AirG#;Ybi z(7b$Kl2s{mvSqd^fC@#Z9z<0&ZuDb}V`|y=a?&W$p`BV_DFD(SFUjTxD&7<92o{bB z>F_&YQ269Xg4}9e6eEvER|qpV;zhYtgGoN%dbYh|C>aJJ^hNPS0X?=g{=9{v&i_XK ziQ9ZSj1Fu1(YB+?^t;im81cC<}B*EiC5; zj2Z)L^X9zjPP=Tya=i{Sp02a>yMN#? zG(86ifyOadJ-|X$qfwQ(?_{xEig6^E!_|s-HRF-t(~4 zr9W9A9k%)l3aW-S1&zDz@ff-bWR+tvysVSuS@tv3SQ{&z>5ym=u`z9WF$Rdxgvtc} zet_hsyVWPpMlAYzw4ELSuOUZoI^!_Kj`5=QyX$E%KL*$&DVE5BHu|E^YiA>Q4F@3*qQ1KN7kt6UnO?sukfWdhW^rGdgxt_ZFo9l|Trj-=Rqo`=3A^Z1h(I7*D7Jtj48zjR6bOkajTY)% zyh;N*;RRu`DrY53f}NI$Jrc7j8N0~aDp+hPoWAc}@A5OfiuEz?b9Qt*2NbEpe)Kp= z#{x$1hTq^f5`lR0-0NyF+swzhsSgYW5HEGRZx)4ZjlvM( z0%w*ZKu@I~ZPW5v&p#r9pf1-H!4axSRBRPlAuxSQzCE>1=&up_Iab~z++9|K$VLBX z--P=zdF843TCO zXY2H0_T?fOPW7`@5-JU2PnJfk{X$J;w9giD`}{+Z>Jb@ z6jd-k+`$7n9=d_ZP7GEU=hA)+RIi%u`FmNT%7h)?I?m1mvrkF)#Z{$#D#B0m=vFhn zYacM;i1myYcdd1zyoAUSN)``K$2H~pry2q7808`;)2H6k6{!fE5#dVtvHO|F+IFnv zM~RuUM?k@GZW@j+=-$hA!UZKXyx#i2fPrbSe4#|KWlMSn>~yt*g6(~1fTCi^9ia=gHd%)f`eMzbB}+&3;Nw&Cuq7a z#3Ps_1w*$gDh_?RHz5ws7`lL9y*G94`Ajwi0jvIWE*mTFvURvvM}w6#BkaGB*4|O? z1`6FRPA+u^*EdwzPS57V(9$v4AVxANr5~rz**||bsn4g{3dp##=3}0Nle0rvXHMHS z8^6%(Ubp-DeZa#D!&vdw-~uR5&oUfHS8Pa-zH!+R ztl^^l5LXW!Swa`Ui=dA%^WE${n!6gkQGN_}9(JozXWSa@>?(nAkFD1s*{OVilwB@q0YY86m$PBHM)kSq=*Z40^RQ&1Tz3f&4!H@RWMS*5=TnG9#v?~sVl8E8+O-s?K5`C0>-#Rt+D62ERcxUEeq1bP zR6#i0BBH?wJpp*WY!R4o-H$TGB7Rvd#(*qi>TNWrduPsRZBgG;QPj;VLy0f@jVG1Q z(BD=%rMdwpL*@+%IpX%URTTkW75+1lu5c|!C4T#?H>B=3N)3Y$&1m)JmEN6{#B!7i zKoa})o%=3weNIU6FOOBG(FnpMq|`;zVr@hW=}n;BCz^i$fbgrK{L32?4ZsK){u2^X zn#U;twLX$k&Kl}MI}d8yyyK!!Wq*KUQC@T~My5i3&S-Aw`AE2pPy7HpzNqz*hAbQVPf^jMkbEN=W>KUoEck(VwrTd$e9pDQ6QlRiSSrr~ zhs4YmJP`d-^AQad>6toizVnEl+~AvYeHUo*|InlWgj;p*{{VD6N-$-0KjHm~kKsb; z7v#nl?C)ECs=i%By`w~Qv26@fn#L}HQX*Q`cWtYiqoeIo}Py8t-JeyvgLu}b8q4%+{o&(hmNWx%^#{T)F>60 zCT{tGg-`)RC9^Z1OEN)Vf3%4wz$;uAw;+NDU9LXASVPJ$aniXoE!UUW=-t2h>V>`N z0gQt{C@`q3kC0tq;v$xCLkTwt8V#L|oY;5oYagCSi*`O&vY0m`tJS z^-V&5OA9NZIUYr+54)dKC{b|$%7=;$nSO)Yeu~mVxN}6K{PR83l3R8~}k5*L@VDE2e zE#Ay%Tr_?iv<{)a=W*ZX0Ba6%yFBV1; zE;C30!U&dv_>2b8Y`s~ao_RPpg3BTLke1ChWh0pOiw{A#{FpJ>q9+%o=Bo#D%6*N6 zXQq+CM^OWep{XP7*aCu7FRWf-nUEa>{t!y=Z@khe@!v^^7BqMm-^lvur0%EJYVmr3 z;FHkM`sm*5G#4>V5Q1vY5Jj}Aw}FLKq$-CSVXq07()SP&YVnwQ!*_%^DTAlI^1LCS z%6=g#Jm2d9Df~*ai82lUzEKUPKYqiC=tB=oa|r{x{@B#s3WR6pNab;b*jJo3qa!_| ztGWlLSr9VgSyj9mC2%@wIt5(klih|reLBfH%Aut@@HCd5@vJ*Q7Fs&oW$H2}=L z0KpFl8kNdK00%mhd=~aXb|D;eZTquAC~&4n0N(@p{EOHka0_sTZuz`0fIW)?!8yxw zHD~4%Fn@HNdxpKeR}nax%0iiTJ$m1;TX?mi&~pb}+Ek>Cu=4!4gcsolyAYP-Im^)> zO>q7f2lUngIeJr<3_1*>+Jqkps*}216UmV4=MXoPJcQrgrj1WJ#{BP;CK<||hjbkr z;)hMQGiW36R0ERf&4BnozGgT;Mh^H*P&mqaUC3X5T&X4+bIdzO`LAq9LqnQ(?Md?T zq^iC_xE=mdS=4~np0*=CyaqKd)PzqRp=r#lfLi85o_&82TrdigxdwlE=I=DsZ>&Xi ze-U*w3EfwL!m@`1^jn>Sd{42P=O+DZ8w$fipPL{l(!QpfsWb6^;gW|*vhBDYCYcyL zAfh0u16^-m+;d=y6Y9J(GlQ0#%9$eLq%6CVD*9(@s( zUC+-f7go(qv4JnJXZ`lH;nI;vi@$OvTc%-Pxyydjzr6lA8@;7_H}#2Iqga%_>%PNn z9p?J$ieC|^stfa?w;`>NOZ2)(xUII>_o)y&Ss72V=@HKW7+Dq|nB&CA;iWY_QP;fE zZVG0A!$3b0ZG8T3k4#e5dXMhZ@AR-@$}(Lt%P=KFr9n1`gR2a{DOHhHS;t+B?1aYT zBj>AX2OR=uqOq&i)LXGd1Hr2~ln&UoT#Q9sk`A!{j*;_IEGrtRbg@FwX9G~Dw7!ch zi+o887p+(0pGmdN^H0@+TTH?|2yI?Kbi9=mJ(M%#e?05KiXsi&+QdTh44x!YXDLej z5O}pWE51<9>9q=R?8*bNa_FZKul_M^dr8UZK*p8s_9MCoz2^+CMSMB`=9B&;X%%f~ z3vg|ppb~Y=fB3NuA)RBInt?MDRLn#Y92qf!4A-bcePmyu znr>Wb0B5DTecc5L2elGjn4N!0-MWg#{VXY-HD)eltSn`}gtexw=;>%r`iYZ2IK?&f zriqI4@viGdtH_oE@=pes_AZ-l1bg7_51%YNps-r3h;4o;G$$;HxpG1y1alja)r$X}U}LWL1pl|7|lSB6kn3goy)G#;Tgrz<&wAekiaQP8=x zlf^_pF_b%b#+&CW*CBqC6H~mH){H)y$h*guof%D)Exs))L>B1rGQ*)q>>}bbA&0a3 zw0z-#`SVj_TGS3ak^DUbhqyaiBwfK`36gijhoMCj3J&DMv1n^*^_Af73bm$hHrjDd;7s(uFh<@UadoxQIifcEeR=Q zVQ)XpDn(`sd}nPNNXcUm>g-a{AfOqVVDv67STKybBE?w-WMp?wv@aFpvXqItf|cHk zixD{Nr+=}WbZ*sRfna%c4KQ%SUZz8aG>FdMrbay9DOmkK53%ZE!;&nt!Xv*oJ1$}q ze?~b3wMj44;8&o-g-A52V)+D6{&k_wAGaKed)(QeAY<9L**@iW0tRXK-?vbBslcfQ0$mLYrnlCpL( z46L-h#E^N@;!yUuUU|9fyhNDk!!)qQum+{`XL7(Q2JB%Q5{6?I6EsHaqX+2tSBm>c z!b|DI-!AFBT(oY>{zj}h`@F72CS$0 z^=4@Q7MT$d8g~LAFNWC7GV_TBNGNw0Keluzp}-6h!Hjg4QHBybk-PFOu6YHHCOw-P zMBigI+pL=in*L0F`}yzZy)8ov|2a1~W{<>nt9)wuaV%)59Wt>v!l5(ug1pu-F^Xp{ z$PpHqK#KnKy14*r*rd0yRHC}0@{wq-rBnuHWp`V26D8Z4gAqfM_G1o5F5MPC3+U} z?kqUMc)}0MY5WK$Ui~@n3O1^y=UvmdKokB+1-+FJCzu36H`;gLbm=`~uO%7GQA#mS ztc7tu8VHJEng;01})BUVE7a~soI_8k2*0&3UBmmua}%C18ZkC}c>A=}fei#g#oHYRuH z?B1+(WYptPdD|2ZM_%EpB(wwPQH;M8h(JsNmZhW5UNC9DqhCum52p?6h8yl-OaU_S zF-S*QH9_#vaI@BmAMpmmOf=R{^hoi!GNQf<#ygSp<#t`V(^rm4j=9ims_aDR9?ojc zReG)WZ1GE!U9(4Rs%a{I+KIpl=7-+eAmVkX)gcV&4w>ZS^>^sl1+(y6C2kx8^{<3k zLs(@ibKpQ%!BM^%C3(l*g2qu6WyrTNvmCgDm_8%}#^!_!m^ht2-1b_A)T2FUqkPdv zuKeGB3(v1e`od+zBidx>9_x>&cGyu6Lrh^$8qp;Vw-`LTCe(6UyaS zqljAN77qO4oN(Fntq3BWfVd}dGd~KkVhj)vByyr#)g(l@oMbEmiO3@cwSBczafF(dG&We z!WQ7H!RMES<%0!6Ltrd&&td?vad{9`P$9 z_+aoKcB_zbW+D*F8c@M&3t>a(912x@^UN4fid>DQ4rf+>o`FKo2|k^@;F^Vw zi}%zwTqc8i64<~Hf-gu`zPqujB^ScGLF$>~{_m&MXWiewU3reDFK31U*A_wWN~{&f zE@=9q(j|A%$+89QGa2(Ak;c;R7{^ynbm(ySSF-Bd(F8 zRW$T>I`#6cqp2!x+YO|DL^}0iB*JoyN#qwB7V)^rOgmu`qh0ysnZ0k}XUSj}jf%}x z-z6?lK4v+P^uNXap@__cbX&F4>ZKia1sPgw388O$PwlI|1iyPq`v?>=`k}(D z>>~PI4U>oMmwxmXXtAjHG(PQVXaxfTu@WsJD>f#SOkQeE0gklU?RF;d1sFl0+E!-BxUs$Sy zb{<0XKr8B^jOh2C7%lDDU)SCD@;P=%Wgt4GAn5X*bf;27E|Fyl z(R%r1`Rp>k`Dr90;dS)ASCBHD=H{{ZB>rz$a@tP2rPB90*H{92YyvLGi1ruLH?na4 zz<m!}{#h%b zm2HqU69ZuDZWfHicucxN!wgritg5O?@#|Ssk3qnp5})2z5p+=IWSDnBN`H^TX;EVNn zr}m{($I;lROjh{0WdRQKo|*W`6wv5E{B!DMeomE~^y*p{Pl~IH&rkRoKs{az_jG^0 zFb-1}y@X^Aycj{F6vaP`UFeA*QbTpNh?b$rE6PUOy=neTnPqvcgKGV^){v|-PKJ)} z3pBubc~(}MAW8gsCU(Xo(zMdo(x zb`HDdqS>EMb=yxbE%g8fel3rivny|jfkWIo8BNroij9minL?A{i7C+9CBZ>8WXASc zf6As zbPAIF-dKS;l67`Od+WajeoMPxVYR1UuVVfTJ=tIo-E&L{KKAmJF42 zR17sHRS=^-{*O(5bONe#db3w$V?FXfqF83lA7~1MoX*@uvKI0jaH}u2`}ZEf{fppZ zNV}^HN%J6d4VoC}q$5Ae9fKHd4kGMTra;D_bQYFc5u-ahzP%8A6Xh6o3vJVKV84I} z03;q~V17vX30QX$NImCR(IvlYd4TjAq72B6*?b)@+oEl_^cp63yE-%c5u4c@z?nyY zYyhjiOSndp+g!e4zQ+4+l{8}84d59(IiUBC%<+4%3%9R#ik`_f48}Wx`j34(Y*SeE zm@_vpemlbt__nost7ar3nBB65mgTdx`afqyvxGdCDj?~IWPIC6El64ZF}KgR4m+f5 zEpeTJBM#QuIP~Su`QeVQE_m5N%3ODf>^oi9qfx3lK|Aov#~pBK5Z9+5FDQ~H^Q&q^ znb)xY)zl`&KtnlQGZ6mHF@tcMB?>jeF{Fe7SXFU%F~F;6j%k}q!K5P{tZd7w)O^_7 z_9OqWOuN%DW*ZH2*_+XWKI9R!f3<895E_W8RnAe?yNuwe-U-L32opO=#CO1ieS&vm zA=u@D;b2fpFtuw9fpDgpCySaX^+ufh2wMb}SU_2Z_TD$*xWW3GIoi7&Lh}Zt_r-6NVt(yGMAz?J^EoyxUYf??Suy2wVO5NW zw5)I>@uJXa5ez_pT)jrk9t=|DS_h8oX96ZXln2htbH;hz>w_S02vWR5CF-M8edBSe z3TX_>2wRm;k|ui2WwTj(@bDBkO{EmWECcgg&~|h2ZcwC(4GwhU$FBT8&dnuo&B-p7 zPHBi_NVttbNbHF}y(&cy-D+JT+ZUlfVoEYjE3!m`LX~V-LlciDK8kSzr}9A1Lxim& z2}xFxh7+OFPjq+67+QY!6(hV^=Of{bVoYI3MyrlYR1(+b!9C8>+|&C}6L5@gf+Hbg z6|8mAECINgFscjMpYuGDZ1Me^@mmJa>OQUGJFwK+1iTK|_@#kBRWqqF=E&jm?(Nl zIWL~n5#&fbQRo3p8%}R`g|pT$h;KJyHked)a*b&SaE2(H{qByd6KOc-Eyk`lF&!^F z%}Z`|Rr3>ulREN&fu-iE3vA?fl7aruUOzD*HZ_%7m#v6)PntcrzBr#0KqAl?{d*U7J)tWq;1WR`uxPZr?nj`Z@LjN(7RnSfnA+@k>hT zp^tfKJTprGvCot*sh(V%aH9_~InN=Ow0f#h>KKkba#Gq3Qt3 z(=827zVDG9+)6tlo!|Or-g!6gB3;o`tK0k{8>>BS)Ai4Re{rO+{j1p1)lpSiBLgiz z){RPr%%FHVt6W%?s)!_BsyT6^9*PvdrZ`{uw~^7I!vyAd)WUN~uzslry2F8WY_9rX zuqnreHftlP_fAS)t|^pv!Vjxw0mlKlj7`5??Q1da}wqZGBHL;qyi%QhGK8iyV9@@;W7dHK20{)KvQ?@5o$uguvXfl zH`#qjbijTor7ZV;UQD>_o!mvVCh|ToNc<;2^6;T=R3PCYz3-L z)Un?WCmK8z zhWB>V-H|TkhgT90YgAX}4!;V-(ERdtb?TY#r;t-U@6BpCw<=ONvow4C&MVCrzax3v zKU*Kux6bCv_IuRjX%r)EEqEK36nf#akw6Qhn7QAl)S^yyU|x_vxRtH_{hhH6E8^8 z%c`RlpuKGNlar=)t0&22pFEG+GMHH4E}cTGEiOy+yMPc6Z<(hcLTAm`Ex>#eOxf{e z8M-kAMY}FN2nimvqfc=VC4+}eyrnp0a&edjO?qi=B{>F1baK^A=tm2%zEM|A_kNu{ zA+Lv=bY|vLsOEL*eb;wkp2ok$sCYpp1apol%IwvujKVlXar*#_Ksix!bf-Pxe3tBz zpT~Q8CD76)-?&>LP<;o|`9Qg1b*=V=$b0ZgS^F!LM#apd&aSvE9jeo)3|5bA$QX?V zkjU$(`M1p576HBlRjYyuoqX~8L-J~|b=Wjq#jSnps|yR}bW^Rc#{7aSg=|k~WVw5m zQrwM1xehRwlv9ItDg?aPIl>P=F%_D=aY|SDi4Qow3DwDRF5W3iA9XOB%^Z`>uMNij zEWA35cPlg67IS}WyR>cXnvry>#vDmn!D+@hpw%c0WDd!Ool(`$96u2;XSR{ITwXh; zjU?ot^GP-DhAt*Y_U+qucyU=iQdU${vdS0qC1SW*t9E6nFOi!zUpXU(-I54Fn&mC*&(fZ}|I{q6fEu8LjVf9HLukiwTm-i4_ z-KqeQMWN?$&r0M}yF#m>-8%#k!U);=1$#Ngw9-BH4skT=@OL;D_qK|{s$aa*c|0~B zg=hP8rxsZ*?nkd3S- zn6!JDZ;mFa)hUUU;EBrw5DnL#p0O}3g!nW%rs733dAB26DC1tHn(3X0_!Xc6ndSRE*?99OXQK)3bP&t6(MHRZu!oq%HoUFA*Yeub zOTeRsr-#dq2L?qj(%u$Ldk(Jh8Z^BT7GPFT8i@-RUldqi@RL+v9$LS+;wLTFzVtgH z_hXkoSN;}74sRw}km&j=N~)C{38tel$PlBtBOzr#zyeqY;P( zL?mQjz2|qhq5(aViP>`)jN&gCKt4Sk4fh!LF3A5CSZs&bcf-f;iKb!Px04ZFRAniR zoa)-h!f@dykUvaxw`#yf1aMq+i}3;Y@7J31MjIB0wz?UDxAqR64DVCH1<&J)Ba{vj z2d1d9xZ%oTR>zHiDen=4?RV~GN%e0^nBNhgwGY|Z0H>o@<>Zd&BW4Rb?Cdy)QS+g< zDgD@3=-v(#AvBB65}&zZZ@$XE+xq-S8?VHZE7Qaik-QK5`W<&?@mJuQsYQ0>(dHGA zH@emGts-&hQPp426zb}o=)*N#H{??F^=^;Bgn4oI@_UzO5k2nS)2Wc#I|4)%2$Enl z+T|C||I%+&`SHbfsrd z^lE*@gEImYQ;LTL2X;>K>u7+O`&6-IT^4fyzXmyhNp$e=7RIh)kgz_l;-!!4z)1)W zJ2Mr{TzS#Zs58hz?axyfk=b~2tcvo6`1J&c*u-7fy#cZAQd`n==1F`K9x*hzw02zyfRQp-)@0_gzHmEtg1-X1Zni_PHhl75Hn@01fUPTZ2Tyb{lO_+SEp*7 zAd8@YOo8Yr|I0_eN?9WD*pkOK&@}+bd^w;^rLuo)JI#qg=%?3_R5hg?DUJdq|klH1kIZERU6fI?o@vm$plyMybWo;u&fVs&Z$Ax8n06Vwz76 z=OPuSNwMY))f}hMI&hRjB+TNCtEFO%&P9;icPasJ4g%dWNB{7B+KSKzT2`pT1w4ih z9QiS&*jyu@j9SKJQg&ZM0l)?YP_*OE)y+zG(1^E3a#p#JbRQ?t6)dlEc_y#o2wqc( zM%64Q6DbtJM<07H?Y%r$@etcxDANP5k_^W?SvzKG_kSm4@qvtHo@;SUR!l6C8yXM>|jHDtgf7bxT^E>f+)?a!+_?xmkwxeq9uM1d~7f;KaRClP` ze6Av)R*a^_c5aOU@Mk>a;nDHfMl9Gp6Bd}h%m^i(jt|boFB%3MyC_f{>UrqvtwCAC zP_!AI;fC9wxcpjdd*S&=4s7@|C95i`eJ`8~=CXrnJ=#D@;!v7h=JE@&ege|@w=}qq zTuaFST`JN$1J09zy4njs`5a1A9QKc#Pmt>|4a-1WFHNMi)4{hmD;VyGIf4Jz-ruNWmCXkHq>r$0AqB(E7kUq?`_aGJ! zN!OV^B=U~K(;IdR9!#u?uW7}DV!L{vd^S>b!OKUu)vt+YC%`sfbwb2m@Xgmteq7Br zl7mhP;=$$Ppfy3k2~Tk83V>opZ){vJMuJpY3A`DtuL$XazoS2n_HSabuHBhLtO{Wu zPPq(w+!0tI7D)JgJsv_an)kW0GSID{LFBbV+S#f*hxs2qyP^li?VCz$D0EC@_cHDv zmSXsHu#;}fFKVM$;DZrL9vgr`&mW(|;h)CZJGZ_gk$Qw9gWuay(m7z?=T+Vrd2wA? zG|}jd)JO`LMd*uul$o*2pz%=8)hY<`E+wvFZ#k3S8p0BN(wT8}RQ_!zd*@wi1PRmS zjHSu1yzoF^h;PW`MY~&gNHFz&t|}`?AjH`|-_>GP$}(y42kQ`D$>FrK{Mgk52&FdP zEn(TjHyzs>g!kUsF{=O8W8IZF4$PU{6SVCeD$>slHtxS9>p)T!9t4utfy;wD{N72Z z(^zR|y26U!oHR<|OB%rtk{(a6>faw<13fK)q?XB=lVK&KFYoVMoR~8uC~gizeV7pe zMNQ&Z>!=u`Y0~f$ozp$#Y;aaqD*H@PkrDb$1cJ`vM$4rx<^FBLg$q>{%7>T#xoc0+ z20;eMJnA4tOEw)}1W^Fx{+9LO5SsaU-Ioe-;~QZogsSYg0R0Bx0yLBE?6I}k1D0)! z#n$E<+B#p%r%pjfAxGR?zHkb2m#XdVg-hsQK`x;bPtzdMDNb{p%8=2|ou1|-fa5ZCZ#%!@{J3+Gu5rbfqBs8CHtwffBkXFj(xxvOMd zjd<*fE%!(OgQw%Ib`P+knm6@$VME4O;y0-@g-~$R8RAiF$|b_xYh&kymvW;5FBz$= z1_DE|8q$qV6MM%m>PSNJ)js@ynDIprs_$CbI}QzfHhP+9I8f) zM*yE+ZxuhqZ+G5+C1s~z20MYoldqY)is>TQzuaz@Bnn(dUhO{L?(!&i%=z>xvHnu~ z%PZhbJ#m!I>av)RniFhzn`mG>(K}U*@J-cx)Bi39neb3$G)b#mcQ=6Mn1&dOh z^R~;B7F(sWU@LCd1_ER~qrCKXhFRK9|3Gw?NhPx@{Pq}6YDMI(phj*$2LF2~W|e85 z9G7`U6A!1EkkWmIGvr_}hkDmJ_aFTdkdmwnUq7>Zwr)5x%Vc0e6eCy0iMa>q3e7>= zbSCjd%$1{z+#;mVymE3PvsF%AeMJ|~51*lYO^?x~W1TUQm~4S5s5}y3+raM}3f(M8 zUC1v0IF>|A^{gOTHoV5{s8~Ww^G=Wv2O|33M$mINs_+TPi#DwZb)t*mP&OcPcESeW z`b!cCFWB#U-1Dcc8t&gZiqAxi3bI};IYT~u=_)u!>M{p47?`es z(9jXt*7Rid|^{Suge1&ntT#m$B2w!fj8yJ$_4^W-K0o)XNQ@F|-w+dE)} zj$#H7Lq=B}I!mL;4qJ^Ee1W8^rknej1If;J^R!K4=ak!n{{Z-?7=IK-VaklxPf zWAeBU#^^p5lsB#9v3v~7-M;Q*HHi=R1LVU~?<2QB`V62(*#Ccs1F#tX9 zt8C#$K>OK!Mz59?)cl%_@2$5(^GSm*3yL!Z@*Y0}WZ2?+Z#Mj8Ax(m3hmxz!v}Gj2 zyj?X=5|@B^T#_7VpTSPlxjs_UFm6Q9OZ|6BT$Dwqyq}qQS3A{Apc@K77b{G7=Ymxv zR~AW$f$yr*Av(*vjIn*4Y~Su={p6%V>Q^JveoQf+Og>GjV#~+lS1DwplGLgBP?Bi*^im#&}tuf3JhrLr8W<#-9B9XCF9jxkMG&LPA5cFq*j;mO(r zZL$4IuoFcYBcSV5xM3dIc`V~nL#|4NXTG9ci@?k!~yMi|FcPw#;FYlKal#RwxugEbg7nv%exbc*cpCZz;k=crL9XUG1f>Q!zklN4n;OVyKWc+{ux}oOQa;22cK{HV}_D%%s6%W+Luk=cjBbd=`4l?|_ z2j`>rFtc2V+4L>md7F>aODXVr`)4)iv6znXvWH2VNRld`+09c?%eS}4eZ+!;B zsm#0E1Em{BatN=$D9}I~Zqxai9R(Uq>}FiizB!xbBD=)?VG2EoAI`ns;O_h12+T_p zxzG~xefzD63)dLAoF_y3+^0dNq;06VsaOJKDQcl|B5($JNqb5K*Hm!@NGG4U&h4T! z{N5(WyK05V-Y@D^W_S1vLTiC-YIPuP6HKzt`wF^nb?mZ`>`Ge`7uHxc=J&~lsL*$8 zR|@QI22N2)DP&Nj8J%-cL+e6F9|Ak@d>#jlF#cZ{sDCc2rqHYEp7NI=H1zs*UiG8t z&sRm**a5rH!f4!LXaLvu1-M9lBW=c092RXMzjk`7@TY`jG1-I?AT?na1#rzT)df)aoZ0XYL| zKf~yW;`Q*+0=un{6~2poq=NBpGvNGm;w#x9`cp}K-oqtq5m5T&tlK9wN}{NU?gBk* zb9;Ku&ZmLf<}(0dpw$O!yUL&2thwnlLY+XPrq}V4wSB&3ck8Z)O7)Mm24nWCd1$1> zNebD%e)Z}7HO;pqf^qy`nE|~x|9!p7m2UGnrn^=&hd1UE#0QScWWmE(t%eu+ZAbjV zku#4XTcR%l?U~?w-irzVKh6?iLl&*NM3s6y1iZ5cvr$}&m;}Z_5Jt!kU*0VZ@xN20 z4k38m300d1#F756w6@@nm)wO*r8spCP`&gDu7N=Qrk?LfjG-OP-?>;7*Y}c~*awu$ zxbwk^f|P*_mWkN8gOf~GyNY>(T^Wl=2bENsQsWc#`cw_W8hE#-c|Da9CWmZjc=P0@ zD^GLtFz^L^&loHF56SqgUh)~1oW@1=XcyRY&c?#v?~dGOUQW@&Pag9;+Ton<8;XsS zfTa&h{^W}@aGh-w|8`?1Y{77_7`Uq<%X?l#(?BEYrUiY!sOMh;$~l_(E<=wonG$k? zZ-Ib`R&!NvRt<#Pa1HbpYoFIzkq&cR+&&b>@4YMSNVR%s;9Xsog~R8}hn?Rx2Zno` z&h`^X`+rup^I>w-S|001@1RK&_~q89j7S#-8W#5Zao|F@0FbM|SOtMm!R=!P=eIC9 zs!FH#@4LKl6V}%vCPDhTXZNlI^shru|2kduM$DB3bMJ_U94Wk3v#Lh(S8{QyZxJMMzj`CA6Az5AxNe`^4aFE)1OiWJ`zs}}2 zA~rM?P17(@P2nZ~U}oEzIKZITTWM&12Wy4eb$R;rN@ju2jeKCZRT@8Y^yh_CbHpmX zH-FWOC@AI~i~?C;w6ec6RTqD8;l95^qmy2Wa z?cse?VCev4$jaU;Zp@`CN0i2P1MQl(p#?ady~O+H!3uY6uju|BdBwDQncgONj@5Eq zbJ{YW(F8`X$Qx?En;+s>>Vd2)7w{iF&;W~SBdiGL(F2r&Lbr*@=rqj2HzUrS0;;j+ zEh*m_Hng5Oq3LcO>0{K)?6`V;2q@)72(dbCc02(Bm66W+*Gg^CDGI;xHaZsV8?L^E zYY9Q$5PM@SX7GvKy;iW48Tm;hYtR~z=UbHQoS-bs+WsfG!N^v?J9L9qjUr{09`<$ zzo!0jZY~k8G3S~)yfZ2s?o93LbkU!NDDkqu*@}kd`D0s8EmwS(FOT13SKTCY^vjc(vc`$=ya zUs}%uR*{%-#L|txrB&trM!`Wax2bAjM^N+IIjr$+4VrAw+D|fo2BJmn2}lhXr>}7N zP);N~CT0SZn^)wGC%MZ0usf3?vTm8oXWR|AtcEw&yl28i7oiV_jlHZs3=G}Xm0HYI z?X7uY&>>CGg%RrynDJPU!$&pp^%FSzaN2Ccbz8~2>`98DW?H*gej&#t4$UJm&sDCF zgqn+q9(NVg9zdl@itEOXxuZ<(%b>?@pxsDC%{unz{nmnJI|x2S16Pgsz7JZmY%cE) z2J_jnOi06PlX&9v`fhD%p=L8K@_l-PHO*3$Fz!*b(H^+2lgnzmS)P}362N0zwwx{3*R441|(sOlaM{#aEndXWA z#IA88`-=vKzdE^s9Z>4!psAMAO%3C!={%)V0TaAT%L2o}TURD~F&CKqdsTO#LRjF& z&OGE*EH;=z6;Tj1d=&PSuY27E)qdT``oiFRa8hqX{s1nUr{a)zoGodxlI8MRUR zlbY9O(r-o}W+vj>$IvkPjRxAK|4AG@uC>is3CG;=%y*}xEYpSb5?e1mr}^gbsGIr| zS_If`+)B+Hm7fpYWy9kPFn0^@ogjdqvLOuO^`rMFv+@t3?-&-s*r02%i1z&sggz|< z8hIh1;9KoHOZWSi5_xoHw{OB02Ao2eVqlIDh(g*@p5Nj7<~b$xmse7#(G@?N?tqWp_vWDjm^?5JpNIkHWb`si4KmIWj!MNyLCKUacM0L25-?4lh_s(d+9je-x#Y zH+e`(Et4PvMw5j0)9k#VTwX@=83s)u^ytiB|ZVP+W@tR~~zdadT z;lL$Lrn9m1ZD})=iBzFh|GkpajYd({CpzEK{am}Mu0VEP3?CYgKgEg= zAEzEvvY5bl|ESHoiKXF%iEiIIvU3h)o2E`xb3)nH>)Lo^U|E{rDnLE`(HRk06JpUv zalL_b77N%mfM3*_jJ}Kd1iKb$`aaoB4D-K0a?-&!i^$38<9HVf=WdMeYoy4_L!V=V zOh>U>#qEx!XGcDj1*`t^3X`qZ9hi`76O!@X*)b|njVOX|Oy$Q#zbN1iqT!U+8r!0m zR?S*&l2yp6q92lE+TPs02!XE<+H(|*sm-VoZ&RlyH5ct>2Ir!BYNyrJ?#i(`*f{@n zX>-G?1l!3o*5|mRWD;)00>~LA;5x%CMT=$8=0Tu_JI4FIG$mQ{i1?>Bs~pJVfHCx6 zN`2`a?&Ns?xZSl0s}*P2)^*FFt_`!21=ms3q?9ZRp=iDFNXg0NA@hn?69Swg=+%*+ zq=LX?Q)lzA$rlX|DGHp|?dKxoQa&{gB@}sNHN%fOO?k|v{HMcWmP*Gz(BG%^4^mvWJkBI}gPs^-F09vJD_<2fZk!=9?xufn-ept( zUNcKst0h^Tt;ZDx&c#=4EBY@-1fI?=>kiJ(C(C6OkWy{GCU#{qOVKnhFZ@b-E0+gG z6y+IDOmBQ%mg|#?dO+zX4Q(6lK19O&5Jnx-a;R{N0>=P)NQ**L&k-$CZrPkT%3~-@ z_4bL@v2LAoZ`e&5eNjasHlIcI1ZLq+{AwFUEXC>7d0Ltkhb%N;%>B+i^F(dvab7nI zloza0#x6L%=$VoJ_a%*ykS;JFOx!Uhk3rN5nNA5R`1h%U*u z;JMSr-jlW?h;4O2@+!`F9O-^m+tZe%D5b!X{XaGOhZ?&R534G|ZjrMhF@~9yqYsSv zX=>gv;jZHwl6nz?xdq>1pJwyme7mQ!1Jsvq^Ya9{hIV#LTlWx)Mw{^-4~g0_uNaQZ zIOM<^qRz4b!HL_+1K*#_Sm>#xWVqA3C+=ls^veOXjzpJmdJYZYmza zo?cE;FxZ#*p!L|l_!yoi0NmtQ*4UQ(34(BL;*4LFq_J_S_+tNnk_9;UbyT{8aj12N z&R}_c9ez;u_py!k_9Ni%Y&Bg zB-w`eyk_~;ztr3lEZ9~pcX`NSSJ@>v`!s%|pq&vk6BWR{bN|%wsZtVNh`|t;pM;Lc zF0p%efo@g_=gCqtbqU%`;qk!Oy>>5Xd@aFUN&N$GA(qJ-O7I$2B0%4_#^2V0+?2La z#hJZ>x9;jpK+(JOh*~_MTDx0HnvgW|xhRxg;L-2GTQuo>T<*85`KfGUKJ;wf>f|Q6ZfwlVpTFa)Xc5 zbdqVPt2cQ4$K#c$_b-+H=-wULd$`s~L!o056l+cHOCx*cy}ly}Df4)5fLovn?7kcs zIN~&sVUC4Lq+w8iI6ugBDi{zD#)x^3sCN|TZV`+Nis*l7V_?n7s4tn)2lsIzY3Qkv z>12E9P17{gHDMVe6y45vHtZaj*0Fh^l=HIQoi7#_d|EX??yLCu<+s(loJuCi3|KVb z85F|phF!t!d*!*&G>MnMA@QAiRgKUI0C01oi@mNE)lGnF5X)GC#{t-C&RlF zuh!xce~mD<#Say}s>14@#~9d)7pon!&mI`ZQQJ_}?Zr*)_gVoVGyL{Cf93VP!EiIO z1r{O~5kY)g?Z~aPcngcG;M9e&x5xfpz-jDiR!BG~p3j)%(Yzbd&1g~2W-u+v;%1aQ zqsXiYPF$-FhJP~%-l_UF>cIgQHULA4`_PWeDS_d=S$vOw@nJu2vL)BGV@lWu*xyv% zbwHA&naP|_xG+%`0DCm($a!30aXh+g9stl4k9vqws37K|^#FuYfp+1L zS;dsy+V7%ICm_XdVe&29mahcY8n4=re%XsOEbh9ECRL5^r`Txf8FWJ^!eo~I`)_5j zv*D&%GH4p0)mOUKccgFw;dUx;N@VJA!UWOsog+7rg?)S3&0b=qZhjfLZM~Z3EUwz^mN@wIC78M4N*248yYqFDt zDI`Y;d%{5F(2~GiR{9^FH4qFtWGp`-Zym%;OPoZ7a}n2`@MC96&;=b9WzV;{i9IUo zWcxzj0D>)-kP)UL63VsFgR& zi9)=A{3pwN`CiWo4Qt9Vq zuD`(n%ZDgo+MjxoGx0K`aBL58{>*^XaJau(Agq==*%A*2z?{>#TdZe zLKYT0PcNn-1I%d`tY0Be`%&&4Lj!34}%%lzCUM-%xoR zcYnnR+yo&V6b!xPwiX+zAt8Pze7GL9#*a766#m7F|7^TGCx8&!zJR>E#j+*4Vc z+Bt)^Wc%Btc~DJTomC)oWjw{goxy6iW759L=kZZRDqS5>OST#*_$nXze2#q*MRDKk z0b+i<8)PZu*sOdL^Ax6=vj&cw6N6VbekMNNw{m2asBrXVEe~f)&(3+~psi!^G;W}F zDj!Qx*3>udf7S-kf|Bo~*b}Q-g_n1sWG)cPIc10)PfKYYsbvmhTB+6)%3mDJ+PYp{ z{tBjwv%6-o+4{!5U@5fz&?Mm-mvSZ1$+h8TuQZ0- zBg%wcDthLxpV1kC&kPt-qlh?cBhQr?mD&P&sB4>EWz^tRHjyr>9vpBM8>G6fwkasq zTgLZ9Y2Xeu2=2|1N(+++DwfLMpg6`RUd2@Bj@kTI7F&OfRyj=hV(&PrJWHTkc+Vqs z`-wq%vUe~09Z{_b(s{&8!g}o~uTF!XxU9RQ-%n!WxqJr1>FTt%%9#kN42e?ubSExIV zO)H|6w8B|=n6!j*eFxCKRLQFy%3uoABkq=uhNWrw{~fX9w$A&>S(?InJz+(M65aEx zUX~8O-6D)k@rNmqO}|FJ7SzwjC;q*GRJWu7R&XuOvFJtYLBQ{zxQ~NcqSeUJ2sN%v zUh`NUjr}(`Gn3qf>s$*;$v*$bRmE`GMvA1vSbq#ko2uV~MXy8_qhCr^bJ#RU)eyX2;76toyzLz|ONQOmzJ_k+HuXW;%XRju zNphTO07(2gZVY>ez=6Q-rqTF@9<4HWqedO{H56K?ZwY2z5aMS0yfGD`kUfyvO_S=z zcHl0O%(aib5DD-1d9a@)1`W|SI6#-PUzQa?fonJ0(me!Z`(9c%ZOi7}4Q-Zb`y(B81vw3194R}fFbCW}(JZF*d#2eg<;)s9 zL!CdE7*$iuCcm^4I2t{>PV+4KK?84oL*`U-;pqqu->eJqrpZ*lY|cu}i3Ylc%xuV5 z)n$Gyg2lqsmPMf}spVhGqx~~c>F%1i<`2U7TpiJ27~VcoZ<1O=64WFUT1Qq4MEQ^< zgZh5!a0f!W`$s0#^T}ekQ8KdwAOeM_`}3E~uQ?yHo`v%-J!h?8{Zs6;4!uo@WxsH? z#V1-ZL+k$6=tc{!HI5Ezt|anvY`r(u#W~up8Pdrweb~nsfeA4G@v<7;1m}eiN2=ms ztzhM7X+cwerbQ^k^+ppjjVCX2v*g-X%Hl66sG)bur{eEHqS&<`hJq*SoiiXyTB6886NK4q*;TK!P|r_qX8@ zIlacdV#j=x6u4b52~u5NSsyQRCB?3CH@E2P%Fc)zvHSS&bpw5h@^_7SRUcctvEYm2 zS4^sg0z;vho-%g7&9VXm}Hd zbU*7*ANIq6Mszo%5aGFd$n+6(F~|CE3uYw=M3Y&*Sb@pC;!_D^SSc_@g=^ljncJhi zYisQwNIX_1$gNmGAgF~6zszbD2&TRXTvd{NY#d z3Y^kt!XilRcRPzY)A_wL3Y)sc2+0@1t{tjV=rd~P=*rvGA>l4ZSAC|LU~P4!4u%N5 zIif(#UF3QZZ9oWG{zhavY8bRqa;3HiODFlqH)ZZkby-WBPi`s^Duk$4L`hOe2PjGl zQqqR1DvCn^#r}s}=xP}?=csB1*mjTML0J`mXrDdjjLq9Ci+o4c1 z2dsh~L{t-Xo#r;(-82}E;XEMTKL}{Tr<@%-9l|NKG}He3BA3O$AhW_gWf^EcdT!bm zM-=xAbZeR9#8dh*CyjxT_QPFg!c@U@JBGzVcknSJj+t`_wo$nQrbn;cGri=~KB=q^ zo02Jks}q-!dE-Kg9kWB0Dm3Z&5yR?LFs6M5Js$H^2oIQ5Na^$G>@S?hcnVPeeldzY zkF}D{r4N5cH0F25(LgP$&8aTBrL-P9+-$w;XIke=scx)%$7XPI!R_?X>0isa>Fywb%&=RAja-;07?yQSxqMAwj0h4>I-x$bA!sE;YyzWN%{v%> zIR??VfNU!3c@szwM=cT2tvGG5Np@EY9!z-i7%k*Ml#buk)3-Lx;{|(>SG&slS&846 z$4APjik{MbGoQ;Mw!(_$ECuZ~{>p?hu3evldUTW0YiG437{IUO8d-2)RyUzcJ^5GC zX*woxRY}zU113aQt(m{ZmkIEcwQ+6^jV?DPn8(`${95_E0+Tm%4T=@!ymZrMLMoGL z`fBO7fkVQ0H{M*p>M#(=Q=H-#+bhJpc6B>}Qsk;PTxUOXU)79eAf3%|IDmN8G-Exp zVZhTDXbA>G7%kA4Kl=gU3?^^Z-d}PlpDSYa^MI?kled_3DSTpxB9kA51>rOVC+%iw znv5zf4-sC=yIIh=NcYwlgXILlhmL4Z=;wLw>?B0>Y=3vke}i1=s_m6-c0_t|GJqjE z&bPo1V2@K9YCd5@R5~m%9MKiaMJ7hnHW%cx;(;b`-)lD*4f}d4jjt0Zfg2n=6#mgv zDe3u^NmbK*cL8H$H(BcI8lxvr?VKxrITJO}X{e?)I{8lxaeuSeOjBX3;qvFzonYKJ z?(5Sn<`DPau($|2172pd6YRq-V;ekT`2xcIuC=X~yqetOJ9^MS`O!TG(93Gv?h-!uYQ7M~BMugQ0oqlqaz1$sa+`)wx6 zldPpqEOz#NKCxbKiUAs@6OhwqaFYIoX>NJX8wXQMUrJI(VP9FWHoCq>c~ctb=^|K! z2KhTpoLi@r>mRy*knBohmfLBw`!4%mL;zwLSz7tcnc)NRPM?i5sq4RDWxW1$co|4QV>kyz8B zu9v_n3dR`@p6!Y_CaMV=h6PLkPZKF*H-vj%0?q4FrD8T4P;g#%fJtuslGTbY<+rMC z0eYD6jI6xMS74*oz^a< zKlzOo`BR}t*8pb!NNm>*N59F|oZtmHhZ3mAFdIN0tV?vjTNpz7-;C&y;_Zq2E0Mnl6bRsU@@pNh09qVQ$nU1W!~SJW zz^oR}kD(Z4t`INcq5;w(xD{iXb+XdRy8SAkM;C1>yWfMvGc@Fa_g`zIG}CAK8N1&! zH*0e`Wzsa)4Qn#RKjiAad>^xQqB>LWr+k1dv+2NJoJZ?Ma0kej2U^SBFktIGbX+i6 zzlMyjjsOVFx~L++EetRp2~DORyRrc9MpDVar%la-Pit_`9RNCv&742ez?rOYjDh*1 zNHKV>=KW$8hE1ls_Od?YictkH51u5&Ub+jno|@EAKqnk&V!;6N4RmeEW`%S$k9SW5JyPSeYo2CJJfyeMN?D@{~SQcLZ_1s$c8yh7Ip zZ%=*mE^)_a%M~9@2ZHgqUyV_e7vfL0ndVR;cEbcpA-#s{o3oNHS~?28*mxivA00Mo z8C)6=T2PJM#tRciZIG>dP8wmr0w!VoTuVvo(uYV#(;x#0Ka&J3KqO$zPHd*9Ih)gB zC9;2z%ycnpD82(A8!SeQc5-62P@Xaa2O|zH6g|;osq3|nZ}w3PFgOmrZX2Gpa|3i;Y%~rjUu9 zP?N)ZNdAnoGXK$KJ(O{^lxlWx7-*)S!KJ(MKPaavc`$()U<>X-T;N#uE8(hB6+I_Q zVYD=J9e!v4zoNM)mfutayPxtM36%Yo6r6w6scdu7t^*>Pg@^W+=_EAAkAP2BnH=0& zj%M?rhB_Vsfv3EB@uIOZsn;cwskNRslB0BE3!Iw8e@WcIJ+ZcqDqsRd-`cFe|HhU!a1OU`0s)}4cgXoHt; zo#1`^xZAfzW#Y&(QvJLxG%$JXkBQG2IdYA>SmF9EeH}uVllv=aybEZKmoyRrnEE;{ zTvo1#h-XkZR>fZB!xIg(_#*5pi_TYpKb)Sj+*Z#9WF;ivH63%|-^ZoWwVa8{F|;}G z#-oUzD(Iz`HTB%`#oDPb;WZ|PPwRhDb+jTI6dK=FR~czzTGW=F$KOFT>_>Rpu_8lI z0!%H7bV>Z_KMA#QVh@m1pm*HlFUX20xgU_*1PT@0m>bmZ&t=p|Cyh$h5)d%w^Y8V< z|AjE4Y%3nr8}XRYz=rRXWKv6W-l$p$;6j!VK2%mPHU9CFjT-(dMhsTtzfE219}dYH z1%6UK6)91qpM4j?#@!6nd`+5`#U;tuM6f|5%XUg2b0xBzK>*m+HPBscGfPO(i?GTS z;Zgg!q@Pd6C%gex78=+kQeD8lDy=G=*?NFbGkRq8qOfhQKJLszjQKw^2S~*w$xmw# zkZ!=aP%G3uv@lY7ViF1sMDhJbsUbNKmpn&fQ~r zL?oDruxZ*tT&lOFM6hWm^!(|x4z0Dm5w-dZfgbTCAUmhBPyi8Io(n{MI(vX(dXg1~ zxC`9CnCcRbH$ybvkHP%?t2e`wup(q4tRc4LdUuXcg+mZr3~))Ptoi9Jyz4Qbxi(qKL21%6$d`f$P^N6VE zZoD0zW?&jDEb1ep27)d_=5MS7IPQOnh(~2r^4e|NJ5+GFsMj=7%!(f*GakZ|J*bMF zoMD0!Cy{fUA7ica+B>mh(S5eaO1y0;v*BOJWZlEX9QrVWBIz=fRlu-gEW{0~4J@BC zazmo%({GUD%TZbdf|OYZuNuI$Lypd5oM@ItZr%di8W~2AJ&Z;9#Gf{Q<-fzajlokGvk!V=7s~#L+OJ=)CA3m0z--u7YOZ;O%5)j zo%BecC0MPXABx%oUKx3>n3D}IAR=9m3lkL7AW|~B@QRhlC|E;lCYAI3<8GCg$|0MX z8~K9E=ZVE4yp6_fiC}wJ6Qvj!gpN;BzH7%)OeX!(Ank8HZzG@O?9wO6d2DvkmXRq{BCQ^nX}&sk5^nsYK&^Tn4ER7}fdfc!Ze7jxO1bUMbG}crb;ND42sazb z>-NCZtmh8X2=RS=FPU@!0(DkPILmOL?7`MA{U&-|rBhRf%2n`o_Ia`3rHjYopD9yd zyA)E2_qua}thCf|rAwS1LD%l;vtFDu&QRLm*FAqV{z%wMT+Z;v+Lo02D`FBhp zQI0l2T8FG%Z{Y>!-fYHr4$at`T&vJOVd1@xCFEoAq|w&E6P|JMUR`ASsczvAW~~Bc z>L<1bJ1c;B5wqj^HvVXCnBZ`vW>0*yw_90H{XEzs(9R%2|IVk&8Kn2G|4f>eY$xc8 zvWI{S_<=!{wn(rFc(8}8y%!rQaP#C-C-@{PN3z+M_qiHicF@Em#ZNLdN4S1qoR5Bj*Wx znMWQ6vnExFJ3>nU*!+FtCN9JK;EC+%JaMzz>PM!#mNUVeAw;w}iHa~2iE z5}ljl1DH9ZDwS2``wXPiS=%kbdd@zCNXEiGf8JH`Xx`3d!rFB}13WzN8g7Gm#KHW4 z@fVlYds}vC&9*I|#pHgGEZr^x#0#SQ*Zhnr7mAy#(H9&4sh}QKl^>Dg1PQJa2CYXP zbM!kn8utY^N_-=_=>@x>(pie}OG-xT7y`a<)-ckfUG_J;pop~T!73=L4aep`@@dab z9*+$Fn$uTkn)8woW8sC>+b5OIk0@1Roz?IstM}>f zdUt($&!V(#F8o5|2~U-Qvnz2&c1B@gkYf*6(RaBm^JpEm0gJz=5wu}Og6A@%?0tSz zH#vQK$QD!}U#6$ct6URzGJaQ3TQE-r=_u6Cmxh1-djKEX50vm8YVkIlRjNw#(D$&HZQs> zu3<9uimMDbxzL=Gd#403)jMbzw5EhP!37;f=r0Y*L}H7GMJ13Ii>Q|!|FdKQkkdYj_A6?QeY z{KPl4lXO$8qt6#-)T|rbzo=>NCnIxQc%$>PnRssLWfin0!RDZoj{}h5bAiZRHaobb z9FbV!u+IOv$7Z&YwRG|ZlT;$j0ri46(9S0(usnJ*yGybnRy<=<#lUJdcd{U&%(6pa zU?`2%)qX!QsFw_F_u-7~W0C1&&z++(kA5l@)buuM(ECCO(v@jaav3}Gj?t?%;2$kk zpzkJ(NXXf7STyOR_q=CjEyjt+@p;j8qDFq3=K(FN+__)R z8@-XO{MX75{5~}dxN9`v%N&mzZZTSE)U!bDh6SsMF)cWO3 zOA!{Oq)nY;3be+jsgo{hxfO=*CuE790jiiE2w zs$!%kCk2@|L&Wa6`5R&>T9G4d{15**al$CsPg`rq(TtQ3%@;Eer6t&JMzw zkvlE0RC?ohPuZuagI~hkF_c(uosV;&!1*MH|DMGAIS(T1!X>gxXC{xxm(qeVG844A+O?Ne)Gr)y&u#82S=#}lF4a-b_i2nSd#BD=*|%f(4cYv_vkwdXBKe<;W&WW( z#c~odheHJ&IVO;iaP&&#NPoX7M3_~x0H#Ks@6&vKGr9z9$&P6w>k(m-$)o+e>Kmdu zTd00Iv~hS4bkf~SrMKa(w9Y`v zEo)JB-0}Wg%O^FeEPD-p9;i-MT)&;2It-(GF9KwuoKO6*buD`|n^5dt|D=wqY=NCzdht<)GFrm9?>-)TLa`h4gA4d37AaX2PYOSW1x41eWjxR5 z(K1alJb>rD43gaDk&aI5->;Ou7~GF(^38t3a0-d-d2Q!47Rf2wYoZIVVAmt3RYl}t zmp~F&LZ+#G(~M0Pk|=9>i0xGJrRn)wvV6#X)pq;`P*+3rGzWV%QaLk2Z4}LJ0I=8~ z5&?!qUousK#6HO_?nYnQIyON}I#+sgFp}s#AID}kZ5dJuzz9Fr5mg^ZpUV60Bw8iR zByZ$)#zjl*WgQ7Cafmgma%kMRA1^Ha$Lc_ETas9qaC-T=N^6`>jq~?AB*v+g%&%k- z?pbR-o1V@55dGPCwzr`dlMoALmGBhZ3^Y-R1g>u(UL~|JN6L?}AjZZk6>Fm{4Jq47 z{y7YCIbXI_UieZ>E_nNcts}-^Nt@xZx;jkM-HUUk2_UCKcKI5Z2&FYtAF?sE+%iKg<8+;k<|;eAUcvGJ4A##c0nV9;V$(*Y`` zrSH?fih#*^)JikNr_t@=8`ru;;`tTFx_pJu$5{ulO8f^y)Ar8+3(5BPtEzQ$dmkOgt(_K zl1*W)P_e`R-+E0Vvf1O+covCP&@LBM&h-l0jTn zOsgdxD$TLk)NnoRc{O4T%k;V;$nIKY^$db#bJ9m2qV{KtQ6a?2#F(JW&g^5Zz1B6- z%ws3>I{qu%sNgjdoj?D#0YXGKT!VMYZqg9~VjZ{U3;2v=|EzvgF9Olnx1+RVuS|cD zfHcUvunU>u6_&y1Br$;fbFa1HswBfV2WyFwXA|AIJ22^VmbQmKaL)IB%e8-DFo14 z!LZnya_C+%)}S0JhX#OL;&Iy;@&v=hXd@J~9M#vVHluJ)4xQ6fJPRKAYT1Frl z;Ji45XZjYsqaTbQoAc?ebw`Q>)h3KjUK$>01k0Szen8kGhW|{*ipY{paZbi++^%ac zIMQyxUC_J3DdkRJ1i`5UP9G@ho5)gO)Suo2rBWf=uqrE6_nm&$ls~CY%=6^>UM#&M zk*cE%X*fhSQHT3n!p4JWTr5!sIKMIVmon0T60{48A?DX$MEycsKT!*I&rc(q@n1x$ zAgZE@{CkJ_*+$j;4`7ou%I{cz92ANDXSfX~WG-HD?&UC!-0T46=xJCKWi+h0E>l7+ z>ZoFR8Wj8DeN$sPKBa-&b9W$vEvCLf2z>TXR?BEZ-p3LNI3*Z5XN{Cnj<%f`G@TUC zV-?dN!g@jM?kcV2j7rR}o>Yg0`bxNrD6C^BJjV?M=d`{Oio{SpTwA>?~E z$MHYWAYO+@HifLA$}mdMC7Y?uRSR&0hMXbyQpYwyYFww`P^zz^7?VApgs24;*8>A? z(Tf5^I1FY7(&R}s)tvY(<>gNhv&qyjcrv%jVD zEJ)!PR>c{#Zj7rG?}^uMrEytac_9DlNZE&WoKFD=6KAnVN*a!+bqdVmo){I|niM)N z%O}^MUFycz0*uj2E1HtBHg|I2P1wIh1y}UX0I*HF(3NCAdDQ5m`JIC9`+!4&mI}wf zu#_4Zz=rD?wtj%M=uq~BMqH{SfrASqTd4z0+8-bqVjOKb{gMC!)@Ck}v5ej(FWaQ> z07L~H?La(@v|*1D3k$g7|N6!`Mf7Mi$n0)>Q$4OujOv(ng>E2mHqxs-BlAmtn`b@4 zIEEH!_nXjcLvSzM3K+~ten6t=D6_9(66GO{CK3^h%5g@IFl z&$6sga#Ll>!32P)dPByPAE8$O08?`O={&k=h?X<7xfQt({-`PGHOc`Q#EsN1kWY3j z0ejq+OHk`LLcF2Az?y~3IQfqxJ~?`oaPj!=YU1+j5A6m4@__+WPQF^cY`)ZIy6B^g8RvWQ=pmWAq1~6tC;BUnURH) z{C0|Xw{&`%T&=LXOYs8yLt{B&>QXwXj}pld(wv4QZi!>@&ieMdraOE;wAo3hTA<^i zK4YsjyxT8Uebz$Wrh1HK`|U@+4?uLPh>Td*^Dr_}jb+itU0YI{TMVR^KhMk1!~V2y znV#K>S+@$RI=9nnbo!M=yCFJc0|Sm}uWE6Wm~&!IFdZ1w5|CSO#i~tu}O~%;D_+54b9lp=RYRIDZ`!% z5A0Eyh=o++`6sV}xB00T=}IeT?3mT`t9{H!AQ78an{RYC7$id!eP_@o zH2yafe@IP!e5c$|ab%1_F{!!>vV%{Rs$3X6x;1uRhP^5t`1McM`sEdd14cTZb1JwY z9huu6CIHBlP^GgyNwD<%ilc_{-yBi z3Oh$~uQYBYs7)@2(3&tq==m~qPfEq!RQk~ADz(&B7sc?MF?i&2v44~~D)6?F6;yWS z>2XYLE*?nUj#|=BB&)Qu(RT@nTYyK2UfY&Zfj81?B&L817^lg2m}Pp4czB?4U3Ex9 z<;EIS(x#fAF5oS*#g|kx!lRFvY%kZG$@b8Ef$ydH5c@oeAWGWG6ueidPqmE4g%U0Qr=t(>lW-BHOkG5Aj-W{O3?ogxWh zQ^FrM0k*qVt?$E))P|`DRkIU5mBI_j5*1Q~W@w-s+79T_JPQquLqYTgC@slUrFRn| zW<=$C8bSgBD-i1wjEanZuTHJ;l^Tk4igO54U0(9T&<0SSJT%>vvzu4WZHENfoT&Qs zg=Q}O7e)#cd0!kA;M4|V8zOOHC$GE?SPlITMJLV{WyEIETaQyS5;|o6)LF0@i_5gM z5+HxbZqL{x7SIKzD*r+Oa(h1mdeDyML*7!15Qn1Yhj0x=oi~6%dd*!^z8h!f8a{Uw z4}ptF3Wo`E+$7PB=@xOyoK&gAXQ2QT?CH87Irs>J=aP|?XbHufrnoaOvj_>3t{-P! zP_$j~x`vYVWX1ER8a+vFe3PP+D?98aH%!ljp>@1Hq8&4~{#VF`Tv}%tJQ)|ovxevt zK|%z63BZwc{tGZ4@ej zxYS)4@x(OGG~G9pZ}VAx$Y7Z9KRK=!P4g5A_##Utx-pXY9rz#6Bf^%kvdJi2`*Ck> zFpLxv2g0x_7>acNh$JH1xUm*$`0h;k_9|<(BDPH&D;WWGm(kuUlr7?0064x;F+ z983v3U#oow7r$}qRPFdE-#~y0&Q(w@Sq*V90|ORh8(`)V5itPSh>=$==r&$V1KP6& z>X$WqP|wl)rE!zO4Xt&J?7{Mi*H#1U7BRQY@6p=ze)5qaNT_f~Mt~4o4RD;~O=W0G zx%fzdY55$?B$_(H_X&Nas#o*N(mjf%Pq=+V7DTwA<@xbwe**;DhcI?RzvfP$4C5o{ z2)ul231#_I2e(*WvG@@I8rB2?W>%*{NWmHhFOAj2N&qQCc#xUZ?_iR-(oe*>*;pYv zkvq8NMEwtv!NboMeR(%YA7Ti+t!cP;$sBB|K#3%2g5G9{ME*lkgzAZ-BOz3Vom8V~Q+ z*6SSsJo>iC_caws+)DvMZP~1kJ;a+PkvnBJ?tX{2SR~4?I)}i*kPr zfWE(xq>ZIX0uzz_v+U!7c3B=n_Gl@?(l?!>BXV>OnB;g9&?PXU{Rgl*GF>#VuM5tz zC#`4F8=0%l)|3YS&--2;n2?w2@;Jtgr70b^ z>;&CWVL61SAb3UI;tq76O?=+Pk3*DGd_O(kdPCu26c6p&=nv>?d}8;U7`SPoAuu4o zf38fmOK!Py0(6omUs*1%2M`FNmE~JU0&+$29^pBEM43%B(*t3X>NHM?AI|b}CT<=l zl*^@bfu+G?k1r}0DR`!plR8erqGy{Oj9f_#5fOni&YUa6KCWrM;dJu|J5C}=SK7aN zB^$UbcFRgVqDP5kE(Z>(Stx9P>%lChV*EyQAmk3*y;Iy$iltN?Yf{KCK)ECKfm32s z=4EOz$b7qz`&JpW3caj?t2 zt!W{N{z^?im)ZSb2GmI=XK|>J@PJ&f8eous3IG03vqpY+aTcZ0ZPX< z8B7mW3GLks@>U(;cii=pQojtpOVFL!Rjn0wDEAz9uJUE?E%X!$B5v_RCj`0x)Rvhx zPsp#LBa@%bgOp%?R5q9fM$kf1wl}!rmih_A?Y{!p*$kfYTxafZ3)V(x>=bodLgYAU z*4KZqkfy{=RP$dj#z9H!e3hDbtCG=aT7QCEX-g=cfi@=QnU9LzVtI%Gr5^a)t7RDi zYyHz2%mK>h36o&eFMaZE@S_IhC9r*(N*I};{8>Y2nM-rVoGT#Z8J*~+Ra~YI(9eUWzhK??@~r-Z4V{pWX(uAHZjO|q0j?{(eJ4M%x;>0OJ_x1Jjvj4 zm7S~lLXY~^F zplu6|vyBWjUl&g)s2=320~rU_`UUZ++-_Cmo!WRqdKX8x1xnUQQu&H`_zg}#Z(j;$ zNc#d3Vqz2D>#!QF*)8adZqF57^YdItDlaIHb#tu6fy?I5k^bn+SZ6h%3!3kJDFc>!tprwIh{l^0|@mB!tn- zVcwnn@I7?c(sP7T^fL)ykCZQvT}_a$6&H~q@&lqnvH>m%uyyrNb4-6Wx_EU#AQH#) zF_ZmKK)ajIewJI9n9v9JGwcozDMl{P$n4z&8e7X@$PX(c2`y@x1Yj6zDk@Dqdcdzt zR_CM89F*e(EeP>MKLuH2KJsvDZ#*h5JnzzQu!iT@#Ey<>A>R1N4^j%7LdyU@K)}Cy zXgUeV13SWDH?o5pW{K%-yY!_E1F(aIGO>W*V03Ub1RZVF0Jv=mRnWWgDutoF%5&?@w4Gnja3={Fc6#!VAclxWCmpe1PaN{%4?9)Zn{2zY?JXX?kRs|KS zzPe(4fDIKki|h~-$IN$L)D+9j-i^egS#CcZ0@AMYwkCe2$SaTj=I5#cXx7)WaAD!d zI(@R5XYn^vCZQN~gWVr66#8Ht1Y-?$>re@`v}LH+=6H$1+4DwLh|d%&i+Iv|ATR6v zcwv`;kmXa~)5A}g!^lzpRak3hTH%KwzQBs@AhYviJfKzni$Q{eZ(n_;TDtdW%yg@L z)pU%*jTM?N3*giQT_HA>Xc@+JzS^^7BAyO~rNE^+QaI}&$uHI+j}!Pp&9HtX?=OxF znbqJEp{IYkM62IGow)Q!csw~{Zeoh-4R|h7)E1n-DeU+R=Y?q-yj31#>f6a1=3I@<1K7CBT|3OwB`ulacr>qm%g&WQdn0+jb0}R3y zXyYqL49UoBB8)#5vW?@g@u|4=mRJ#RuGiaYwa?{uc55_8DhF6egVn5I%gInP8)#7M zPH;j7vj>&*!a$|KGQloYHrFd`OSWmU#)64WnC?ftUlt4c93{vmE$&VlfWb>P!9J%c z((frG8QxDh%soq^RKBu^I(5vb`4+%Oha~ez{q}3Le$v3)Z2!J8tO;zv<_BI`R8cz) zJ=+A!KWTvUXafljPdjSbKc*J%VWY$FYqS-CMzN755|B@zzZHnwRw`?dFu zB#S%2KMmGfj&>*c;`!OycLHc75lDn)muoYhP>4skF8${t+1fm>Vj(i?`O z3*8-3k>bv1h<*~|5T_%5sIl>fjxlY*l1NvbB;a!wGBUEd5M z3xFLm=eMfrUFJ47*tTBN$|BM4(doLaIMS69b&Ymd^9r7M>k?c3GJYaFfk4`dNE_6% z>L73UukO8D%z~;{%b(YBZuo;smH}`vnAV~)-?#fBoSr7-Hd8vflLba)A6qGA=2}(; z%hcgL@&)QSPrut|HBuyrZ&iaOGRaTL+a9%RaqdDU1d>;hXO3Wyk>Ot)wfk4DOM=L~O3aSIPH5C+Zx1<&$e`4IISS+Th_H&ooR|cS&Z_ zvX!U4*V%fqQbjk;yeLQ}%?m+pg8|uTH^aVEIL*;zxv~ci8F~zL0*?*!YScb^uPYb* z$6{Fn0Q>-h9>0RJ)L<)TlAU<*ubMdpPb=>(1Ic0=%a>`#QFWVZgoJ)ft>?9+QJ|p!cJy<* z2^3{>eo^8oz8uj9nL#C-h97TbJkY*o+D{2?kLUoa3CJo0#V`Qc=Tp$k!Mnscqlj*;bv;4F-jdZDw!RD+ zdH{_cWsksoIq1m(U@;SQ=@tPZ|e?v~3F3a6iROCD5t&7_wBsmjaYOw$5( z9^F5kmkw$l7*H;=*5o_Ta2g-bY_BfyYsFYh8lpZ43@UWbQhhCheouK4PGj2kcseAc zHc`0XC(HGy8f$r`{N8rXZjiz}rNk4MU`%a?Ya(Mimi7x>?S2JQWsEaNkg%tUnwAw? z@b(;8P>gY(8%&H#ERHJ5=1i!LShwKF4;wNeYWS4qjJJE;JUVAG(T$?j7)10DkSVTA zCL|-AsYJWB3d{ZB%d`1#r$IwumfrXeC2y+&Uv}ZNZ$;?;1sg~EuO#fcBa*Gr#UL{D zW)e_C_SxXP$EVv{DbNIPLI3`Nc>q>xE)m?!*+&DV7c9#pTLqj`PxTz|80D7x8BI=Au2FWy)KzMNB`j-$ARMMf-cRHzWDeH#RpY) zn@L!P2-A8q^(Hk!YHIwrli21qCk`krtxABS03qLFNx)hhHyNjSz^_y({m=wUlL&d8 z1I(<^ks9BrDU^n7zz9fXp**#H?-E<>gq0IxRZ*HiI!5!9fs&0MXusKh!r8m0b+#J| zy|KQR7R^rX(bw^tbgGbzhnAD?Uj^vQt;xQ*lE6jLR`{K1OiVru&xsamxgl-zsa$?- zQmVcKwi-_(Xd%=7igbr?i7a?8487R$i`ciU0DX6RtAsqp_D47m387V;M z&JbTzhDXS$T~^VuvkJ=We1YUYjQ_v+S9M{m&QP4uoNs?Ng{%UJXQc^#8(h&2doICaor=M7V4H_g^&)Of{jkB%DGgBLzlRnF z?$N%n_qJIh%2xLK4tUkfpWKSgKRvxZ@SAvPpRoer$$=7%4_eoX+;Cq@m@rV9XCNZI zDVT^Bqyi^T-zDO_((96cS{b)@J}&yMdcwuPb=L%> zlSx;0Z(Pzxc&wt~l1*?4ovo#_0i9V16hWW#eFy62f%ctzuf)@f2Ci#I` zhlrY@zfA-h0HSbDxkxO0|M75vZgYKu`|fCT^)rP0R1pK`)(40+=G1tPQ17ITG|Jx1 zqy8U6gp&^OZa}95L9_xX*rPyMQOubs0Sm6AP`EI|;~3m%LU%~_H=z$t-7On9_zeLN zUU-~}qfe0&*YJ;AqAvv zlGqTkQ~}|DHm*WA#zz&5JBcI zP!${BNArex6{uBA2vDXLc_li{92EHE=c%@ZQWPv`^}yNI&tsFp;HmB4q-a6~O$W0J z*cVdnIV`lJ`|Ro1W?u#ZTvW=v-UZ8koF0l7`dq7rMYwrwRPL+B(qn`Dpwc8)4Gp0-wy*QO!Kmj#^ zATpKi;=?qfmSVk|6ffaTEJ1Vi9(+xS>;YE&si9HZicwKuqT$SeP+0V0T84!qCUa2h zAnfW$nfVB5meV6PCeKbv25ZahxCrAhui(wechJval$#;hAY>DZo#D`qhJ0b96akK! z$WFbCARYig-HvXCJNG<}S!ofxd;r`8d{wPcHPs?(e&ywv)Bt3Mw0# z_AuuGmIKfPfyFmG zs5D!ealOLg*@a3wsHrGS&0?hx(cdg9Uz|1uwE85>pM%m|$a)dT&k)QYlxxUCM58X1PwYKKvYNg@mP3T31;Zm+7&Q}0zvfzM_jAaQ>@sDprKu2`# zvcS8M=xrn~AdHH-hl;iNMZ(3YKAPkBg6g+t-_dBZ_A`Ykr)TO>_@ud&39rXY==>58 z3kK4*1#QjTNZip=bgo~MbTUeJ{66zcg-&f=q~H8v6H2M}c3KrcO2esPH_Wh->jcV~ zt}@dEK$EPxL_`3wf<=4%b^|){*RXdJ>kym^d@xx4x_*4t>E{lFc~Tq=fSE1(%Ft-b z2iwXj2O55@kz)UuwJNj8fbT6|1+~qzS}Vy!K$@cVEP69GfQJiPzac7ue(lQtLghJ6oS<2o@idE^ z8T^n=-umtn0*VLt5uzuGJBWTlN1+Vq+T)>7Q5QSUsHrNO;+I@N=W8kz4$cdp@NSlu z)4{vk;aN!ZlPsYNcLuO(ONDY_NaqBATnuZXKU1^l?##kUV!`e z;=pa9`(hd%*h`A{&b$k3yK=Nm9LoHDwNwK6aU5pO5CgFnm!s_Ax#J~-(xD^7>0?ja zD{u)ECK!H)AIFx8V>RBHWa%EPu|Z0)mmB2~md}Ldg!!6gFO?FDy2N7|b%a_8SVCV% zp--@s)uRY2hoM7UaN+Q8t}z>n5+p(mW2((3vt^*&!)rAL;eZ0POXX>JDWbTkf25f8 zauF%5U+J^o+$A|4`=SXTAt8cP=bbnH(P}wMj?cdbObE4Z(kPJ_X(00}p@@J0|9FP) zhL9EUs<&2ch#*DC$tN95sP|AgS)IPb*<$J;tkjRkDOj#ZXY7Rw5lmI0LuDW%7pjVyRf--6h$1r~M;<=5(}UNY2qO=}8U z?eg1X9xJ<(Ffmh-DX=A`mu9SdnZEEi`AHMYJMvlVWLCAeNK$6!7RxAkvy0w&6J>)w zcwspi`k^nKEsS#o*^06EzD2sZ_H`MrlIXKZ%<5m{Eo2*dC*VyEnMw*Wx-2>O*xS07 zh{PXIBmI4h{X^5418I3%$E1V8%*3upT7zHZ&h`wi*JJ>Y2-R#U;kC{-bL+X?Mup>{ zk`dX#pW%?oyuR=nU6$A_3MQr;(kr0aLpZ-eC!W$uh@>&)Uiz0vE;vXD)XIYgI`GXl zQp&gguMwbYjgTzz0`sFU`>O;9IfzuYq~xqPPb08v>cySNZvk#<5cVinVHA#?lns>X zGpC5>si-2+aKywtP3$+{PYJOoV*v4_M}Gb5Dd{;PpFYXCe~lIAX?#1#;>|2|?`JaP zIA}AO?Xrk(2?+txDQVjb_KF5hMzV`yC96Tfx=buU|JV zo(zj`LpbR6l0`{E+d7owDCW)iJ~m+F#XumSvk2A zwLb_Wiz4JyNlx&M#MqD2O`<;XE~N`kcxY_&YN|*0E60j?fEpFWuGOWsiX3&N8IvYoejuQCWteX%lVZ`p(g zS(Qph5N^813Jx{V_zdb9Nh)CLK#IZ1|qSNKYV;! zZlg*F@=TQ-a2~B6C9s{zrJ*d3NMor^4y?Ojo~Q>Xru zJzo6-WobE7-wpf*Dof9Q9*(kbKnO_7c3oSiE2{FBwNcIk?iY5znJA$Uc$Zy97Le0_ z>=Pi8{j>>bN$}}bnMNWp;uhv0Eiq4w$v@Pr>-DVwlF;WO>*W?37CemozLw#o1)X>^ zdxx&st9rZh#;^-2LdaAF1Owl~UAP1HQIm-JfW6_USt_+y86@i&PCB82aS*F`2Qe6k zRpy(X4{?zQ7nhnoEsj{MKeA5UVxB~L;)d*Sq^(>GsxFtO?zh0-gsvBLXg z1(3AjU&1_^u>#&#pNq!yNJX=lcBT4S;B;$$a{9k9jwn<|zr=F;jG*)dtG@T{xyM=H z>ELBNH9st@%XP=t7{I)C-`CmsIU!YgKu?*#H@8LwuZ_0k+`YMESHCAK(9ODVZ-cE2bbgVolWU2w zf?|YH{`56;wHCo$s@*fhndL-5T^0U;TKD6NrR+5s*!u_I7T@VZ{zqP6_jxhhzkLrK z5B~$=uTYDXKMmCKsu5NsZ;8$Nbk(LkVKNP^CUE=%dXRZlFG0r}UT~fXi|UnSag3y< zk_dvH7Ch!q?L)*+_8mSNy{HN4Q;j@8&NNJRnF*T;kp7m!-*{S{uySl=+XMf(< zQ@9EX9jbcZbrN{?>A7V5S{-Q-F=if0JZ$>4i{+vaI$r0=$BY-rCk3=Vt-F9cX;tH= zEN9d#;^%|U?w2L{f6pQMl+I_Mo3iAN&MhpnYQ$A6yJ_tRLdxRc6(VkB=5EIi>@QfQ z$cPv!Ec3svRo+E*4ujr^=qXEOt~C+%Az}A;5#)|U_j5{pk$=uq{7 zd4C9N<3Wq=4$QA~_0)L4tOJL=Fv$*8!qUR1y6}{K&wM8U;nvkv54rW}9TL%zSA~kj z_=qb}5}1$VO?)?JWDcr!UQwduZhfV{9VG@fO9aWlO<+wn6K5D0A#3;Tgh6BZt)&}FAQg+<~NOneoz9(hY5ouh5k#949dc# zg6=-l3UVoPnrf`tHDxT*s#=NsG1xKa*mXB31>+)SeZYp1a`V#65{!Vj6N5Y~#`_>> zo(9^Jksp~EppK^K415T(pB2Ui1egPVBl%-LiQ&1D(~RHvnt+K{-QtBk+8&XAMj_%~TnZvisZ z$B;?{#zbzVrl*W4Si zgx=!366D|Wfwz3*zePoF%^C#ng%CXeAHbrw+R8rIVVX2q4#ZG|Wxwy1IQcemeVH`0 z&N|LP6X~DXRP>_O#JqA${-+tt1NJHrwi`$v5MIb4O@>MO$XJ_ZDY_-FvtBw*3O~ji z>W|L8r6l4bI>e@}hCpdO_LZdIrmKL7X@H;EwUnc$3xBjPq2aa@2bW>$@JWg86=uVC za2kz3Ggl2p?px-Pb!0fJ&s-1L*>G}eJ1oFe2OSde?{sA@cT0Gx(QGm^@(2esPontF zot*j^gR>!E#<<|WG;n*lJYAd6)844v>0>j84@av+XDZ>t!^f|U>eKTOFM$E`3k|Lh z8OI!mIJ0k~C}QE5o@vP|U>B$Fu0+=d4 zEKg8k9oIvH`0IM+%CvV|fyxhg^_dxXINA9rmb9y5WXdQGw&ik<{)1+fC86hR=$Ko_ z!L(KBuxH}uF*&ms_=_i3uZ8qS22!+DOcO<;*D=9UKxh0`3bDG~(hZ} z`gz2lJ4Nz`60bq=jV|p+5hxzRVNu#Kfc@0=)4#Ppg$<*VUL9ysZasbFMHgcR@CmWO ziD<$l!7dptRs6C&W25t3Oxur1ew@-x{KY5){dAb1>{zLWGAU`?% zJ^3@(xm!m$ICv`Dvqc~5M9pR+BSHIQXW<(vKy4>k*&F_7E^;sjM%?zw(npT^URF#> zUOvjReQc8wKUx&}Wk&0}v%Y2+a<^woBTmj=N9O|OfD_v^0~g8T!YwfEMHsW`2qz## z#IM~TRkS6j5Ie)BLxB9sZ_JT7%=2g`KTf8D1SQ0KC!+A!8F7P8Y%gFE&w|~KU=eOQ9RE%KNHqb4L_ElI^8n|2{lut{umItsbc^^G+rFG~u z(bJy(#%oRfNc#6ifFRV@i<4#{*{Klj)-fPn|}4C7>ZGtRhq${{2mYj17% znj7O=GJ=U(%|$jTKxbDz0Y01Fv*ONBxa9%!N3NW7@{pJ|$C9S30Fg#IbX1Cov&2*x zL`d&m*1ZaayyB(7>GpMauTGsA_&C8w^N|qIExVKsjiWx?hFaMfdp)IVJ|WB69#(|-1Ozu1FhQ!@oG`eQ z8$D|D`E;gD8_jHF2G|77yZZNJjMb%zy@;zoB3x*@o@QRTY@Lu(`r7FC^)?voqrTe7 zH@)Z>q3LePM11JUu~)VPrae7F501!0g*)|WVJ%)1QF7cagvlQZd_qtq0t{6@LFD_a zJFf@GSmi*FCA}R=voE0**1zY-I`awzmre9XpLijxrj;QHvR6DR&$!q}00w`D^^8x4 za*}ZAcn#;%>&HyC!=bUub4rI8Kz7|JG!R zQT;%^xJ%dpgwD=!*idMLkwh7(KW$35(_@Pe+k7qB4&sE^W{LtYD0-DyB^iIgH2pJ) zaR^JQG|iA1j+^z#e~T+18Br+QPzLo-12`WI z4TY5}Nt<5Q%?529b|yHZaWM0t!Cu7IQbQig1+Bf<%|8kmP=coeoPYd2K0saCUt%!= z0zOH&)`KuT*T^Jelo~dc{q~68Q$dQBskj3f^iuC{jq2E*sZgtUy9mPixwFf^9U zoC^zPxNnexLoa}IN^Nx$q$d+PsUAB1pWiGY>{l+(z(u4*t zyL8uKDEEB*(KZmRLs_P zKwt=!m_j}X8Gj8aJk0F0SE8xC+MSKVF*hFlG(54DE6-(>Y2yDx;fC4o!`#1&)YG}y zG}w(}tV`9Q5|jxxEkRwwtO?=Cl0o|2zf^Rc+|HCZGjwoo3?|g{X`pCnl0dScP{uj-kUUp(AkWZB_qc4+u|FU`wsREX}&c1rzWPiUR+r+tyiG{i2*@_Y;d|9x@7r(e$N6 z;RJu8q;(uS_ZG5^9duiftMId%<@xNqIl1`f37PvYb#A3?g|F;(ntab$Rtf!_{7L?V zFZ{xk`RXNzs%yyF9hY~9=WT2Pbjthi+`@{k@<=GPyx9D5kTn8$EGC3E9b1ciGSOG; z1C{m-8}#EJ%J!E+S{@$5s^XXerPU z7qi#4Uk`zY-tN-!KGXiwimKiK(pZg}{7uS(1qt7!a3ayaUa6ciQMqWYnOrgo$HNk+&aCiV5|KE&FrX$&DbCmqHSZejr1I3>uFR+z-EiniA_XxOg zI2V{{whHZn!D58!{2>5|!giyz+{$O(5GY}^s=CzD#G&uW{gP|Kd1>*#=}o3Xy<0_ z$IXP@F8A1f-eJnuvUWpMp1G!wq4Mh)=H!6G5LLKo`Zbg5titzqoPA8m02*8?RVh(@ zYH&%dLfJyp<0k~18X}H3eQb(JQXzR<7)i;gXH6DTu(2qH=&_PDOO$UpoiwgbHJ&DH zqF<6X8!UaWQdeFm**2@2@v>KANb;6Mcu^`mx#6&fa;;pAw%CovT|{I&tBLLWE)b?p zwx4F(5e>YO0OtnSUz10$IRdoe-Q)LNM*;FBq7AbfdZ7sTMZ&C-=@z6w6p~Rj(-$rC$7n zd9;8#^OG9f&m6dUvC+PutK*AeR253YB9%rSz&JF?2gSW_-@YfyIGua zE2ATI&JYFt($XxB)0nlJudmdsUVLW&hH~SZ%`0ifiXH~%d|`c7{x?c49hrXzyzCc} zf8ZYdY^`6r?NIYI;W>8RH-UldmckNqn%t8NKfuX3CSjT~)1OY^|9D~s0Og$~dDN7V zdE|;_3x~Zn`?Q~WC14jJK8D6mi8%IdyH5J8(VLnEi`G-xuz@$+oS|&$j&d+cH{Zgt zzy2Qi%@vs^aDdQ6v1u&)r&`jiioe)4s()uHy|bf?)XyUn3PYYgimv?bd3V7=P1*C; za@}!anFw{_zV%7AGer=s*BhE5^^Gfqcv$}Ne=d6&!uN>D0Q&A5R{K}3&&g3?H@7=@ z<(Ej(k&hVQu#PSTTZiZD3)gch+-13f!_hlW#>3o0|dZ>JOrksGC;tF51Uhl$!b_7AsIuIIeCC zW{-7~iTqGQV#9PPWQHHlHuOtIDwSXDHw9*Yqcn{Db}`+HX|RlSpB6kubB>}nu@6RU zv?J(u!Q&(M!=c5^m^1~vSfyA1kaP|kCPM}VqepywebuxRB~?>w6x^EpnxNi$Im|P7 zE@P?1;q4Eao(eo*<3v@!N-alM3<;~5r1B{wQGf39L()yskq?1Jol1nEKO)K;t~s4V zDj=&G^fA2+2Y_ReKYvZ7U~)0jV%n|CohPto5<7a5j^09Xms(%R7uGXTfYq|VA`~}U z4R85?Fw?d2W=1WPQnWpbM9R~m){7X9)?Di zwkGe8l;tm5BMAIdUZ~&wL&IADOHwqGMt3a8-dnDyNyioAX#F1Ea}kim(h;W{xyv$- zCd2GDr*7n-x$8!xBcFzw)g*1uv;#`DUo=mq>@fF4Io>X@Eyff2! zy#UK_qgn+lH8$UeZ~@wG?2zrJEat$9ttC`^g4eIyX!TLW5grkJ5Ps|OuZlUshLI9T z38ikrCo4qHAe!RJ;m3*@5~ZW6kdF=9a+=Exx1x1Imk3b^lT`vs4x2{xdw5ov$G>V| z>sih{_wgqwVKr3kL*;Ru9zaucq`B=TTUZL2qiIMAI9=4uw2%(+8#E%75z8c^oL6S( zHk9-Gw4lUNc1imV{020Qj+zz%O6sVKm@g>a-2m%Mo_tKKml4XSHV;^fGG*)MIncW( z4RJD=&7Kv`LIMHVft)HG`+vdmjkS)%bakEKlfchgrAj}$QgWPhxS%UFc#buI0yZap{tHikd`$Mfn`bdkoE4l+ z%NzoX*}{=ABAO&AYIskUmE(x!Oi6e1{JsexonVl??xwGyjnnTZjN=!vAwEU$Hz+h70QDJh!{H9Z7*HBy3ve6!e+PJM*g6`xb>7rsY2UL>>6*8#LZuirP_jfMXQ%` z20a$+f?61xY}WTR_b<7t)h5P!!0U7|Hh35NJ8FN(OoTo`DRegn`PM8OXwEqIzZ(vh ztPlYgd`$PTwoG$^$*)~J>xJ$CMeJ_)H2^I|bulQ}Et=bF-V$w6?v?h*(C%c?MuAG@ z>0VAKc^V5I;b9WeLk`F0>6kh+I`r$J5Wjy+Kwj|B^vA^f zxG5x=7_Jq7F944v!i>%!rLc2!Ku9;aLIg0uj?cvc(U-kyxm}Sv0fa4nu>}M`hqFxxGRU1Cz-z^nQR!htb5V** z&N^Kfv5JmVWz@ZgO>X6wM243zA|_ZF+NrDC0JX&Pg{OL`YWgPF{Mf@t{K zQh_=#p;eru?}E)^nu||ZsLgsz67w=%&1K39#HHS;+mYWa&LHB}WTACfDKlPG;YP`GWw5W;mu~ z!i4QbZI3x)*{okl4!X@t3UoPL>lh{8N^hcF>aFw}on^eTSBAWGx88aA%wb;aB=ZcD zwLqM7$>5TAQf?m4yEzd~DPeA-e$+l~6hxk^=ACM+=|i89){mR?;QUO?Od}XW?>~yf zxPRe9AmF3guXZ_s@C{+OoybWpU*h7~4zI}{ADh!vNUbu+k`S0Hq!0Y)xCu-_;Nm1k zTY&J9#{KWv`TRn-LOXP6ZaY>1B321IFM9RgYQZC$i!XfEe8<3Uooq0^~?W zi_j-wTVwZN?^w~~R>>+et0IsR_Me58`3}(#OX9$li{N_(`AZ5=CXb*j-UfwRlc%li0{-Lw0k;jG$^h{QLAKoI zNI??8Q&&4~#ACE^65Zs?n`KS}Jcj13SZk(Qd+FC~Qgf&LhJ(?;)=yrFB>Fg_hRI6c zXs{T&g4(BHew1n`VS%wH1;dMdn2X!w=ee=qO)&E$TshKMeNKOAP0VMjYb2PqZ|~{j z{S~E_&07wO5J^ZFvrtjmg*m5IAcbXcZ+q$R1tL&){6V^+h0FWJJh*IyXS^7_v|yVO zkil;#X(+eRX{pSmaj^7J&H3x*+O9Tj1)0X>O*4uJ*l=?GjpDb$^piETOcN@&Hr=Dl z(oguVyoPs$wP@z@3n1c{4npY!#K`A#kA(@xQS7G`KMWF|Lu2__XYsaQkZ{QyQ#^6& z@==Osn}&m}24p)doyq!ww-WB>Lu1v0+1tZdN(tLsSqLiQj*BQ-PhPuYRlaCm{Xgoh zrb@qrwv|U`S3zT+s&^b9GGQ=G{mZNoy+bwgyn>$vi!LV;Z}d**PgMo}Ov>**0R9Kj z^;-Q8C(pEw5J3rBea@CQ%#8m`ytqi`MkFVRCGM{cy$= z(w@eB7F3i&+!BxGrZ+r3=_I;cknE6*#o1tGVb_>&KYp5UagI85&)^2f>&4|vLbuaX z$7$#j;G=aC5tv~Ht)sEJr7FRw2uZ4FEA~4x^iRtBR|^Z_@zdr2)y-YD8nALH{HRf{ zDbdvV$o9`23JB+xrO7`zk4O}o5@+8=BW9)_K_KhTlc2;3F9@wpqbqRt8hiwZydn=; zWtv;1>@gzmdKW+DGmvwl3{Gt6$n*^a|@DN4MvfYqqD)yt%|P%25kA1g0hdX ziBtyA=hd49SI?gPpnty-wN0iyB8sLiN5#MO*6Ib%!iIwSlMq%Q3rnabdsM68?(sfdZNU8OMlc#VaKQ)eO5rdV zhAL!R!3>yHt}unI*wXzb|LXj)$`6acKSMEAZ34WbMqGrE3S=Pfm42Tf7T@d0wosav zSJ284*-Joio-@B5bha#}NIr%P6J0_#1NvIcrc*j!gk`1H?F`e|WTZlc>-+N!FQ2j`?(vk360m?{9aS46DW6<)lkz5MB4d_dEt2MS z(2x~rp<0+X6U!#)i+iq$`QmR=-Lk2=^gZ~pbHq=11P;P{wc=r{MX@SI=6Fm&S8X($Q}ByX8HQxz z9A1dRWoc3_RQVn=fY7C`bclr8RX|<0x_d^vr)|)WWm7c7rHwtCe^_pSIB520 z8&n|8Hjq=5iJO5paj^u9GpG=NibI;Pt^p^1=uMh7KvU}O#Z&`T;1r{+_3oYz4w>-J zthSiic8e+2&sB#86_eoRh$uTGOy&w~Vf~_D=a%Tyu+_18e$(+l(1U`|`Ws}+ni{-c zx=ufLLSN2_o1!1l4-#B93To~z%&~yTfeoMIcL0d$7s*?|wHx;tyaQ-=3TG{fHD`-m zdAx_gd1?IunxzA1S0oeqv9q znh2{>gYEcjM^q!~yn1ysrydcL+iTI-Bt%4DFvilu8PBov0?avcu1- zKojXYn7#@7qqPc%Wb}f>w>+yDOree;!Z>4zlBa&B3tQt?C3L&i%>aW&-5}kYr`haf z0#En==^FOn&O1?Iq1w)LQ)&!#HBEg(FAnSe2)u1i{vu>HeVDNO6UoF^7secGb=2F~ z5TXn_uPl#g=%jfjO-_3k$So*6(Pq?!5G!L`Z~m)+`7W-s4TDFKZ|Qa!od7o)H~;EW zAv@X&*DYw#+4c9V%cg!Rl$8Y+V~^K9bwrJZ=ZI zkQ9B}YiE+jLHcjc61~i@dxi^D%h0iz{rRF`I-OF32PA`luY5qi8jOAlGc^a4q$29J z?wsdpzGJt}jFk6*s*Aev@a;@NE_?7!5r-r}=O{`X45n-LtegIpp5z_9MXNCOmW`Uh zi`Vj~wysMdod!a_lj}H%1&tP{+bqHrsmFOuYsr7FY{itU|0Iv@>C&tmr$+C)xC8&G4L;D8l_O!Ch!pEzyZ8O3C|;C|2XhH zXgX9h1uU?5>v3`r27TGmYirHXV_BmcEE5#f9MMQfsn(6FY9&3lky+((DTzqcp$`}C zaVlcA;h-2lk@og(#nwz!zHLZj6^Fm0`XTaFoA7yN^K7<0 zdE$mv=En_cO|ezUYP$2H9}aQ`P&?Ps%TVH$9D%Huo7z}BKnNX$mvag_cJibDI&o_s z_g863ms5(y+caDAn{oy@`pu{|wHb<{HPyl22O`1MpYGXWLHg~>i3kn$?Fe;aq4w#3 zj^Zr=)cX--Mt`3!?K}+J&MQ5m0YuZ*e==dy3c~%xdAv)dXF}k+1P{ars#DmS3<4g6 zH>Gm<_@jd7)1(ZW;zG#g#-LCp!mW-$3nnX&=i!y>fQy=&C}$@w)KGIamfY?rRoo{b zY41=YDpMtBUpi)lG2IUqfXXEy&XhO2m}f9<1$Uq2XSjE&M{;+> z0bkOMH8o)s)*+mz+qO5pQ$!-ulsLiFaXlWS;_B zMnClOaWq#9ChT&`D?GZbL!59%k18JzX&0FdgZE-6LCj@P=KV=cgzp=Ir1}_a&uill$U&i)-=Yz-d2v;)FkKqEKA6CnHaTS{-%yi zHMWTbRNBRuT^Fjr1go)%e5(Lu^klBZo(cS8-q&Iu@f;oZ6%M2|JU(XsBdeQnKX?cu z9=Bi>)+H^^1zGOb7ccO?|Gs7|RW&eO3G6V;8k;yMu!^41hCPMQ36X;8t333sr^*Fr z0*!=y)Kj3_T^(7VyHFbb*eJWfdibDK`AsOV8!!HcwLl!7zyOnnhRip&hA*nL9_*c& z=>tKIMFg1;cG~Cf*J9hOq1h;B){uvVF>Xy1K+vTsaEO&`Pn9%K*m?{-lPt5Qx;ZTO z)u9ZPiy0g!C$;KLfJu$DXB@{6G+3J%u`#tKA4p3%U$z2;-sBZ#AtNBRTR`N976rjjs}k*a&ka^%7s+O zE-he#M9omPsHvN*bFzu$2K|V|-;!THLuj^gR#eXro$rp!t}SKkkJ*+#!c5*#+T957 z9VuL#n1XIC8N+F)Kjz{(gxIiXCNaNdC`1BCDwQ> z?=i!|oW2*ivZVwOnG9RndtglYDVDq!-BvOkyGphfuS(ve-sC8AG1}IXGkN<=s z!pe-0e$tAzlA+1!5~DEf<|*Hwe5w|S?SD%z-3FI?mA$Cl`~k9i$V%gT{E?6{4jfgF z)ri&8({_~@L#}bCBRJPhW4EAQHK+y3g95x6EVBUbJFUOnKz}N1IU68;W}88|UGSI_ z>J!ioj9cuj;QH3EE&Sac{$c^xkrGEL4B~OT^44igVtpr_>q9#EXX662n_~Mci#I)a zqrkmr{H35>|EEY>0;P-$))RH10U6&67J7P=pI3x#Gy>IxZj+iAM-I$C9jN6>aKDUD zr2NA@k&KUv^_c0yKN5|Ypu?V|KP^I4bYsj5L4LA_;bJhe>JZ?HF=X7Y1in2RKY^Q_ z3#qjsvs7C>PoqS1cPi-vs91vEHdI|5D-W)c2FS{y`%*h;n<`4#HqDK-`pplc`XM45Y| z#ze(%%)(t9_BlPPR=AJn*A>Z357cf+N<7Jr;|tsVNd#hOee5I#1e=Yi(p3wS~nz%BKr6@7?}i3(bD1|1vp|g&^qz!e(&L zxED!6g>?*lS6~3SFyy`;*G0L>0m=4df#g*7M&yhD6m*F9K!e_Dc}Vw|?Mg(b*F8pk z>|%?@#(cq7K%^DyJPCZhwVqA+eXfxOxlCgFsd(2GUnm^UR{-5ZI%T;P}=iAB-#Lc2})_Uu`F__|q zCyFhK*+bhaYI(*S)qzQk1Y#fr*Hc-Z2V|TVVNTvhWomMZGW$}|Cb(x?>b3|3M)N>C zh{HOHG>5gNe|(d>-oQrv)e0z>aPFuC>YtA6>nL}QL76jj(=|HsAf{=?DO6CB857Fp z`GMVB0%`vp%gLSI!hhS(?gb8sYOa~-69t}HWuEapWRf!g2a3=c7^7Pf)?EdZe*d2Cs&cWas%b@d(>8gV?kCS zH>FmZ?@`6EO|}CVPE;ZQ2{!p@S?MgW7UmP2$)@&O#EaE^eoS zlN`r)TVF4yMdcRY7{*tqMa`#3uVe|Uiun3-cq{%4aNeU&vSZ^7mY66^k6iIzH2Tm# z0uQ#ozm?E?dWS){Yw~R>Vh%2epPyAFR?_R^io#cJZlf0(3Hjg=%C8Faa7?d?VKr!u z8zjUfdZ24^`&v93WnR;&Qv2YS2;OHIiGqb$QMI=g|NK=(#VeJA9cTf>&mcOLw<+_3 zv6HnGYz`%%1yVmGKyY51E;Fn(LEu%dxJhe-ovEQvkfZ*UX?;4v3)-!Iv`Woe1M>Tm zk^dt7BKZB-CX^J}S(OL@)w}1EG zbVUK~7xq*Q050=(*U0AMi_^Y2UOL)A#L-zM&znP^GB?5DJFi_SH@grhU6IKY`}eia z#z@X#aj{iX07mYh-UQZ{o~2EIb0HW!#4hlne9457rNveNAk<>&lq9aAg)GF z4j{ilh9Yu1_oO7mK#xA-5b6KN;ce{=Wx>*Bmm|YZn01+5OSm@;*n{qvlT6n#uw!b@ zn1=GSl~i^-*XdO>M5cX%uOP!@ShH|;AKMb1>sIz{FQN3kNZAAl3ZWEy+D^Q9D-EhY z3KU36xi2r`_vlDQ=R3q{e-NS$E%w64!hX*V_Hc@X=NA9{C7Ur*pXcuJSfNf}d<2CL zBZtFZ4{Ph~<4WQS6~T#VCRfM$+jBx2g5MFxaqKRZ)OQ(F?FL4qMmqGkEhhJ$jn8h2 z%O)iT{%VBSXzOD(m9pJ}%hFB}q@86rH!Z_x3``<@yZNtY+s*QSMDiOw`29!PWv$QEMCmsCJ&nA*@Tn4-q?y z&=@QR-uhI>WO=GJDe+%7UzzippmqNi!3&xgGx{a`RbDI7tE`(3ybL;FbRaJ|C}_KM zntxv8umsb?E_g&g>iOd{NOFSyqlVXa)hnH7R!sd+5>HUsK8(A zn+bLxhKocAi?1^A7JS1x`sxDvO|?JYLc<$4COgqsgz4`9u9_N7W^w4yh>{RZ3?6zn z>Kh5Ci>*<>R0$*`M=cZ1_-@m2j0iURo`RpPb7>fCuQ(AS?Z5**K%A9@oP< zfE%qy-i@pKAoP@NuF5FbZ2n*fRSOa8xmo8{xG9Z}$+LwrDz#uz<728k);vBU?afwmfML?58~P5!F)AU4T<*5g+N5f+%J&LpMBA> z>`jAr=ERs0N*`t*^3z5cUWYzG_SVjDxU4v0`1!}Ui*;{FR)|0vJ&05Uj6_L0hkF^^ zGMu~0WRpr#*bzuK10E87R=rkv63ozTH2lWEZo;@o4j%VhID=8UT%gJCkXkI+O0%pQ zXBsTP?--}a^5Yqv-C1xNzYK^TC(p#44WSd=6izOYWGnq)-nk1-Ij}rTpMEKR{FJv~ znOx(O!_I1XC~T-tVBLifzgjrW(8`2FxI(|bJC%1TMTfK@Oy@S!wrBeJh3XP@)%wLqYVQfDNRKB0*MygN zA~|mms6-O*U+rsr;ltTaPxn9(tfBcNo(m34cF*u`clV55jr9*&g zU4JZi0p|?Wq)o^@V5^T5VL#46+X^<|1a)=tyr;J&*H1@A5n2OSjuM&`aAj<6&JEYg z7x~6?K;#|G@VAj5t+VXQfwR}khy&#Pjnj3tnfjWs9=z(@WT=Zvk-C(8`8bQi|R#hxUkT~NDt#eheDm!s;cOQ8U znmS6$EX_(-8sBQq96hx&Brx&sC_#(VKg(uvH27kKzq;of|ZC)K%JPK{44^|mjW>56_AcQ1ubWjr^qse=Se}5p+Lsu&J9c<~vjT}= zOD81+d70(_MxqnTyZ+#LkDk=P&dXQ9vzAU4>Kg#J)n65=f3b%h_?@Z!C&)k~5K7;! zi=Le=RH1|`%D)8NaL+BDyvwwxw?{jn1w165WyUSeYoFt2P`OAl>w0qZsqA?`cXz+r zaE3yIZkP{Y#nT`w==RKTBFp+|TZj4qBR5Si825z}{5y*uU<2D%it(^c8@ zC4npnvizr$rS`NPaHfyNemo)-ia23b+?3cY;kt^9pW& zC_m@iYyrA3Z4|F#< z9h+Ud;7aeMmF=cQrme>@E z9zinpPDjT89jsowWaVJhRQ(PPA$ldmZ&i}>GfyhM+Oi9F+{k`M<2P>8dKhRtiXUaO zf;FwTTM(;n*%->bhUt zZ%@|lX;r42ahbC3#H;><$IW9YW#8n3Pj4^L3`N4yFD{mq@Yb|!cc7o$u^#8QBEY;* z|L)}t|Aw8s8>fe`TSO<5BhJ@T-gX@LTs=~57rhljPq$B-H!B2LNl-=!+H01GG``|bHyE+7Aiin6uH{WdiAU4z2a6tg zf`n;m`hg}$Sn!eU=RF-G*UgEmKbW7ofO_%cW2xCOC2g6T-z8!tKpsFEppU!n3&J^? zrJ>NJZ87_}LH*ABgCk&CK-4v*M(J_CGYz#S)cY1Bb`KJ}#ZurwNrl;YQvy!(m&-a0 zUOF-v9Tmtgc0@kch;bOGb^Jm@V7!Y&*}*j5!YXE`0eiH~@=SXlS#<}&t=?@{T9*W= z5<(ij`kKc+XC&rG-0QkdM$P{V31Do!p278c&{Q+oN_dHO| zTzN4&7Y^XM7PhNetnH`u&=HU>87B zq0YAr-T*Gf5#>k5&ip9n7nb!ps9?m06}!t|ErU2I)l1EZ_7oHSg3n@(k_CI79i|9# zbR;QaJ#0Xd16T&`#OrPY*P@3#1#3{nQdEnTmOhnIepzTH8T0u}T3naiY*$lr1cgc! z3D~N6!TMouPtTWdA#O+gKmu{rA+K3_B}_T}&l~dCjIZPl;G(IOc#*n{6Tb|2cP{6X ztuA0dvgwG?IaX;1G<{Le=~iE{RAP68{oy4iAkw9R+M~1>go;swU8n*$WT6tD4~bBq^-!J#RSl$kSaagd06RUEPT0;ao2 zqj=r#HA+IiyeQXJs*+H*>VNJ@J3D83v=Gj<2zRLgto|xN7HFr6Q!2z>gK@95S`~hb zz&Xk@51|@>X6b&zWW^aiswJlVaK=nust)eM@&muX7oS^#4B2?!HHr(| zhJjl2%pMRbh%L%-SEMn!jO&HK(a$&Vv!42gPM0Qs<0q!ACh@mMt-6Vwhb^TE}g%AsD`W^16O zhOhk}xe|J;YU1rgq^Przw42{#Xtn7PDK;uW>?To zOEj;QA0=3lhJdOMj7Ufmj#YGNOl+TChUnOwHt0JDtW@F}SgR?=VJa}~ETK*KHJ|Uh zH`Uo!J2;BcNOo7j@f#U-^K!c|o!1(=qnQ{6M(lUMZ`vJ?Dn+~+4P@KCIML4x_+5OL zre{?m4;U5#4;=DtdwE=#&O^;RD!kmz9pD9kca$PJKAs#@gu0qW)p}%cpDhq1Za}7n zZv-?T3z6a_+UF{T{YXJ*{d&7t+Kdv9MKq&nHEZviHFT{v#Q@4!6~aQ=X?V7iz4E+x zfM}QeR{<-WIdqIvJ*Rn1vLc2s=o){rq~A%eJF5#bJ{#*| zWiso=)!+obn%nWbG4Lse9@l2?fCy6X5(3Ztj?Xx%jLA8=kq@E8Q>@00+gx|6aeja8 zp}^0H0R{(o6*bvjBUvTv4&?UE#bI9&Lb7z&Yoa0~8do)va&GY>r4;L-%(Xbq<)12r zGcd;#0G2jpa3jw0-ed!Z2;B z#*GzF;io?kl%YzWW7mVc&QbiC{u;A#g|#v5hB$Y7+5eXk&UVF`CjWuL8jKqrY?EoM z9Pvc=Dm^U>u_ij#T8`6jp+&v2*YR-mF zgM=e8Vo)S+B*BnI%NX8Iv}~s8OHev(q}d}3-vnlF%W$1SaDRR`<78L z6_AY>tqQ4Eq*nHw1czCi(`@><;yw;=<%kCW|tKl(#ID-<@nDg@~!JQ>(H_W-A|fy0dbu~rWJ z%Hf+7N$~WvRl$`ym-#sC1-(TA$-rowy)L&`j>5~1ge*sUCfS`YAUYx6sF{SRUe9M@ zeoU;EW_?8E`1O#QIfE@agy~sd4H&H@pXVwQ`jDb1v}t&vGS~@ufw-oK^`7Dey4+ut z5lHVSxy+5E0@=pij`hi{)NXqPUwXwt=p!~;=`UC@aW>I%I&HkQt+m)I2i-$qC^nBc zaBc1MUXje0HdWDkw!wXdTN;@6f{q0y^NGn$H=ChD;1ktEh7?cH5AYB#*l=(S0*exr zc!LF73}-NclCS`^P?f73VE#kAK96z#c(&PV48@t#Wl*~IL$4w58Kv;$hCr_fS{Eya zd75@+rMi;Pr_6T6|C-%@Dach!%&a)b3XAHrY46A5JK8&Ec1HkUNOUsmrd zyB#IkXv7z^cZJ|U5^Zwk+1|gtAoP0|3i?Hj{M&$=eyux%3|~FL&2Rwa*3t&#>QAQj zC)A~un|uOjz*XURF;aweGLJ6JJN^ioMaC4lh5YtmML{(UfxDu0m1no;2TdcZkyg}* zRBe}W8@6O2jt(6tT7!L;$uP?KLG zvv8C$c_}GPl;hf;5bdG~BUOWR2#k#scaUAPT(a9s3b2l?_gBQY@xOhsGpc&ldD*%R zOF;t=#T1=#xc-eEI$~BANW^yq6+9x0X>&qJHW|LWhWU+izTMKW^rluF;H~vhQnU>ggnuk`;3KXh%Bra*>tP=y36 z5C95j+hoHFy}3qd88W0c`N0)tf5Vy}uoS3eQtaj69XtACUf)|;{ZPnlKkUKCX+_lJ zxJ|t$qT$-kG4n+b%N1c%j=~s1#La)^SbM)(jRu*eabJ%T7vw5bJ1Yg#6#vC|g$fqe8kFXBfYKA~5{6FodrUv|L2K^r-t;2BD9X?XA7Xod7X zm5}DDMXQzvGW176Z8)v-bG$e7goA2PYI`@4**Uu1QtKd)Ib<(cs{wrn{=l#bf5nrq zuDDX-Uo&`%FIq}<1X$j>(kgI|!8L}h9qSVA`;33SYhJKXh*OO0QGzD1iQLaj(4Q{r z8Mq1v2qg$lad$$pX(q}zNj2pdHu=*kYK_Os|Il4H7G{rPO^0q)lneTBDwR2$8;H8i za*>3 z(5LzGE+YlH3g@j+Y2I!De`Z-pnA&Y!_C)AJJqUuxGsLB?eOv=FjwL@%I9Ssact&f~ z75gZ;iRtDYG1e-p4>gXcsb5z=KF@go_MZ<4NG#klFikdING;K0g(1B0@1V0biLFAvo>*kc9a44 zE1R^wGMn(*A)33JSLo!<4A2_X1vl^V!Q}TjF^B>c<)wXzQYxYZA+9JF8D;h-_G2$B z9aopLnk2`t_T;A^)v4lvJs!yJT%oe2=}APWyOa{~J)#}@vmuI;p$x5`5va=N8c$pj z+$_d@su_Ul*`&!eCRCyt3KadCcs$fCKYyC=>-I|23d8y(NHd_*uBAl^#8!vKeJeyF ze#KKsj=R3O#sM)tNZa|WHZV$kDht#D)U%BD22xV(4U=M#jt}B%}}!%>l*~;w1;P$@C;`QepV+L zu-EI4+HM@G4j@yJ&>m+2zywZanG^wH{?iCt^wgl1xw(2ErE5ho;yZwTGhx2BAoA8? zyBY4j;#j$IfqmlfqheI-0O=3n;;9fZIMjygf8TtOV~xfO;y1Gg6nmgmJCZ^FByrB& z>t5>c4eZm?*X$9*we@h4Vdc^bs!!;35T)ld4azKz9-H6Hc`~y~L7&d^qfc}0YL?qF z*Ji(+Gv(4XLK~1s$H6k?gutvGzyy!nmL&WKsH-UWMeD&U7Buh%fMFW(^ zjEbH35>z)ImB?7D9GG!4gKd!P79i?b5L{m`5L=Sj#Gq6H!5<`apQR)C#;+ahq_gglgl4I>M$RY1SK9OWXSQY5> zS>MvTXa{!Duxomcu;=Zt@=_3A@6sl4GRsj*a2U<-CM@Mb;i^S~XwlG+Hm$%syqa#4 zGwwCRRKAt^p;Whf;GtA5lFNRp&0j5rU%|V%0i;gDPUqeFTUzrrj6)1o=DvcGpVOh% zQ~`Cab~#+I=*IQDo7(oY?K@4m=i9km)#4=52Ju$x=QFy*#)U5Of~1gjiuhxzV<<)ex2sCI1du+@1mgZWdMyt&5EM^3v( zXAOK;ESvb=8QCLt6MOTXT9U#ZTP8YaN)xWo3!1M3a%d0T$4eB`wt#WU5ZzNk0u6?zub6=Lnc-IHa~P?&!Ezbb5r9)(hK@?3yFP!%7FZLw72Frz@#&mEpjtOB zdM{Q7s>#wmo@z@5W4MpEfwyVfMCl6{T^}{RWKEfe1;KDGRQanxyvHv$dHQ7T;@5zfu1Vm)bE^@KYpCl82 zMkNX@eOVwnkWWiE;KY;RaXb~j9M#$k}BpL4(X6%M-nH& zK)DO*+~rgHuWX`l1I9C_HfEe4-|VT+C9FsW)8~ifj-x(Y`o6)rN37VMT+B}V)-YQV zxW3v`L3brWNYaxJNx#$TfcGE0Bn=(T>7<2?ad@7v_|eor@gWPmE#k73x`*ZD|4GxO z>C_hl+YIpP<+6K5d2@|M^~rKFi#rS_vC6bRn#Um2{uEelt^{QesA`qv*=IoL1+3nv zZj05W_#3+lpN{$7>5`>k@BB6YANwO4F4;9MC^D73sDK}k1qwSjxdjp!^FxY#dt2t? zR3|J)G(AbbcpkWq3R!o2B|eW_*^@e1*65*&E}hiHNFRk397FpYTO;PA3yk3&Wi6uBOpnR_TXEPf*XL(J_8o-1ZA~d-Rv%yKRxu0c_w~fxaVilpu zIB<%(5Pxvf`$@Z7j>H*Tu|M?TKCd};>lP6sL7A@Gey5+8vQcbsoLZJ0^lt@~EP6&2 zmf#KUqgiQ^C2*Tr2g}sH!fPJl>#;GGb#$EB|ClA9M$g6@AUg7Am-Aoh*%qEUEpcny-Ko)U9Oyp|f1F zPF(zs^{JRxS_rg^U-g6Q4;Pp~2U#xS8kf8Dz1#3Tryd4du$aDQxr^pqisDD894@Ts zznNSAtxKvtjZLB)ZkFb-95JaovsXD6h)U1%E3O^i$fOEy%(i5Ktuta@_1LQ4$>}qf z8M(*>M8|IY3bzv8f!(ukC5@6H-22u$yoU1`g-mERZ4KTuu?$@TT%P4bMfHG!IO*CaovfOq1upi?;;6D4fR6nXSF3##lZy z!n!9vC`{CGzhfntug&oK#zg5v6AaY&+pm0L*qx35+z!`t@7RH=)dTy%$fh}dS0U|j zi7IyT=^ZlN?2WQc$TDrrJo8&vA9#pJ>{X9b5bu-48b#BDd!&OjfBZ|fJgvK&yqb>V z4b2sBC|Kl6X20>7i_WGQXNKauW0>0HzQp`Yy+QLZ*D+(1v;m7dpT$kU#$!wN`Kzd#vl59=%2L1)^84P`brR<6Ae%3+$W6=DBPb|BAP#} zo=7U^49nL!u*Xg#pJmP$V$CC7Vc92-xJ_}Kkl>C|^k9cY^F(O{+Bq>dFEtKrAA5)NKrz;=Aru1G2KZY%!Y`&(C_vBHZ@ zFidVC(E6_SBuyYo7vzywng-`fCS+_tgOvd@{CuS|1Z}uk7WinHS?=r8AR`4bR08xVDA&nU{_$SqRC7cfM#Kw$Y)B zE&H>j4h`f`$k@ckO3^^R&Miy2?R@}0WElepSA_=5Fkz42i+FI_FHQ2!%6?Hr}++Px&6F z1n6gt2z)o-f&>x>vO827_8i2l6ODO@X()C7ZOztj1FGh~O6t0RjjPbnPf3KKC+b%e z1;!;Etu;CZernB`GgXF+tO6joTy(F}`%Tphz3{;n1yjMzsEH`cXnOv<3$<92NGn-J znj;)W9YB9D6l=neoCc=>-jvOmRmT+-&h#WF z7&bJ9re&XB3lWfW0Y)-{dj4xQSz|SlDi6aG)W;h|Vd#x24&_(wGO<~wL3^z7(^E$2XTXdMmoMcuGjK1i0eYD!kkI%+Me&4+|Wc3X)=v7`?o zvXm8YUA0=i-nCGhreNm?j6~@t0GXh#>x`k;BkLxQz9!Qpwc;Kh`~0G|zPU}_j0Jz> zc)!sVRzvD;JFvvZJa$CH^w~e=1x{43rp`0Xlh|$DO~DVr5s+bkegcnJZ-)-)<_=JUW~MH4?bBBO;8oFM zaMgIjZNXwt<;Ad z>=vo7>X%5rnpqt-?zNCZ2$my+lv)2tXsL3Zdova$<8h zv{|4w64||uVT#O^GEkT!;Ma7eL_u-KcEyZ2Sn03)mqWdB?-)b3Y^;s!n*Be2s*@MD z!x%r_5OK|YL3;%egl3R*!y>^sDd%Sh35k6Ih+rvNW?5EuVTzp-O+7%0OY9bxt4uto zKUCLRdrt``Sn)f7*H-_65E)y<@-_|u)RpuT>?>qcvRHYF%`3uml=47ZU8N7L_sWoYVbavAWe%>qz!~e$HcU8!(#!=%x3f9>ozO6O(wUC+q+W*v**8&*STwk;`&lo?<@AN}5PBivx}_ zApHEf6h)UT)db7w%^cJQ2gG!xnBmP1E!d%LtWQ#M)xT~8Wb;W#x>ig!&TykZ{F5*K z`GWmo?v?un(AKTK`iIV$0&g!rs|HI@|7|nslhXPfELmbzTDYRk0Iogt>cHqpD7;&i z8y{2GMBC$5uRm_}LFOmdNLHyLNnvgU_DeHp{VUX%`w1?_T1(*Ql^_&5)FA_Xm) zcSn>)q(QMWEn!3ca(XBz#9jv$do-en5U68t* zl8y3L34>Hwp>W4p$h-^>Sq?tjyd|dMyG)HZ2-1yP^y{85Fy@>w`i)|aGf{b-04z)j zdJMFCTZ*uy4=vKsxJdeEb7RaneTy6PNUS~p%Q8oo}Amw98ESb;N) zGSP+a$fMF5;%DO+tiYre78 zPR#BzA|$Xv1d6-V!1f|yAhuOYHOBMMM$0v~Euns8lx%nIV4vQJ2=0}Q!M;>-n2}20 z!>Gibs%&Ijh}^|C^tku2oN-`z@aely?aCy-Cl}oFnnz(qQ`W`%xx;7%>PiFItihNV zcPH0+NXegrvHF z6QjKV5>nKung=~SXkSO6!zX+t@GD}!J6RYP=GnRfrnITFO&z{oUWyJawo_W3w|*cv zn=TbhXi*n$MdHxhqNe!Ui?>LdJnl071JUUx+1^3Z-3#}Nx_FN>uc;>~FoU%(qjGi& zHa;hdPN*z?b?nKbC?_SH&W80*6#?pxe^8zI9OC)ergdb9A$ZYW#~l(>r!`vm^PGeX zPLiF`GMqcs#g~#goQRPDYa02S%86i;%!=_j7k{{7OU>c)A&`tgAVFHf)g-bYz%SC= z*`Gc<@bxVav+!42DJ2Af2z6$u)1GmY{0MX1*SO8)>G5m6gc&frSR=W115;HV_nD}G za$z`9B_8r9aBPZH(7jfCs3pDkIirL1fJ?)A*vuaTLbK^YqF@SRd1lsyn)nb@;JKo( z>esGWBRSRL@R5UyVM(NNHSl4LbIvJ^rvd!~>*L@80sySH@CLT-S*l{ze@wLBcZ#c6 zcHg2u0;iM&Vqv$tTs(UUfgT!skalB+kRm)QC^#!66u>>%D`0hW)rlEFsV;H)O0CFH zH_CQ|Y;yf@Ru9GjVf{nsrQDG#DTA_s=iz)vTt>v39D1I^Y8hFht(sC59jHpUFgkC5 zh#jw(yZ13ooo?LI^fY12&E^Q3tEMo}aC!xh%N_yj7wRX|Uvcs2l_5wMD5qTJ`p-9K zmXpB1cS_NmUwin-`jLQl5-ReiQ5_8LZD~aa%oF7p>+-`m01y2Vn=0tf0tx3+$lx31 zc)%5VMes+a-z3VgmoU5WrhR`&}c1TQZ@fSUfQ<2(WqynH*g=k{t@%)q% zpVeEeyao9{Z?_1)wI8cI(BdWaoH6r_lKMv{7@p9IVAgQnBRM^SGVjY86_8DNES=)P z?+!G@#$5cCSO-=Iq?m*p|IGZrb0dXQwd~UfB!->b_zM_7gsi|ccRPpDmfmBJdR2Qo z8B#q(M!1Sc9Hvb0Q2L91#$=O4>#y8n#QUfyB@oQPe?mABu5V~b9bF*s@-OGNYKj=V z)ccaAv!4i8g%4tJq$cgASedGlBfG5v6LEDxCs3aJ5SP&Mx<~X(TC$jmu}UIjMGI40 zmMz%ASDYN0Xu00odh??FjAG{-DNWYWXAD6fDr;;Y*!V{m`d*Z(J#@__*x4!<^liciYpmZJXxBt$xsBuYzRne?Jryv!yq!}P?RN_fur!N$=y{p8CTD&BU;eL z5P=jU20amIGsdx_Tr&EBjqJ~?aB>RoRRKz~Vn7R_w?|IS7a5|Fj5bZ~kXMeO+Qa8NDP@z8 z*>4`)lm#VBS~73c1{2^N9;*9-KHQ{fkpxVP-+j5IxH&oe=Wvs@-|*ZIOh+b>(KERZ zU=X&NRmXpN^TVJzW)lVJQ%i4|%Xb-Z*Dy-wvlBZjaoJM3t7k0j13e8*+PD0m2%ZFG zoI)!>Zx@GZgwl@GFn4r!*JZ+2gHh@FO8(7f=1$*Qz^iJD z2eA({SIPS@6beaX%q?;K-*c+&m@BW^=eOkk=dC1D>Pxrr6uwXBo!B1XjBnmZ3#)R_ ztIaDoKF{kCridaw9zyMvhehcMcSr2by}Th%kp1-92kl6A$IA+wBJZSDv}fC`rz6h^ z7Utgg2=cca#~+vqf12}7LQMmZCi&M!+7?t2OD@2x0*UTSp02AI6$*HEA8=p-0^PKR z>2CcYw4QZUzGOJ!4%;VQVa+S%S0#h=e7 z=Z!pY$L6%^A0W5QU8r}9QrNKtg?*L^xIXdBI8lMV)8$qG>DOw^t8Fa(w;4sv)BlXU zM&a2u-W4?26f=F`NaX_yOsED$02wJaKpQcP^gxPTFA^*Cq;=*WzuH^NBRUUjifw|Q zDd#W+h|&&?%0plXC@0Go@i3V143&@%f3uD8kjl?#T#S$MvF`zm%OtZW$A~flT&=P3H-rx zLb@#Ul7msWUlU@zPVkeEFGym5Py|d-euJMjzI?26{ZY{XFe2p1W-pWi$(!zAAT8>! zX2P(t&|B2|_-|1aff_?7|D8dcpFdlFTiUt1X7ontEdOc&?Ad-bCy5P(I+cPYoQuPi zK*w%=Xm{mVI9lnWDBszOb15zw>?FHfsqht3ge&~-{s6j%Jy@jw^_SM>(ehNgGfR2U zC4V3nq#%yV4o87m^&V~7K?0WKYwa$RSdd#K*lU@M-)c@fHsxJR z4g1t@$V?5IY;0w0XVY5jv!~v%Yhrv-rH`kSq95J%k}xO6ds^y)Fb$8~mUVqu!UHs% zg2O;pR;S#R>58ZzeBbKxauCP45N9n(-@`(ZoRy(Xz4C|KeHKu8O%6m5bQo(dGQvj@Bbz)Xj|LdiCWd=?b`t zM|XQ|);$c^L+EJZIA??KdWNWlKrjQLM}daWsP|khX;0FV)TJ0yXXdxvN5jtC6sU4e zXbi4yr~>DCIOR>%s|!!2uRyB=5AAdHUnZ?&rt8;pmbtTFm2ckb>nKfuz#D+t{mSBV z+1?pqrqVXu{X{K9i3$i}Vj{Z4lD(JYbEiI2_L$sGIjYVNX=S)y%!2p;ADmmXp8f}N z|B_V*ymcg@ngnCy)}c%@?c1YLcv~3fQ6V%CkU$0Oxr$N19TCqVl2th9F1XNI!Wf)= zdT8m5PcpR^1UqsgW!hksm&i4X`Qtwj{hKONZoU_RULAap(j0TMlk7UV%r9`U`8W0{ z#wrJsUs@;n*(NMV-oq6adfE<&*O`r9vzcei3OUsMrE>iZJgGHv{s5YwEt$+pcC0U( z!2afs1v!3IEaIc*dT#OxIC_ShS(jauSc0VXSI;Ub0LF%v>!Q5F{lkN#QhozP%E!u1 zMA*IYy7Eam_jU+voyD!P{=(m5R$zZYu7o4iGDNr&uUF{b_%QG*&V zr^67Zg%kpz5-r4#0{eGijzXb9Eq=&?|Tx7n&m(kP94@=upWZl(1tw9}5g zeqFC%TfD|F%jpxN!-Ce(HYJp+LG|NVaBDA*%v1rS>RUsCz3KLXoe`8un8K`uoszAl z-kBcq%}&@h13<#*&~0PKC_Y_h1%n})9AVh5Nkyh46f~~QqlojN&7(dE#fvhVLDZ-L zDa!|`OhjyiI877kkunT209F(|7KW~;y9b>>5aKo0St0lTm}rPSUX^s24i>jP4N~Yz zYoD|y^v}*`PR(mk%fRFW0u*66xM_es38!#RQu5qN=WId@gPvc)8BkvjdrBvuVdps8 znhl#M7;jDsn{D8sd}kbI!_lo%3i;65(KGm>4BBUGLABW$jX4Zm+)pRe>FkfEcM^0c zWbM|A?7Z2M&zYq@f;rN?`VmpV001yBixwER9|vP0&{c+oS%jNfAdU4Ad6+Pa)jw9# zTmU(p>n?1tmiCjdF6YU~G1~+&0^!VnD#^l!u2KlN{liMjN~dB@}M8opiTq-RWj+pNOa* zsfMMu1AfJD`1{;5Z`lup1gD|gBrM-nf-ZP&ZzgN>orZUiQnP4Yt#wcz*4f2_z%)sN z65;>Le}fWgAz;|iK9t`#jaO*73ux%I8U4Df7yk(5o; zcHH@J5ai#McMDc1xaP&CP<0H%d@1tfn|6|P&}`#!7>bKtr<~yDsbxUB6maNo_;%@s zy~8PA2oE-A@Y8&yfG-i>X|bc_Vu}N_)z9yJ8vCLs*3ZN_S@zik7;^Q3o|bG~-~5A} z#Bcg>N|XZ$Mi^q5-WM#pC}$4Ol_pG9wk{hf09+ea8r>^lrmjo*%Wg2Fc3%G~LwFL! zl%MHZ7wkYw@|oj}%UL6#a^N0Lj)Na9J71M3A=uqIfZ-bk^WNYIJ_n3g3;yuv@^%q_ zx}!R14%PHD;mKA>(RdT*!Y!6m5 zh6%(J4i>RBMi{(?-pnwZ%_}S3*w5Ez6k}@m24Z0;k?1Xt1S0&!0?nI5eEX=NCg>dD z-p278V>sfRb4#_SIwli9V1=JTlVd9;WN^AFYEzvrGTLZ#TL==h_$dNkkL2rq347kB zMIxDw(f^Z+d+LFMduu7tL_=7r_1`rbwKg5PF^Is^XddIGMVuY9QEI|bbc2{ulXLS4 z@&}#eWDH{;RK4%dV3o&F^_%tkMP|f9e)+8^V6vMYweb5Fc&z|n<*O~MBpNEPocuT>o8?n9a7d zGQZ<+Da?qZP-#|ki_92zBSeq;_JuMh4=vb!(rl4LwSb3$Bxwi?h=}2^fR+5!mPuVY z*Y0BOV3)!EZ3{P>!?04(8(8@VQhciXgOl`>WvZ?bErL9PUx^ESpz4A5j$`_a4*0Zw zXOMswOasNIgX=+UMvnpb@neI?!NPCvGMQ__|D6`=Z#k*9#Gbdo`MU%6#KipU2uR&f zwH?)KYJO#8i0_VOcz`3}wY+H?Ma_A8$xD(VSzVRU#Tg3>T#_p0F`Wyvw>-clm?4-6 z-?!`zt&t9!O+Q7X=BZ@%W(_{pHUXNX4TMsP#)%R!KC9BS)bscM>03V!aj>7ni$EFq z(r@SMYMo1#JoO(0pW7X!KU1(8(NmMd;?+fGn@Ourn|t7a0cmdWjjKDc9b>v$^Y#ME$xU4yMlsTnZkE!iS)Ty=>``^L%j&7KMbfR=zn(6wQg9Sl&D|4g7hpIn zI_?uU+8!4=0AJG)fT(RYz!ra~KUe6?{U(ZbWLw*xq><%l&<&a*hLeoX>C&ikxeojjGbsX>~dPsMrXLLfmlz?FNAXWmd&A(gvaiMX zHUFm6P1H&QL?|~sf{g~6Sj2xnafDby*SzGjDwNpg$?aDtG=S$e@u59PhR%W|Rb!Qu zdNjDhDZo%TS9!gAqE>0Lyr&TcF(E6|_`r6ELh>Rz3@8)C9O8*Y3(*t+t zDtiG>V+cu@y4Q{54&!V!c|hz!vH@Hs*AC&a^k;$-m@JcL;YvT&23U#y>=&mVHU*m* zB@+Na=&Q+#J1|DDyFQDIq;Q_rq)BnumqRIn7_3#Xjr2}fZ5Czeuv|@Ak{g}R@UA{W zh`&hRuXYkOx3n-?l5iq%S zWBPT&Gd}5=dD1cq7gd|>tYycA;A7G6^HB9@aUS=e3a=Y-ObWUm^1f0GrW#@da|ze- zhTQ%zEf|kMKM){BbH?{OXP-X25u#Ac zQ9y&Zzc@u*x?7}Ej8}s4U_ECHtUYnY3f#`Q_z;=dtR>e%yJf8qAcqLn8zPGAJAx*7SCkg6UYL$gRWWf%IP$QFd|YS}cD0W%v;EEqf-R zsRoWq@}C`?s3$Vj_4eTfu|Mu!A$iZDeET$wfi%THh*2yGngp%?kHAv!ILCkdL1Rw< z?!X$xKQAUbL8Q<+ol#PSUesGP<^}?@cc%;l3g=u=G#rbCV?U_a$^J<@O9aXl`@W8K zPtuyI_ynxER#Of&9ghSIHozD+EL@rdAlF5vHTCeJn1sv&B^#)&vvbfr-*`Mc3C1JM z-C2qzu-{etr&dP^`(?Qq}Dt*9X zngqF@4v)jZ??i-f=Cw{baQ_48CM;A%@QrCn&vjW03&kJ?$3l;N?H|J=T+oEiGd~ z&J+%{Os;k6e=063eWT;`u%ScaJ0F*l(DOG+4S4&(#ue~p*%~a7cS%TBNdzkmP|EAi z3CcB2a*D466_j0?yG#p(gctL@YkGO{XDnL+LIKY0#-PK ze97YBhL>e$7crcK`VL-Pnd~t~uxnhXMjOX~F)>7AUt7^9W5gJX#}XLv#Oir}bP&P7 zr2x6HrL$uj>@ml!a)r#gOU&_K)NQ}3&S%ld!WCx&x1wim`6i>>MEjW`>0=uxZB+Z) zT{gC|gR)_H4M`%ziT@X#t4#P~fCM_tZ%YDkKF86Fo$vRIY8EhISUmnuCH?2r0RF@2 z`3N$5QK?gGhxq-8K&vwNC=y$}AU2gOz>oRus|8_TzL%#ZoBBFy!z$m>qr>ph8ya() zg&h{sp=2zF=r>12CP%O5C&e(n#0GGTCzZ8HGQ*8k?5~beA9I)|2Z!RqTx@D^0 z4@X^fB@L~@5VfI3!{c$-Jjoz(IyVI2dhn3uY^9Bpzc6hg|35lSDaG`Y;1Ca5s^zqf ze3=cJ|2_Kx0j4ZH56fyOhx zutP?E=ajF=eJ(%16+@E%O%VseR8r8WzhwBu-V@rIGQ#XxN7}a{z5v+9f?d-M=TqYid=%+M`B% z%(OMTGAjQ_P4+$%L{kp$gng>6OcX64ysy>PJ2D^hjKFcn|Dz8M0;G;@GpNVqbF)9n z-N%dTEu$fY2SHW=##y`~lr{0jY9NGLsGf__+n^yvl1YpBog3xd6X{=$^j4u|j5 zj7qx~b_p$8c?A`i&_L^*ox(bB0ulVC5QV^6GxEdF$+=-Nf&8Y$Co=~Uym-x6ORiA=iuw&OwM~=< z#$$r^ASEa~6F66_ayn!YhTAN~_s|-|XELjh9Z}_1ukSp0-u3l+0BFi~x?%SB^_y@A z+!B$+w}HZ92b`zxINHGux4Rd7@7_9&yG}W8= z%=5~cBu1kGi)(nw6|V6V&JOd2YUJQF!E)!ab#&P3rT!^k*Ep2+@o}QWPu<}J`L62`;*J7RLyOQvIphO zV|nMO8%A)d7PTviCybrH=EnG?hN6xW!By?7mCzP7mQ>#l?9|;xiHIGna#(o}s6vjZIU3}wH)YaLR_>9hBP(Rr@aO1O*ETTIJwOHc` zj#EY#cKtDA^hDy{`+}jmzD{xUTR06ctoJ80tb=o?_}Ne=GP=Vk-&8l8`^(c%%L@Gb zkO`?|kecQcD#b@X9j5u0v5QRAVwhq_V%6RO0L47P+ZEJ4j^SxHe;9#`?uOb`Xu*@G z*6zmtERMrMl67IO{^v8c1>rRbJqnG|T?+QUO&?r&f{G z(qW1&xHQkEvPzhRNI2S9$+!1c%!A?TS?AdI??}r1ix`|cWKerQBjLi-6&Ex--$_yL z$q=CfB)-c>J5R3OeluwDO@PCY&e-V8!(s5zs`k}KMFrkLfP`&>hd&#${hKh_;tQ6( z_`oc(F%%JD{hpCIcMXNGbxlsK3VNH=!3Wo7f5O$MMNa(R&2`1ZM|@TzVJk{)6@a3e}kjU;t&U|4pyKOlyAHyf$mY z>~&yhm35N|?bK9Saalkx-aS$a;7_$)8p-)%*^#8;iPIO-9pR zJDbH=?5+$|WRqsJEPJ5^k&s|$u9FVZ4D8=XIxmj?20qe4;gbmz4`M?M=BUob^T9{k zMi&W)t7~XfizLu4-vdMAb&V@Ir%IkaT$)bFvwKa1>i7+~CfnoY{42RrpRx|gO33;| zTr{4YKJoXmBZi5gJ(qQZ6=bv`HfAI=rJ@9r@13(U$6RO3x=Qxmu$XZC zuB;^-JIl3g9|`qU7!N`=jT(vJQI{0Ip@D7!?=~#Y4cn_PpN<=DKsi9-E|{0!@tOuR zDSbRa{0jyIE8;7EAgI+hK4>08Cfs83*6Zcf4OqxDm|bGU3(KJPEN>M%Ca38>GVOfN z9ax};;<{U`w|brPVjU7nUh*iVFPc=o9MYxT^^**!FR{B5lS$L=vVfildHP#LiqgZ2 z+6g>*CG>>fV7KRz86D4~3_^O8F?$@+tj(neSVz7%KAEFIjKhMvUF8;E*xI?aaI$ZP z-(pM}D?;wAc=_OBE6>N$qK1U_Q3Xo(*hG3@1 zkmPJyMc7y9dTphm@K<~uzml$C@*iT&(gvJH^SMl@vkU`*9dqLFTTY8P+C`PQ<$xbt z%8AatH&|l?r~vM*E3RNXw5rm3X5Lq*=!O9+iW@bc0y1$m{x-Rxit&v?5JU*6MCQSI z2U65x3DVQeZ+Ngsi0;v~j9Gvh_Dk*gxQsdI8{VKQW*JV))EVI`1stwL7-k(&?ZTSN z;y*ebQRmIR!q8!}GfOIA3XC9BG;=e=D32cjKtA z`$`;mYExZ0N4PK0xb{NB9gVz&$NA}&ZAaCJPlFQK3Ibj``(DQA-ImiE_g=w^Fx`7S zmzs;;Cw{{2&-1U$pNY(u&Fi~U@5h>IfU`(5jn}C(KbOH5v#;)wp!;IReCBCyd^A-A zhSH-kVZ)DKHNGGs6?3!L;V||(@Ot2$nwTeBs@v^z9S@pg>8ia!xK*)KGKkrvObLCxcG6xAFBHd*^UVaYlBkCXB@_x3a?zWKnVqCjb#HtI$hALvd48iE3590h#6;RM4X)o5e3ms&wt zLL_Y%KbO`U1N!y>3F*rHeDFQYxy5|YdHBfP|VLTU9Ix{l#GCPOf0jCkpOOOOF z2cl}>Ku<#drOQ7KXFS4a7PIz1l#aPPIJZBfbC+pz7tO->eozz=DAI;< zabKey9OqFznY95GARrBwWf#sc#$7l9m#Ekx%WJ__P0xiswWvkCfgv1H-fb@8@6qw} z%UOJaI7@f>vZQ^yQ|sS0Yp6}_%c z5AU?oy4T(BNk^l%Sqz$6NYn}Pn|&Y8#^}%3Ym0{@AD+AYb4sMWx&$sh++;1JA_|Uj zbB7DVi+8|e?%C)6JNC4vRJ6%Ph-K=dFv56_W~kvr(HxC`&ZWvWyTmssT-1OAs2+6X(2urc)PXjC!|*F z@?N&C6l&>T07p~gP{=3*wGAfv;{cpW1He_}oW0w(s4ZvKi9sAMxR4EmG*vNTTM~V1 zX{e6Lcon$KW6EQl(DBIGVTP<+L9S0v+&e!DWa0^L{QO7I695i7G7<)~4P4>B@C=cE zg?7P6ol$PYkjKrNBAmowix3%$jEVLS=9vRlEfFRTnNUmF8*9#__#`c5F{I~2VexB~ z{j+7x%J`*&fY9f$&_5NL=_iQc-QR3Di;NM8e*?({=4FUQ5%fC#Ly2`CPIJ1jpE|i% zFr?xr=ehaFuXwss7kAugDNX7wrwpia|r=f@fy1Lp7IoC z$G&5k(lEKAGVR=3T%~K}+_o1bd}UPsTHp_fBXHC0dr2!z_)$x9@~c@1@U$o8WY&cG z9Tpe%tef^M>vFKpweJS#>hU&G-Ex@yKz9gFBqkKgH!puDtRVg3wy{LQ(BbB*8<{asKUz(=h!|(CYW4zJXDR~s$|r)^<$)5v z1#{CQ1kf}7Vj%n@)6v{0LZYdwR&boj&ddcUhboKwL*^m$24CQ^5pS+iR0+5)gdKhC zz0ac?%Mb-Lv-6nCjzTSP;neO`@*|J)xwkV>aafQ{sOzeYjSFK9qppBi8OQW;ISjA-#_7YsWz4|DBYWiO5RV{y4+NM&1{N%>WA}^h2w#y?N(@L#kQve^5 zX#Qv@7K~_)sllfCI&XX+<$;~@=H=KG0i~fIN#9dJ52=z9=)Wl|EzI75gnMkEWDZHB!0c7MxPW|Hhu9$0&VGdUDpCSh7iMgV3-k+ov`U3Z@ zIn-rbTC8dk*y(mxM(CY3*iKi8vQyuMTKDIMjB>jYu6&=(-6@RBuY3O$m0~eB&T}2# zFojyExO|FFc|N0U`F}`+?i^Z>vR77Ws{`iIe&<|5U$L$*7?K103!tqMrL$UF5FThd z*;$zSyMQ}um^6GP()EmeY7Y^l5|jq5{GI@kn+-j#@R#Phd1p(*rK&1AU}`XL8e^m- zaLr&0{(dNP?C)5i)qWQ~QOZH7o+@Lq*UD~o317dky_h#;f5@$#Q@};?i{f+TKz^Bs zYXV}AL9&pIMu-`ofKepzv4olTa{C#3d$0cy&?_HQLDqS41`*__R9Gh_kc-u%d~*C@ zAi3u~sS3-+Yb!?GIk{`6Qt$}_Z8w-}6t8>Xlvpk-Vb?9BYt^!!2`v|UDZtjTKJ0+} zr8{JiAqnxP>MquXarlKkUD8`Z9ijm7i9K>@9N~|TXx~d?ZnnM|fHVBbrQ}Z zZ+Ni@4loPrK+{Spv5**tu1~j=`fa2GYDZYiMabAXD(^C*4^9?u?HefAVA-*wh&l`XFvNr_4NAo>Fc9 z^4}GWwd$NoFhwtwIm-H>_tx*A^q$CsSe&L4g?<=~=6uiZTK}=B2Jx;V)4w4+O&{UyMOH8l2^~VFL`*qY^ha_JI+qd)Da% zXq1bIP-P;M$Ywc-IaGp=u9OCL!z8aADNATZp2@Kw`>{gZ;GQjDbFMQ3wOjS#>6Mw* zigTmI12M3+F@((-%})6PEg8Cu=)n;9gQXV4>^^uPid7e9m+Sie^&QZ?pj(bpLV4)1 zA;-J=T$#D2EeWHXT)cN_>` z(V_v2*kPcnSUS%AcOJW`vZGwe6K6@1omra zF`ZWtlT~;Q)xriLaU0JNzuvDJ@57yD*Ac=X+{M3TD{rI2_J-~SNwB+*y!XiTzR7o=xZ4P43;)iew>p2(lJvnq%)>~)@avbd)JblpHm4G?+~ z)6&svgbJ#jQWn&7wE+-UcQKhaxhQKpb}j}=4L`lvj0cCqPX@`|c$#a93iaQfL%$X$ zUKqSt>j202q*4DXGd1G75(h7}EaJ%U2Lg>4eBr2G|Bs}{uo|{`7@du1d}I5aS(_B*0dFX{mY2-WLbcwX@C00sYtxKF>ROs>L6kYjQGJ)p~EH({}$&;05_ z1AK2{lfyN=W5GRvsF$Q$6{gd(IG)f56v*y8v}p2eor}sko@^^AMEWQnTp|lr0WbwE zJdIq&gjW_yd=iWw0C_d8H{`1dlTGg?Ff`YlFm#_Y(DaD0#j-S)Nd9k)H!$CQv~u|Z zJ-&zPOL|^r9fk(RBcQK>mjc_CEF*a;o6e|dAKu(w>upZ%piX9q6fB5nwG@0gTU6jj z92)Ecw^-cxrtJWcAtseVUc#10RBVM;+m*2-G5|(K z&)(hq%NDa$eyOkSlrH1DP>A_+UeW1^0W!~fT5Ki8e*?MN9L2viy+syX(6JI4AF>Fi zE9R9EaYZ|Kzd+!Ino6M+(yEa=#|B)2DnnE>y`Ic@ zT{xvdN+u<_)<^UL9%=&(<83jI6anDHg$D;Zc+%F9^+d45<2p5)}!A*v|j zlC;{gPN|INxiTNmvoUFD;WWEfb0#{%yy+KQ=KU>N!(g$sD|e*A=nsOaQJ&3? zYQvPEZrX)Ss@BhgeihOqEdMhha4Q}~xvarE4I>;VvLZwY1s~R*LUWA_DNA-N9RLDI zz8HV$9?IrQiK*yWs7iPZ)J?y)YM9?sHFPctXKpvsYJBCUToz@WEt^_ZE9feX{Vq)x z5Uh;R#iiEofh+I_5J`b}!57meA-uqKn1uwdtCvz^z~02fX3jbyp+S}UrrTFfD+Lh8 zVq#(j>^+l2_mjcYU!pzQd~quqCEzL}vseZAPikfr3dV=l>;_Z1f+XEr6F;Ir>GwX{ zo(?M4LNP)y&}Z5z9IK_UAGkI7lL#W`d$wn8zEti<;$EW)3qYZBVzAq3gpmiGaTUA9w17+iEsI$KT~pb6t%bQytU zO^(HB>aN9vgXOjH#@Yl1R@Nlnu#-O+#DVEVD&Vp8+0#gpb3dJuEHS&F>XjuY5WvQPRXe>0!Xlc8tQl6$2zjW zSzcd1SRDeSo@5%j0;XIATOhig@c2TNNyX;Q(O%-BuM{EIPaknks0jO|gd4{hzTCDO z1K{BT#pkQ!gy2q_?-thYmQ?hIrb*@w&`ww)IAp|0MnCM2EIXNpN-drx`*p-|4J3pm zmbeZr{~@vo1OfA-aPu_@$DDNJjoSA=GYQHt`9DK-9Z{&@-fXf)i8OxAR7$y)2G1-I z&!g-DU9p6>GmxTVA`I`aY5>w>2OL@%99h};a%F|UHU&@N24Rn?HaRc@(a&iK4qEfs zNX`QVa3}}kcRntFtQiJbA#+7Ya}_lh29z@~9>L`@4?Qdabvv(VXePFM-FNVfTp6z7 zaXI}PaA7E_o9z8l9CnZ~M8!5K(%S+6ke(S)j@y=}{TlN>DB*AIAW72+UQf0OId|tM zC|++%14=IPm5)(vEC}f}zTngmsXWZJwxYg@pSQ?R>-WSj&ePN_#XuE-XyK1L_~*Je2o;82URQrFD_OLyeL}k+q+kvJ=qtRiMv58r@tfX zo5fp}+CQ-qC|lM|a5PJIYEdvDK}u_r-Onax7R?&Cw-ZynT}6pUR2qsBHCS|{00D(E z^I92}>bnb}r(v`MT7)g_pn&*q-X~W({23;pO=$CwRu3o_&=N^br^)3R51PG%sER3< zdWXjik>PsP96}}iAsNW$0D$zvr?rFhq8!OWPj+GtnwRBVS7fI9reu;6$!bjY<+>uJ z9SX4DeDyKMwijT2MyIvOBAq-h7SEY}U7l2>!{ z-kD3f9Z#02!#zcbg6MWk%Xk%&j?|o6qP0OXRZ3Ex5@Qee(+w*YrV_;UeBd~m8IOkH zmkm^o9}Q}KvqElmbpIHu)#T2;xgW#S^LcEFkfdk+YXyUtKmxaB!W8Rl;(0pun!LY9 zGTgDUr%w2WSbAw9wbWA2 z4*dOz3(}|sd>3sQ)Ad~Ci|{zQbEaWfW_%9W-kuSSU}=B3#ud~LntKD^=OBM$ZJqe94P1py$0G zTg?3>1z`#eP|;$Sn+9>^Cj;s$@9nBl_>-{%#a#X^QML3i)&v_iFIfz5sii)Ps^~T+ z#C)~rh)C@lG{q@Blt?Or^$m6Iy|p zW$_+VbcpZ1%^)2(nw-0Nmk35RGLRx0eYmr;Ef9%})0#wZqj~U%#>>kOU6fUn{$;TJ zRO1TWmH%?^@9+VP?;6%%-(-nVzap+L*W-&=k|2}=UDwr3k*Z86*jUmJOeJg<)TlWt z;_zTphD&$_K?4ae8PlVzXN;)9BySV$x?f9nI2OQ9F52xJ-{Z@8Yxri!!*9cre>SPI z6KuaGGs>$0WCIPmXX3AmA!J>0!92333p@wC=k7%zsPo!N<@VF^clNhKf7%Yp(=_<= zNcPf{J)Xuq2IamcpRFXaZi!CzCGpRfT{)7w8j5U3av>tuJ8%Ic5A~DyiTvcD z!Py9JA=6NtPz6=%$Bg{a3@`iG-y5SS5+WJ8_4uy_G6IbED|(<|sK#4WT|J~2v%RDk zj^N=B;#H&}7x<9)J(^I$hsG}mfp1+yz!aLmc(wRl8>(OY&(khvO2cO%nEJ*wO*{P9 zsWX!{2Z1Fhcic|DLZ_%8haz}@a7(k>R}kt8fv_n>E)MT-2a*sULHws`NWApw_LL58 zuKy+EO-Ffj!}LV>E}5Q>BTzopy5!QItzxZBI^-8*k&Q-~+dzlKTGVZ10s@QvDl@m0 zJew+aGr#F<>%@eIQ#tAi9F`Xpw85Om+IJ%&eY!bx_&wf83J|C?SHZqLdxk3|;;Z4T zbP@1F@)I1z=*pN_RSC8^dS8KctPlplJ>%RKl*63rKO6Apd!`rlx z9AT|qZ=Cv=0!#e^C(`QF$DUptc#7SPv#`JHM!h&DWWta3FI$70IgZ0myo( z%TRt{z^;YsbaSKLjIKHqQ8O- zKj&$oYYLHtZ5x6MCHB6xA4fc)FtH)>#i8Y7n_E0LH(SK5c`gc&edLdkWWUm9*%Xee z9N%FtXx-l;w2`)1VDF63!IUpzh^TzeItf8>}@&Ir@f2j zU0?no72Gk>VCQ*a*N=VRLz^%FP6VY0)OR-+h?x|OBq)3uQXv_$2f42iXASXr%%j4! zcTtLOz*zFeeX_F>V*Q7OH|+)@_dPo3l2W(XC?zpakF(bd+wd({YFA3VI_Eka>Yzn8 z(6NcH`jq+(qH*VCygy6p3Srhag>Io)Il)e|nDPT$v>f#?O zXPVB~7zW}POqpS^ExqIu%q5`8{GR04T9g zV3B^I_*!okmNkkjO^&JcUMlky<<(Q(kS$l~nTyscEry#im>S`};3w9{`kw2-{8Ao? z7ATtAt%y*6bQl!z^}2s3!~c1u&wai!R{b&mo2wMllBO0*&a&PRzB1#9s9}J2(7P3o zwyLYb@D;q{7^m5*I5uyCuYmJv{L?=X_ZGF})JrB{q0-s3MmO8qSgcHfiiuu$;F5dw zm(bkK(aR%;C{BM1Y{X9cYw{^f`33vop;->DsHXTA>r0tLH~B6H3&0D7!{o6X+GtV( zv>S1h?rN`{o$gZRKZYeXN?5k(p;1@4Jo>O{cade`Jcv$MvcM5F!?|@$*~M!|Y)lH4 zArmH4C+drl+HJzh{sv&RnpCddYy|MR;+>}rOON0v1J1MScZk!%hzFkABP4=?gvv*T)k1MfrWJ z`gD1+HI)d%+CV=KP@7jZ?u8WF-P**vC{P*(D$+=M0|pn(sbImmj?djEULV`_C0FLX z^L?7}f6h1fU}o6Ht+U;G$3}PmujOrk%c&K$y9$2E^)BMIOeH_JJ|ts6CZLtdM>G?T zubtSubvWcVO@4c0F2vh9@e#LHYEnsu^7KNM-Q?pck&JfGY4hTTECCBuE3yoRhwSzL zMug50m4VV_y18n`@myf4g^pp$BmXDuF^6Z?%d06{23hYnI65o+Or9XJ_SV9O<_c7u zZ_5t*;ma`308KKkOia>&xFaF}IY5>zXwY^pj5-El`mdgM5Yu^N&fN0-Xgxf_5`2}4 zWuy6@eo9bPiaLX79|O!7#54vpKi#h|nM$Gpq^!*xkBoSK%+pYB+d8$5!hhqUfh-Ov z>u@jOxn;Wi$uV|jRY8TJ*W(t5S~WR*3Bc@}{{Ky{Q9IDd&4(?lJ>RP*k(<)7>hvBU zLE%$YB;u@@s9E?KnCSIN0vx3bx-?3*!-dFlcsN`FEz&d*bj%BHa01t3Pv(*87#t7_ zWVWkWY1lGr1Rr(4fy71UZqQCH+(V_GBn*4ATp+@GPwk4zD@zN>peqf=>>N5g%Ch*|63~1;AkPHL6pmzHu{-VCG z2c}vk*N@iYW}4!sYXsRoKNK7%jtuH=QX`A(jjv<~Ag_V|m5}WmHEP(YCA|c#Im>SVK{xh$yIFKxq(!sm6xj z2@WhUlsHs$dD}?G?d1=6eKNo5IK?lAa?3Eau%glWS?AZ!la_>QYOH#)%OkAo=~hTX)IY4-sL4PG_x;29u77)ttlXdS8}}6;9LVb_T_$dH25Ex zUeO^(nzE^E;MK#^n$4kRTGMORTlte}*%_>O60jyBmKrWI(CDZgaw*f~?pqKXIlWQ% zp<9Jo^Hz&O13gP@C0f{g_--LK{HgdA9Csv>8;9^I6`y8>R$JhWA{QG7Q73m+%7D z(YBGaCv)J6UJ9$5p%>?F_-T+@0CS8RUiva=wJ+&B2#Ws<1H_~U0srH}c6g2(l7&Yv zX(7(RaSbzKXN!84zANZyU-FLs-i>sO765lGu@bK45H`1U<>Y&wHh*0w@@YDPS$vo& zQ4Y%h{5iJjdaH|;4OVkQQATJ$#-Z@;n?OpuUFl7U!O%G3Dh*ZSv-a%0Zyx6#YcQo@ zpTu(2z0Eh=7Pf4;>CAzeGsxLZJ5uHd0@xpm$ZCK(tWBUwtAHO0qF`c1mPhH|$i@Y1 z7-Ky{+t?*`$X_e*X57Fdyum)a*RmVIO#mCcuqj{ph4+tU!1hK-;!ha^+$?hqzr*43W$|7&AaL=a5(1!7Y@x(Kh>%9 z^nycs&kK>eQq}rtW@3P;=5V6ITdvH!eqJ@zM8oa{ zh9O#nGrGZXVR0H(5^>CFLID{SL6P20F1f6GJ>XO&mBHN(q7+>AN(2XBtno5F@16*n zg4AG1zBVf#r zE)roRU@Qfv1U>1P-+Jj;BOq>D&rn%G`OEl4&9=R1CIv!cfMyHX18LQx-nERpr3zG& zwOPdbrA|sqCTf2I1UoEw$f%bV)0`T6j7YMnlyU3Cag2Ho2Ua2D=L#6g(0^G{z@xeK zyWsA@E*jT1E_rc~-yiE0br%_le?aaNxO=qPGH`z}QAwtpD2?SdB>d|)JL_&p6k0t5 z&5scE*iV1Z!#NIjWaGC3z`!gr4`=8vYD~&j?wc2IPs%-X`>}6d0E)yO;hvwIv$mTc z@aC`nh1kU_{lz;fF=J z&7i4F?dvo{tPGKR1^*&5Du6F2p*hy6q?xggVjq$p%8Qx5*Q>RExfScTPXIiYrFX=9 zRAV9@>vu!kN^hW*y^*>!I2M@K(~#iBa?71W{(BHgxkYS*D!u1FtFkwqpG--B+T_S- zY7c0Y-S;GTaPBe*7Xg@j7)JDkxj`2WH}73?y=XRleC}jZ2V^K+z9Pn(rWoJ&*V*kx zC78LZ0T7#@o(=mK@~LeOsdX=hl!zZ4X7(G4fB9G;22o{QUw}l*Mhj_L?}V?AA(8=c zxO`k7bo8o7O0fB>gSk8ATTpn=ZnB%9)nTAZTypvshi*A}ZMV6olDxE}Rxu2Su4lFX zH@7z+>^f;Nl7QMCAd{tVA%9=CKD9$0L$BOX2_r=f7M$bK#Ka1>J?y#91oy$h7-V~f zyJ?yIGZj0{AERC(CaNp!Vkc0xv zCHZRY4mF+R_(idRi3jf^z}uerH;Wh1RA5kHuD|bm2FJuCO_3Gs>;RPoEEQmBO#_I0T?^nLhXJDMbH^ zsJj#7-*|g=@FjYe+{$0VK%sogOm&73E5cdvZyoJQviwM@awhR~Kks*^$!4&IGeY<# z;(LcLwcMLv^Qly2&A|x<*3_s@X+T-L81sb^q*K@e*-5csvBaRpOB4c;n;>D63n_-% z082o$zYmcC0}lvyfC6@iuHI##KI?~SyGlP%RkqnPSZ$z@Cnt0}bLG)b+i;-T8C{nEt}!o1BS8!v zXQ5AzBYlZa#9V;`^spib_Ja*!uKAzY0FvRA;YG*j<&zC%+J*#r77(^$TDc{62UV2L9e&ztnq6f=2N+sUp?T4mLeap6Jvrq;z9LN<#QHE8uTlV#7LIcqrLWlW zaQivyGP}uzX$4e_o33d44gWr-abmMhq29yEIK;j%B+jgh2uYE(&Di)Y64o}9y-G{+ z++F@ZCg9w#$}Ptfhx5EyFhg9M0@N|X=FpYvmRj zrB0|&t|2J9T0;`jMNea_t@akxZ6d4#D(D2F z&~l>lr$j@i!ye>yb{*^VHH@gt+6vb8y#~paUz6GL&(g;PE}ExtMlrc0pQ&*EN-Xt(`GJ!%cs%%s zu6@V)V+{=L+3N|~?fMVSdg`Tl0GgvYxEte8hmYvH#;8FQggRA3bO^dA>Jp!q9|(Ss z6}PAnrCu!c`(L%}j=@re_C+{;XEy>k?QSV+m*E7?%`Quu|$ z3dQ!k{NRHuhS$e=ULtYCp@8(Bonp#y z+PppKy|<(x2Kq3`GOj7^)-#~#?(H&LoWsO$myOCOOQTHAUP^lzM81bD`beYVB_iV)Ttw6GNZsAQB;GT3>Ycs z{S%U{l#_F{{3ZD3TH}`|9=fQ}<);XWrw|0jo=x`&3N^}%V1f=}{~vq@fj}9H$sx+t z;%jlDN8*(93Bz2Y+h&Av6v#CXg=0ru_EN+_5$R!pNtOV`A*==J*Q4}~(@3!n{(f;| z8a9&1hOe+B$zkYYUQ2mCz_M`h-wTvJ5AZq!%{#+5CECrO#Z(SvTrRZA^c!|RRB|w{=g~3E&EhX|&7Ix9ooqVnypPqz`0weiHtC_(RHR zCc^O^o~xyNLzRZ0M&~v;s-9j2?EnL#d)~8ryTy#-$=&GJiDZTTe3>#@B_hgJo{iz1 zn_q4_9Q81^gnG$bbwi${q7u!J+X6v$!6?2pFMPlhT#|kh6Ulw(!aj$qIyk?6gjyZO z^_#LVoFf+du+A#Lio}ckFL`rZzM%uXd>9Cw|p4?!Uj zUgUHwdOU8tWXPaU@?OTH0=K6VC%L2v_R1_3xVOfDK0LmE|lS?BEDB5?niGrVx3wQB7Ps{w3pI=#6 zs|QI`__^07>p$>DXT*;iQO^eEiL;!(Ac&d==Ee>+7n%h-!&Z8KZ6(zDC}Pexgf}Y_ z(|q*qluPl`va#Imn`64N>c6=&9lA`DV4~xqfZ$Aj>-hL*BYfC~?s8ZGP^r)TBt?eQ z-Ldyu;@f|&J~b*Zuol~=#_zM{t?C6i8yuwB@vA7 zF!~cpoe>_AR7l-;%#5gtaXExNV0ErE=*vVPM^_3Ef|=&@^qieydgZ`Y@&xe0w82*_ zp|U$45UUEB*Xdhbu4o>kYeS{N>7JFcMMD2?pTC7S_P7WI?<72yXClG z;S@p5S2QkuElHs=+&=ZTro8~+#w8ead`!S7_E#8;b~Sds-pC^DTa807&XULKa4z9b zp7(9WT$(oaqcWyAyx}Y#LfIg*wJ*+6BA$KcEWkRwS=wW#QY1Q1s!FXQBg~ie9_l%Y z%$!2ZQO!VBfqn}ytpVZM*rWEz&prd6zQ${)7t0Xn#+U%_>9P6TTUkiFp{E18-docO zcwFUNOY}hBNnf`q{V2+fuhUTe5(>MP@m-p{E;tGEnT2 zjvNL2!y;))%`N|RDk3}!`0>L-iokqI&!MJ+C4HGR<+$zW%&z^NazoK0q`A?{5j)gD z#f>`_W8;a)9SGXZ!~2u7C~1<|Wh^v`lvrlCwkFrB5LXP*beA!iy5V%?pD{>$N7uM( zcPay!w0y6T&>V_Z7qO@y%j1|yB=jA7zE{a9yr#f_i)@f}cC%qwVCR9%yUITm8`*nn za7tMKq9$~6AxH<2Z)4wJa(fR7Tt#4bC&Cypkwtd_B~cF?QkS}bs;;>Xs^NtoywLow zldg5Iz+0jmKQf{?&4i<4WPDlgU}FZt;D)Kmj@n^>i5pT3ScnOte0_r+n5}jg5cLC>I;dZk8ypQytP|JPv9&d_(%SHCI+RM}vgMQ%imt|41P5R*W(WBAGx zAjw*?s8x2J-+FSZM3_l@k^ZZ3G#hDR*tLZ8(`=y^iWmmI+sf5b6ZtA#Af>n88K2m1 zeaSU_zZ5+6g?{G#+52Qll;0bKLjq5G9OY!yNyVj*C19XY)6Nd}U@>CZmw(!Rdw$>R zjVY}o^9wbNVY~In^vtPY(jd(N`wT){iNsie8-cP#C%}}2X@Y9`Y^dNTy#BZ45C8D^ zq{@O5f4Z_z0M|H&Whn*DS=rlsREL$@Oiot zM`eKajj)-S2`H`|f@I^Xdc#zL;ugTCBfy}Iwu|u)b*DUr#QOn77q>BdS?r%9E(0ln zLIQJ$OL(RIymH%_rzzhdmy4ng^#+TY$WvgjmzrkA@Xa7YM;ul%!OFnZf_=z-3EYRh zFmF0K6CQ@j(?wf_o7PVLzfzQUy;gh$OCT42&;L8+klanD>*H5))Uei@$ChM;5{X6e zZjK*pdUxhKblZW}Si)v$u9-mqs{u&y3OpZ^<&D8~M}FeTA!LT4jDgeCA>VAK&`%L$ z`k(>T)f8Zc$F92#ysz>-CRs~AZeqFBJW$adF;cfd#ziZ{8Nb1J@wNpte1BD+VOV!$ z?POruK)qNs-L`3DT^oUh9IrB5J4$wK)OHrF^pNZXP8sFqZsXlR=RQ*_!GCabfZK=w zoSVx~*tJK&P2Lig`&mr3DGrIO0t!-QmJJyn58_TJtt2d1c$E(O|uf5ODcd6hR;J{_y~s70i#_pqQ!=i zrL2b<{ViahFLp~KdZ=a3B4xMrMXe7eZ}zSi4j*H{jsg=~_mqF3ltw1zYs%$Kh$vbI znq*?A{d7j*#Jse!1;_Jja%GeC&#}pYtoD8(7;KvGGW2Fyu?5|Cxu6!=$TTkv{l1d>d`!B2hmIx!bI9pfoZu*t{E8aXvXYyGNMj11p zO&_H@bUaIKN&AYH$uSpLSzkurj*ivg)G41EuZ?!l6fHz_9tDK;As`x(d`qtjX^wRz z-6nA3obMJ~e@__hkVl|&@Fk8$lmi9Dw~%^#kP5F&JV_$b*o@aFoF}!b)?I`rJu`i^ z`Ji(V82SPgMh4bU*2Q|&NA|z;wOEQm_`%Y59S_)8BLhQX+_i-sQO}Np%U;E_U?>Y; zqeQsLT4DFkCR1N z$6TZsF9RCJ(((h1^bT3&S^}ki4^-r^ZxWk>|>%LFG+b}qDa+(QG4}Mefw^i^6=Zf4Z z_Jrrn`3?p$akh7LMHY-*vCewW3!l{2iz1N4@uZ$ms?Cron2ISv!X&#buY2qau-kkM zX4ec}NW76g7j?y05ot%^5EfuPY&l8`UD5;P)9scEIrlJ@#!(~Bc3;>1<0JwgH8O9k z?NS17@2|#%F+~RyZ5YclD46;R8*UbJE?-UO7d&GBvV;D~R_vSLSHWEBV|<&Mg!;U% zVnq=8^Oc?-Hxg(wF}#_AL?CNj*Fap~;e=PFL7f6@D)SWsgy=Z3_i)sHt?sIPO#qbv z^KO#It3N?7%s{&LUTuSaL7`7i6og5r`}N;a^iQ!pl34f<=Cw^cE8Xn%Ztn)Lxk1Ka zp#9Qm!IoUSq{KMx7EaQ=hi*U(H+Ngpx@+5^N8Qz%s4zC$7QvcfYQF1Qx64@EIkGzw z05)?`z~6%Ti6a+>&duLkC+tKYt@7>WQHuXM+4POcihKgQ% zK=duP_K+24udKc*M(Z^Y6_+av1keQ0=`?^z|L5Du^g)NCX0cy@K6j+Cn zS4`h^P_ua;X9xPwvF%cPg);qSZ;;6- z4()3Uh%wSsG{mx>yC*oPzBS|D%6y``X~hxZ0JCHN zPvO9?5PQU%j4lkqStL+Lk$8Ld+H1&^*RyghXAwzyPMDi<9e@z4`J$oHDAtvCKQrDy zUBQJE{k}vVjZvC$k4qN#Cbt2r!a`*`5~#^T_&OQjeGr(k@#e&-tj!9n$w_*{5bVf_ zpg>_0?hx?A2S` z|8HO*COH^Y*4U{Y>7tO*f}z{lVUei*k*-e1LJrR@b$U7~lk>SyNN!)YdaW~)M>ltJ zdjhXk4@BHG?33p?^OwXHx{sOCZ|2-sQg^25+#>FGIiBSQn=O4QYZ4mVNL0dSi4M%W zAVDA$gCp+`9-C~KL))HCewym^871SZCY60c4V;&JoAOYSE)CS`XJSf)iO!6y@~$G@ zBSo{`L^uXJ3~?P4k(Mb6=#K;zD6I!B-XAE}ZLjU-i8}}S+lY|rH4Ai-%>)b^#Hg1z z@G$0k28ZPce_$rWqLhdmGLHH8&L;v_48DW@KLAlaGoaRzpz<;e$`O-S=o?QKekGCq z2X&pdpTf25_z)!-ku1Rzt}C?oV>N0`K#=j=KsvvqQT*dQAr!jj+l0gRQbR{-iTJr4 zS^LAmX%v&HgcM@nClU$-$i=#EszPnNBc_t_g;Y~h`8 zVfO1$KJw0mPpW~BcfD+Uvathp_xpTV;_;8p;!EVj{m4B(DXMW2ev3zuE@?V|aGUO;++IgBh%qi*)t<^Tb~ zTpB{~=Br6LnBCpQQLY{r%j{rkHfUL6=h?1bS5NL0HXz<3gVrLU09cEQ`a1j*jjh$` zlo}GK4~Q*QI^^BaaUOl;{#nvp*50*8!!QbXcoGvFPTKfLWFQfN;H zlYjo6?Rq`OClV4)d_Z6SB(-=N7bWa33G`FDN9pp9JJw!)e(ewZ5L8Q1)HXqHOM>m} zxrhZC7@u7+iDodzbNt&b%TNd^TeFZMSh`!!xnb=%Z(zP-VvIc0;^c+3H^l^z2xzG^ zK(78XXr(4E_?PfXiHNvc8lD|~itGlj2n)6SV4|)08q_H(klV_vtA{1!SjAO6qTkU* z)v*g+c1leG#J8z;@J!0SdLNwK2?TJdmhtU!dbv9#<>&)8SH#@)gjFNMWJx$b;*!}P zZD~y>f5BLR8XejI3L#Q*V?rAEZhx&su;T&i$I|Tu&a&{i%VZHrL=O=<#gd;LFZCairb@(~LdU zR_QZA=MKacG-GiSc)-RydyYtZ1MCB|v*8YlSiZDo^Cloa*)_>6MX@VVsJOm!<{8! zp))F-TjaM731Ur+7*tzDjt+Y);W^tI#-Lu-HkyI#<7O#W#bFM)%2=)x{{7C9kaTup z!a6Si>$>k=;U-bXy_`eXgOF>_^D;RpWhs%8^>#iq=ei1!++S*MKO zQOjKWD%{6^a2}bPk~SPfch7xuZOZJ_fI(Bnn&iG{TA_noUYK}6jmJW*ro6?yX8aOHRvd&8B*Xr*>B7w@>5u@>lWO@6G}fc)iik~Y zQt%l6UB*?W@e#KTaNNi;^L70jH^IpXm}awCl9*o;+(UtbIGgR_NHswz=U@{G;!KYR$Bs13d4G|18zvd^EZ z@?^eTtQ2|u{xBu#L!brpViD|K7L9^z)-p=2eC##c9g;JpT0U!$A@aQCIb=5l3yowW zYAnqgo{q5bvXcjmw(k?98?0qpA7c5$+H#|>8cU(=@tj;f#sFAje7+>SXs-SetwL#~ z{tLuAEhZRDab^BSJUL~!BM!v~u;x%Pla9F_zDc|&H88>-n2)>GB@0gCdOQ4r7x555 zhfAB06P#Oyf;&K4s~us-wdtjGn&M;%)`u)B4YUc2;9tzIAjVpIjr|l=#G0MXoK}Xo zSm*Twyn5?Mg2Fn&gbD?#l+SNbDvUa8<)_Rz1P_Z+qK`hE+7P`tWdPHio?mHu5ZYH^ zMUCif!;*kV5{?Zn>acq>6i6^SY2VzeCz?l)QlHp%p0j@1cx%*cXmWVC=y z#UI2Qd7QAY;o39#-P4FB?GQ4Cc|)OX+rMmqKV(PQ7w>qmxmd#TW}+rx*e5@{bYEgl zg(^z@bG0!ew-_@sbH`hFb%$EooRTvE^0+E`B02+T@5wBNSK|nBIP~7enR(<;50lqk zqpVA-(RsFJ1|EaV9EVm>)R4|r>cgv6-A*@(k}U?CWJz3Yca-XTuwQ|Jjh_ zkd=(7HzAC6oN7!JuCwjGESys><}2K88;s+dkP&lP!N;FZr}W!--%1Bkvd4Xmh9ukO zkMj9^yCJ5CQKv|44fPiqCa8+`pEv*B7h%VQDL6NEk2*#HKxPh+!2~r6b{7j`FF8^I zTqtV35d$o!Fm|Ku*v*>Q;IUX9V)giCTHDA8Y(u#iI)XTpe8Sep&G< z%oYb5bbeTnVmz62iuFgaY25`QAn2YckWg=G@hol=(r6GU%yt>_Hh zR&@?tnqE~?^TOh*kt1a|XRF)(D+6m*50u6r6`}k;K|+;Bq#ACaxR>LJzpypj(uYS- zh{*t#}Vc~Zh9-WXdxB=r?) zTDZkV_J0)ZoEmE})6D-c>0@YQ5Us&a#;J4?8hU;-1qKFp>WTAn(ypeVVK@f4IN6Zr zhhe0>BI%C#Y)e$vzVl(<0mJ^}vC??uyVFkkj;?H(N#$|(CcwiJb6dBea-4-#4_IKdixVtnJwXTgTL$`6zFu_& zi>6CTyY)7ZKS!tSjj!CD&Y$MT=#p6#@NE>wrIMJNN=|qzz59j#k(5xw-1=g5LA^rv z`?kzhgN+^*)!Ojre^h3U2l(QdgxsLq7CQW&MF<)tO9-iG8Y)ou*Sg5py3NE*{-~7t zHr#aJnfJr>oz(O=;=a#>jY#lLunM{mmL?C}ino}#U(*y>@w6y-TC5lRO!`)vFKP*p zL^h3X?^_Svex7{HS;B44L5t5*W$oJ;k55vLl^CL!8*L^4H(<_@UcXR{C$?n0!SZ~S zw92Y`Kba4rreMZ89WVg5!@{->b{jd%s^Z=3rqI6PsEX)bKIwSSl^Fe$>6p^HrRnKO zDVRVMp)%NL?3=))OU0UVx-9ZN)&X-Sa?kf~d1$XI%M7<)C46#)CGL_xcc-I*k3d zit(MW6dS#~*t^A)E%Gz?BU5B9w>nWf`%Ate`|jMhvgP+UR~d;$3TBWMDJ1rl5P}yv z?pH#2MG~yOz_e!y+8p6F2wmk#gOV|OV)`h??)=Hs=G;Vi8}KEyjI*6%P2-CBvqgTn zUJxDjR52wC!R|+UixJgqbeK{4)Wjq&E_>pp0f49It5!|&YcQtpxLF-_Oc#L z@|20(h_#=#MABYW)fnxZ=L%2fc7@>-tUd9d9)k{S=s+ju+Hh2NDG!K=^iqx9{De~Khrs0JY8ed)P& zsDuwhjp9mq_k?w{SNRF5%+I52Qd599PYCzQ5TNTtqJtl!bnB(f2?MVUYIM&^YQWN1 zk!=?TviXCZ&WF>TL@;FHJ(RH-gf{h(?5~?bWim2qyU7Othr5&elX21%Kmi;A?YKgC zChRe=xQ7H<7BK4!nu-i`SKFG`Vip@5ZBoTvW<$Wtbc~e{?vP`XXDI2anaO z2cN3wGK*Kdd+IWa97La+wUWK|!Q*oq*(8qa8%F&56|ys@SwS&jSVVc{G2}m(Nqv!K zjSH3{C9gza__q?pc5#vr@-}eE2(ZazV`Z&(^~aEKk?Tigqot#ao)_|a>CDDrqGwt~ z`y`PqG~dHU7*cM1>lrd*iWj7Osscs2`Y>%K@n2Aakf@kK~`{&dJ_*9lY#}{`1L{0tSNb!cI`7ZJ{17y9_}C&ymO{ zR4k%?*w0$wm6*P=X&bwZyHshwb&n$qh}^xbPOqpK?15EZHkbeU0a3(c#J$zFm>!7E z{bdB*#pT|&td=C)GoLUgn+{k;Np!;TH4%9%tr@uygHSbC7&42sV3J<=uK6&e30|Nm zc+SO0Lov)__{kIlx;GLc+@Kyb{zvc)uj52pwZ8))CWCo#QvYl%Z18_U2epss_pEyD z@@Afcj4-o3X_9ZXm~0(%H}cw3yr*mKQ(yKom;5sEYK_V}wgvrnp9bHQoxQ6@X^Y^L zkfJMt&#f_yqP7YmKk3suN9=IU2!OFP{)68%0e{GG1o%8bjc>E^6m&xj)GNAy^ld3T zXZX)XVr~ijRWUd@MkBM>>KBG0n;#qUs>et&q;%wF4ub?JC;M@nkE>>+SeFnlF(&7O z^>^)*Hm~1TPp^UZneqHu`k=|9j@Vwl0TLFkn z+d2j(74C_tR^v*`KZsrRRcW)m?q$X5pj;zjph7QaJUFU3(GD`!_;VMY^yd_ju$(Vh zN3Lwn@aN{*=;5I#P_g3NO!9Cjd6|YNJ&~d#Do7lFBi>CBkn2Oi@SXR3kipb^Oe^KK zgRhn^Ybbwj&?{Ql5~R{2FWA^v_{uAep@i(hIdgDru9{#inLD-;jxl`^=b{#uxQ{mr zR+1*(rxo8))bTn*y`qQ#`R&fpW4Am@;d>48E8~feIOsC`d$cNdJEf}=X1+5E=xq#@ zBu5SgqKzFYuaYaLViV9hZL*XrFXg4EL7CO}6Ce8?#dfwo4{$gks>FwK#oGkg3DH^l zH5{VPd7zyX`=X4J5r{(qhfB(EGm(A9IRZ{y&<4R|ZSY zJ107GBN^`l@^u&Qyp-;P*X~#}LnlS?KLWR8lN`j}f(r-jpc#kLFw!L4zIu{+O<8^; zOcCyZfDMRQieR`pG;EY#!G!rfk=)6atG`PBX;c&;%^P>xBMtZfUlydsGP5$&_j@+C zKg^);sBu#uRaEo3SQjfw!q# z2{p^{vxqIV5Euc?u|uX@$tDK*C*2_xDpN(6N2iV?+gcaRH8PINHyMQVO@3&7Dl*#Y zeinvS0LMQY!aa)%kbhj35Zq)i72%CS`+4HYwui8ud=|n*ydvXy1nRkWJdABlRy*=0R$3 zc`K`iXR8AUzVEwd_NXmla5^DYVZzA6N{{=Sn8D(cE zt)Pcr&!tP|RuJGLvr8Bx`VaokkKIZaOr`i1`{yCir_>sn1mI;kH<A|2`PK4J(Rq# z;Sj-wBQ-XZYw2355S_R3eM6?y_oR3V0AceSon>A{%K`fd+FrB`fG=ar^9u3A@}}@g z2eKwTkdOQ7K_vzq*>RMb^R>Pze^+>`E%}GeeD>R`&6SOC*JZKL# zPSGeOI~^gXG;I)rq|1(UkMSc=S1OJkN$g+3xUXM+nuiwqwCG;e?HdL$PAk;9B~S&* z073T2%g|eh?hI>^jLJi6NhVftBT)nb8o94}a_$t6BOECko|R z_VKi>PA8Y(LVO?@gW_}KYQZG;T#gKC^X%I8`LbGE)+ym$%cZDz@IjR*R7ZQ7wd)-% z=;2nYjb zzguS)023sWZO2ISR`+TiUiS@~=CQiau5vnjPaU2u$a3E~q^9Chb%%*_6y(Y|6ck8s z$g@tbd;fb>8VsbvR}jz=#`e0KKTQ4kZgLb`WbY$DFFHV$@bDj#$2#L6s{_N3xM@am zH?$KQPBRT=N_?w<2lffZLDb|FO50Eb%N;-3a%r?X0{G32`kw5NuI6&Xbt*Xjm6BZ= z53(wA54!ZANQd8!EsaVcu~(Nd0pDfPQG4i@^=i-Vh5byfW{DEOAo0%UTBM29tZT>i z4*0zJ6T@We$^&_5Ne^o>fwgSa3L5sd&=~YBlpz1e)@Dn+$`+Djlv8cnwo4dcXd1-H zRoB-5zmWzKJS(S?e*yW9r^BJWxtwl}2ovnIXybb3T_(sv8fi0zQf&>+m*v+WROjvu z_y0tm`UfosBV?A8%m*BL6;dTy?kj8jj`~8g-1kgJ)wYWk;&0pcfM`6F3wC$nd^Qq% zN~&Q>_{Cx*jU(uJH~jd6mz9rxs{T%UK>xx@cv$uC+1E2iZb9x?EP?%kx8^BR%$-%6gJ?a<^t_Te*}v^p%cWMrfCx)n+|) zLq6`gg_p-Ptq9wPa9;Zv(hUF2XrMLjc0SFlQ(9{+v;7rxcq)%m*S{BX*J9LIgxbXA zVG=cSK0cGYYubzIL9ltLZZKkm=fnegs!7{ltIW&bSnap952f#&N9jVn*H?FJ5e@iiTePFB}LMU(m2cmwWPdSb(u9FqM2S|IY5 zKA*qU2tKPv@AduhqH1ZvAp7`;*pj&%&3MO7*Y{X^X0nMzExLV0^6K@zO|&B{QV?R# zH-P-CNBs=gJJgl3LF#+9b!`JJV2&SJ9(VwANEts^+vw50p6QXDnV}ms61a(u-O-T{ z{j-L1W~p_gz2hC8Oo#7o@hRm#>5|OU%6>T3R8!bK;6{bG_W`L27hA$kGj+gU6z4cG zuv5|vk@V#n0+Nz**t(t{ou?j5pnJ>X1aA`C z%0-jlwk_%DJH7x;>(zy;NYJ>$YPMvsqU(A^qN4 zoo@effmz5&3_C}_>7yEWs9xTS%X6cC=_i_+a%ODQc~x{@L4W z8&K|vMWQ6R^b0GJ^Q%vW_8{7Fa8*A@T`orzD^3$b*$cx z)lAP=&{|M%l=r3BqZSlsb1`+Q&vaq|)M&G=qT4c(e65U6t2KvfaQqc2!^W4zRFn!V z{`sS7ewKK{b(V5BH`*JVDF$X2e6iBxZ;Wn0F_JaY`3heORv?F3l|^z@TG?^Gz6c!* z9t({hn3w5rqyXdc)KDuagAqBSp9#L-&`5{(ifXdrYEvC{ZAG@0nj(j{j|80mP4fXp zpm>`qaubU3Y~_^L$2dHXDDjS10CxEhOPRg~%$Ynh3BZe1m58}2w|~DO)o6!9gGR_w zfLLG;`EQFLsLNgJ;Xk&FSYo9EN6MZt#!Tca<=mgZ7qR%9n4UtgQKNR@-Ewu&bi7Ur z1Q?-)*vA~Q<1xV7?mExOn_;WHLxRUz=m`;^^H%VDwxB9Ve$gsIays6@|COI8tTZkp z-?>WRTVQ{Ck(P`@c0f@p^c(;$2FC72ooVS1OyY?` zH=-!O7eDn^3AfYC3-5`U?uNg(+u?#f>fd(tkPqPQb(E%&pcFpKRAy{(aP-~#dN<<% zt1@Ba?lZq(0)3%jv?rMV)|lAK;X~h!XAn`-rZ0rU8I{fJ9l~YilJT}|mSY>16`xh` zWTtff{H;N68F(7Ul#(l@1>z8xvkOxoc)vA@E-VHu;O8yoZ-gzwS3-pEU&CPL|uVQ6GJ za<~P74(h0#bAHWKBZvhP&F|AJ9mCh>be!GsjUmy~MSh{I1Wi#RxzGuc>xH&>-y7$? zFG+McuR)y=GM~Pdnbxk3D*R=3=`3}-f?ZF+3SpoQ%5%Z|!*h|z(c7{-h0rl*BLK|d zV%oyU*6I8<_Iql4o&iA;_O)h|`Q;K4zQS!RDt*6qWjrZhn$B)QcCSVA!F#p1)|u$n zxp(!rc?1_s;uU5yvV;(W)^ft0f~JGaJmuXzBU-q^k; z6~q(}Cp+jqwo!w8B)|-6m@o0%pBSa@d_`clsT6gM4_l7<|aSo>T&;#3S{{gw6!q;Po0rc6qBBGLc%gCQ+tAjZA|U2}QklA-FIM9jQa z@CjfvO=*NcUU5Zok7K#w=5;JX77Xv>|x?4Adb@&x)mM%&;DIx*pFOFjk8M ztNHGlb^E}Jp0Eu({r;)YFj$+#5KUKND7N8)Nktce0VCM}E#hFRN@@q+B^}ja? zWs*nq%;eH9xs|>aIFKi>sQ}3}dA6bR`JZhB7N}}Lgv212 zjNRMJwVe=g=n?;v3oYd8dFReX@m9 zi9NA{JZzvM%SGh)%WFkH%z7n}0dD4{2iR4Xua{$o8DfJZ0rSEb-+dZnMaH@!yUE0c z#J~=})l28ApTqx+9 zZU(TzzhC4qZfDy3{e~3pXfI2dl;;)XQh^_OaQ*}lx>1_xo_vGsi`t|U$L|CdwyXvI z+LFxj9Fw%FXoA1m`-qR0Ij7!83pTerN1D8MV|v+oaS48vwM;rn3ghn1eoo?%Ss`gy zgSVAQ=Q2PCIR@hDlKAncInSCZ$h#QSwUJCtLv0jui12E6u(63%$j3usiL-1{PrETp zuNU1KjNdv$OREP11xLCf$!$*+gVpYvBqBjJaHR_qrzjnPj|^AOj@k*M@qBMcOrcLH z(0u-IpT5@X#XdGMpgrlEQDqbhIsxUn+_x%a#JKUn`Q*ug*53F=E$~_WwnH9 z#(f{$fb?TwL%pb}>zWO_AWA`-)^-?w=efxKmd{jH$5ZnS^{3U>PnyH;$>R(=NfyJV z(0V@OzWser9lRoo)Gidxv0$t5THY6tM@7Tvgmu2f6qLT=QbCa|Edq5a(i4|Fw z{{i^N9q><6mI|g4VL?RxMcTuJ8hy*tumM8CX+^EERXfwjcWV-)F0er4IzU)@J(j-U z)Qmkg+wBZtfsFjEtj9bk$80jqhp&*o+P6v~E;G%yj>SA(PMDl;kXN6_LF^^}_0=_3ZEDbiO?INo zutW_R)g^o%JcQmv2Vug$KZ5$CQo?<(kzW*DVc7mc4f~3(Yv{i5b>IN|Aj+8uP={Yf zfgl#^_R#6+$1Tk84=o6!$I4J9FmcP0t2%40<5KdEidEX8g7Be#?|CLU=)ID~8Z395 zT1Uh&l#yl2UtPiFH!bi?W z3`Gsiab+)_LW}6|BMf4@-Y6hdgM{NqN(upLcR^9+B>ZO0d~U;oRr>c2seM%b*bpP& z>Uy4>4U3}7xHWlcL-b0$L^#Z`dRbZ&^*Mx^@im*;njqJy@C>Ue<7DHCnr`5q zVd&gZ`NH>kEooMquDZ-o3>paju$42X2#gT&N_h#~p$wT+Fr%K}Nfgtw2H)(rue5vu zEY5(ZqCwxX=UYx_Gu977v%V3YwP}){HuUP;4|c7ECd!~1aEz*{u)Dlwt4#>wzIAl$OC6#j~3kXO;YmbpoZ!2fK9swBX<tHo?8gR;es+V-?}U#*-KYJn8F*lA(1$Da7(aW?+-VIay(^G+;@=FSj{M+CLp1 zYsgvJZei<3x*oK?8$#DZKAO~TNh9{(h%{$<*;+CrWsH=i;TJ265RU~i?-Q9wF+^Sz zTjs_jfys=h1mNF|^*an>v0z?`<{{*&S1?U{gvy z{Yq#Y#s|X4z@)520;bDjjsHQGAzhW?p-F0(g*9vto)PTFT7v&!FQLUdhU_pc0Ojzl z!zy^>^lf~##j@bMqtUy9yre-Y@THYNxF03Aaw*y-(f6TUHEypI@|;7o{cFo5UoiKPUL_i4ALcAFw|Jz{J=4ro zGeZoDxpHw0GMeh(0UZ+bh~=)D6>%i9xk)&YWbZvK(13O!`ZXYyu%ia_(u30yj@gM{ z^lq+wyU5Q)D{>^)Huzoy6{a|vIOh#KMQ?$q)R2}hh_lW9?+ zxXFWPuP^qr&+;7vq*y$uLnCOk{z?^MK%|sURs_Yr>S$7rM@fr5=44oSmH=V4EJBLq z81!gtTg@0d6-Jx@8@09v|E=up)a7HVi>Rl^#k7|8!~y|mL?ps?yJKeV9PlG~y5MyB zHti{^_U+;#_`tIk#cv!l0e9P-aDq?dwo`X;oLXBMsDc!#JQbD4mN|%}SheuKJ$1UR zP){asSRFQ91}4up1UZ`{WCo{<{Q|3FJ0k??ZW0fE07O8$zahRNK$B5%40=&^k;o)% z87Ok{y_dzsHuxCwBDmFV5wJ=J)@JLFei>Huq^LKfys3dd8Mk8r>A(=qz?mH&p=^zw zcE0?pXDIfvyBG^9XB;ar3&9&`%%RnFyEHYV7J#;>k?a9~sUbWKMTo*fwq;?|DW2{! zk_|cq-YZ%Yy^69=-_Bn=q=mut7*7a_74W*6t_7ll1#F7M2Oxy8#+0BQ(@6`Ejb1V` ziY2#WAP+7xbQ2X4>$Wc^sUdDHcy3;iupE&>QGP2sLXwi zebv@61dOi%4EC2awJF@3j-y)HGi@YikTc*s2<)$dvO-(icL$*bUJH&KlrJA_B+fI= zjeDxDnIp_iEh#ti3u_smwE+18Uis$Xu#+qn(sS#WC?Hk8V5bGHiD zD?0tw>bFrV=`kV|LpN9gUL?%#Bg&g^6|BxAP35rI`pBafT7eDNg;qfe%&n`k_&hP1 z`bw#MuI=aU@TTBjtz_XHyM+vGq7B4egS_@QIJiwErpoTg9PBMId~vdGCOyY26oAHOhiEP>(6e75|@Si1X+gw_1%+1ow5cA6)( z6N9|EcC9^fEih!v2mY9kf&!ML%)ez0k5q$?zZKaXXe06iT?2MQZ0(I5RaH$ep}v^& z9?383jaw#s|CDaC!LfOCWj50dWJD%>oECBeNk~N!gv}966B;+ZanMfDzQBRd%mQG4 zp?F6v9%X?A?5sx2C;c6{`8Vt+`AS>9;6rR+Z6R-s3&+ba;}wO{ff(^M1kV|NO3wy=EOV@iXllVg5S%on&}H`NVgB z=(v-Ij%KcVGw_{JMbL*z1b@|g;$U4emxlp-K4=LyczGMK6Oi(@^-Q{elv%O$VD3Cz zyQQh=Ixpy;a>-6C*S9pHtuK}l8Y(@5u2vfO$bCHv-B;h9bEUCQY;B9`2^Vn@251fA zt*?ztq*@Jp1vzd+#TxJ$Qnkhwn6LdcMby`Z%WXt9%76YL6TCLE&?zWXpg0)WqGu|A zYgb-6oCiaS@X&~kbjWjgzRNc#D`vqo736vPO{{i*hy9DMcd* zoX%$6LgWXiU;>u!U?wBdD!!Ask06}{=FFKL15p;zu|{c{@JiIN~3@4(VOZXLb9QlZ4IYvNJ1I zpb(KU7~P}LeMIy@Xo$W0!ss^i^*Z}3@lZen@IV1RfEt_9CA=9B$x;mSZ#jhXa@8HO z@xV9POo%?i*o14_b9y4I>jY79%o^DeTK%@8%L@5IVIV{yhTIo#9;h&o zAaQYS9Jd?A1gZXASNmava0k7p^~hwTSl!IC4}hf#5#AD5_B&9G83?KxsG3TPi*i}T zD;+(bN0yF5wY|US@IKEZij`>s&{#7G2&0E5sdRxJaUM)F{ia<~bMG1|Pob8bDIr5N zUw9yF2`XOMG#&vJs;cW4@Ly0bC5sKJ(M1C!&z6rqSqm11;#FzU(vaq&7NeIC5eLRW z&S-l+wF0N<)*v$jNbW7*_%Lz>fd$e|#-_}%Q%Pf@2UE(|eE7R?ek=lC$?+`0W4_LP z1!UglytofEQV6(O%fY(H3wX#;$3a!|t7-c3DZE!)!Z<+B9vop)wd2Dwp_}DVdLA+p z?4YSQhDD9<6-8QEoSp&mi)V$E%HSgU9w(I6>dfpF{bBCVBIXoywLE7twcs8K6^WP3 zD%AcRiidz@wjKus+8wh7;&*S)xA^LYJ8ux>wCiQhdCNNgKZgFW`rxE>s0Tw2j%$sU27kFl2p$5rO28-Lc|nPg?oZF>gqg!r>UzW!zi}ai=Q(A?8Y%Jefhi&%GivDj^$Ekv$5pDk>(thmMaY zOpReP2Og^=0$X2S@IOP6O;GMF045T5!jW##LQpMlpl|(n9YeIsfKi-?e-sTvGA2ha z9J5Ij#l6u4Ixe9CzZKpayvf=iJDb~Iw*qal;+@reMsY{+D$R$?r^O)?@W*YUk)Ae} z?!rax)JbW|Kxex+i<9h0E|!rf>80XDZNh{cc!34&H-N+wCEB(9Ep<(#`+)Y1_7#B_)kumfG)RJ#AJ+SehskewP;~A4oC|@J%vM35$bus zu!JXcVyAvy3)5|2wRT7u=%j=gD=xU#1i;Wx3nxK5j(ld&e;R$+U+)j?OjlXX@=xGYSY98WZ#@9rPL6i7=cQwWLXru5ZLRi?n3Kk+P=M;$;D!&L7$Zme z1!1CnhK?e^M@38+C~!hDyd)wK__oDfCS>gfhMZD{gz(JY&H&C6(fD~A;@Pbi%5U zI^oI9yf@6fCoU-jt2T4hhqk@R`opgdeHYG}9kIH@e!=dM~+%MzI&eZ0D;U5G!P>! z+pE1_^ap3*nUuQ?76`8N&m;|AG5yDI1e<+NKK@fWE&(=<^mnN8Ehb1~mKvllv?cwF z3CC(jk5*iv6zyG(9X5m)ZFn%5$}caNBWZ>ljafYx48Z;^l-WOO_s40>b0I=N>% zdK|gqrO<_*(I;$4oo% z_O#CR`K_&SM`a;}kmZ_2*J=-LxqFsW`5ykI>LsBVAe*YzOTjRx?81gjhue?J?5orF zA#bV%Jr}d0Jiu*g&ty?9I;DPoFCa|RyTHW(k~-#4=qU|)YMaP*JdGWDImMprW9E18?CIhs;YIl~Du*+fVMk%r-;(hWJ5^HLr5?SAC#=8-`kRQp zK=Rx&U)t{qO?zE|iGi=w4@B zA+~pv2}#A7n=$usCnmlKF+Z1ZgQnwi^U`Hd=1iz91gL!eJv|F=?y}CL>NH%Oqc)w_ zN;R#Nwe}O<5b}cx*KaWsMUqgeLXL1RQ2@UJvOSy5BW{i5PC7& zsbb-sRE*zt@gTe!SQ|{(=lgchOTBIXwEsZLV5q?;@`W{!6QVhf{pc=-$Rg$r-lH{> z_74^|e-{Qpv?^LWZuObUWdwpxx1J;MTueGxaHIT3E?Fw!?9T$vif;+g>)^czAhSlaSysK2l+-#= zt!Dza>kh9ecEIeXmysK+m>M|)R7}rI3nc7H?`0ehE2!b!%r?y)&7MpR4vVs#$M6(> zHNN<}XJw0k40O>|OuKY=kSCR~-dT>jqhyT#XLdv_?ksSI8t4MMSjByZ8~n+WQMX#y z0eTAvQm7ws+lsi5j<$6G{i^|k&6Jx3j@dWQGM=dIt!tr>`sHY{tCuMlRkH0JfCLU} zg65hB-?M}Rz1108JQOBQ+TYW}AQw*dI6jOG?OpkZ?>i)O=3p6)lZ_iE;l*zVN67|& zPx)I0!i(qcZD+bse{a~1h8#^-#QnQX*iv_0l!d{3M*bBfA$*v5gt;HysvePA_&V4n z31*bg>nsp! zBh^8;67gYcaWlK(4ZqhXS}(r>CL5gU2ojWd{=cI{yEXISMy{2saKeqn%_nhO8(s*u z^)Q40$OS8;>?srzIo-y7o^8a};^G0KgjCOHl$@GgSAMb3@j;|7f7$^v;6tLlx0-1S zL!~Z{+gn(Iy)%3L+$Vz8cTa7K;!KeVQ4~Okn)00gO0=06wyLwaV9)Ct+FV7w5>9J&J7m598Uz zJ5}5Y;ws+RMOvy3^#@I!l;iP0UTR1tEg)l13JBy^x;{L4M%20j$5u~%oO{ZbVIsyCNG0EdhfXAZh-T(44>-c==t+N{`B*1uUH!7+7A_0xQTrJ1BhC$Z z;;6%HmJ;r(5f>*phGZ3Ljb$-&YnoUN33;@mB$g_>)Op=wk&`-$Y*zWnzr}^$8;4QK zVH$!HNBWCBwG6S10*CC;ue=ln=RobLQuThp(B2=0N)&E9l|`eOb0yi7F}slkWMl(t zX=dhQ(%Q{$26gR4lpZ^|r~W{@DmkC{E`+6P%5v?#nsQo>)`b^4)x(aAyQZ9S(+o_K%VbE1kTH$RjPknpNd>Q$TalB-pc=N=8IyuZz0ce zPVkjxD)afafh)&ZZP|G~jkJK=BL{ZZbQOj%-P~^9q9e|{wq|8fwksDtzeNO>sjF+1 zj|$ns_xP#NIIPRo1*fufS*6f=9a;7VW`a?9e>a9WCf}wDo+H0!lemNLi?isqMre z$bUeoWgU25zjq;a#sXn zjKFkS*f3O;koVIQycA+hJRwQ&wJ060Rd#SjX0>7VLDbUtynoy|wG%4%v*^N4=uh*2 zNkSZiF)qXXu^>4n_#+QLE z0?e5_kMEu%fw$|`|KSnlLm7G->r+}EO~PT_Ks#NS{7hp%J_n=8TqoAk8c#AbRj}}L zp<{>BQs#9nhILmpD(%9=Ev2!GfGfLmSYTQ>#DB7`6i;yZ2ATBk)|624J3;vGtV{QF z-eCjIO;dMV3wjty8Sm?BeKz_StuWNIIS;uJ+DdOA9`F|Io81Yq~Q zCDo1~Nmhp7Ve?q%H??5Pn;uVOaTh>MC1V-Jrd?kx-1c(RhZE=n`kGps(j39)pR#;H zHx+w9oUmYf8fH+(3mLHgK|4qz1pSI*n{qf=4<0x(#Ag9S6oY@NT4rywJ=Vr@mA*D4 zKZ0IboC55oWV$R!~lm z!?}3LlIA!n({w&%Dseu?Y7-HRPsErfcB42;AvWHdY|ZwGk(L z>mx@bjcdd3&l~6!-Sp2dKrtmrPKtj1WD$Q(K-0OHWr_cNJAgvFcRR(N(w_6XE6&SaWQs8hHWQGyU+w>R@*a(!%x|Qm1X}O4^MiWRUYH%9>eS{qu$~l$cTc# z#gJ1l>Yuj)uMW<$@b8{J@l3-7Gq5x_8Zi|OF%!dWxFGx7AOExVLAXUUF0dr7lu8X~ z$Y10KzWQzo)&^*alYevw1K>XVelBl1ot!V$Vn;GnycGOM%7 z<=Zs>=kUvSdKa8jZMNK8RDi=J27RL;rV@;mj-CejDr8lXu7@5@$p_stunPU?DZ4dC zksIKZFu2P+`Tj^y2gAIK*f=BMQ;PTSn3EmOD0SK*#-KN;J@TtIdRb8i@)GlTY%bMO z9Dt(pxc5BlKrvpqU*Xdy+X_igdE$g6u%oh*kDTRilJPRnFuerZYB2&m3Nbk_IkqOj z2bpDMvy{nK3bzUbT?VcRGJ_M|_&7#wIe~ApI zs^kKuX@Ak4HH~tGn?MW3Y6%Pt+n~vLK!I_hW??aX7WlL1wNfFq7*YHt0FE#(NKUvd zfElwU@r-t0EJayZzYeae{>Tdg%NN_q^Z5a&=II6%{+^DLOkwmT6^EG($=bEKlw>&e z#=%Z?m2R;DnyX!=!h|Lvtj7P zmdDDRS?!>hqLMjBKCND?HE{;Tff_dQuQdQ1YuccJPBp8are1)jTm^TUT?2%(0KX3u z9256a>F;e5I#k+;t(_*nD^on183k4XSP^sTWdcczs71i8TBE|!|1ckotvuiuMJY^V zrsb5WH~(xlU3hQDYomph^cBVTo`{lORh_4FU6rXeC{#twVq7HW8Lz~&%qk1mQigru;r=Oe@wIwJYKcr5@Pb}BxRY;|aB z|4qhGO^BiF1019IbV!6|soI`;*ExQl>6`YHNBth8;I-)TI|MfVbTA~eX&Dw|(!7AJ zLw;Jl;SQWatPrnh>4i)Uw;fXR3hA$Rc}j#9PWuc>mv;frpskoS3y_c)O_b{E?qHAF zs@qT|@RiSkW-5>oXaU3O(N--@#UiFNzm8@DMs2G-N?nr+C)J(3*dFh=h&Se6vh3+B zhXMEgUou$oYzq=Fz3y5`3S%OgwPFzwN$5WvuO4_mZ9fr(#8CucSh};0`DfdVwK)ET zIFLm;&Wgb=k4Yr=abS0qwk5np!^2VmuU?=CqYKs;4vO~#m9R?#98plbPBj)z$fXb` z%X0<$$JG+Ba|8CiSfYA(bDW-4oI4mUv{nwT!krO3sdxFVQ&#Lx{hzcUFYO-6h~6lZ zl()Y6g5^o&h%eRo^~HsGi>;Qh!@2DrKQ;x-)bK8_Vh&_?^6ZGhVz@-&a?1j)J4Z@A zY8HKUmU&l#98QBm!f#F>zp)pPDg3J)Ox=!F>{xY5_2#s{!9N{X*L92n`WXHqMj>~t zl%9~K5z_xsyc$*Z0MRk`cK)o*A7x?ht`Zd0wNi2rh^I4SL9lmWxH|o8_NTwhUrmoT ztpd@dm$cs;R0iCvhYtl^q@xT^4smuXC#>BE`doFr<~w4f3*YwvEt%Ha8xwj)u2}Sn z#qV3xgD`P7t{N3BUFNGRR?-kDwrzu}?6Ag<%jr%*ey`_dAxl_wNZzHjQ}U++wQXy_H3 zzP#m4uHjv0rCBU??p%n!%X7`~A{{;Ny}=o0(q1@DTZy>bpf3}PjgraC#c(jwx1>G2 zv4pbmsn7iLxwE_7-f4i%N0G6XfeqZC{-Um08nQ)`B(4cVGI~&oi}1YOIrGLg4@v{R z@57bz$!ir=J44RVwS96u?j4U0LV`om3r2QnwiE?PZVYpVo>LXCN30RrR_T`Zt}n^h zv|fKv2#y0c$wDq`;lW^JGCuGR2|KOj6o@h?61j5HYt3lZqG zryiCx0bONlR<`zg#DWhP%%B#~Gr3jDLMAHZN8DTlAdn?88Edlza4Vv9=m$Iog4IeW z?yiz1Y7G@U=OYBg01i{a_bYJ@6}hLCx%_iYT|!GzGeIA(v<<7#m9UwBibz?{o5{60h-Z579h=Su_n$?uP%Hs2+F_h zogE)+tA~LiH%7024;QEUm#Y=3uY+k|D=UbBV_&+R#hdZo7969)%|(`o-h`LaMJ1xF zK{M6`lYCCMpp*-Ow|ESX&6pFJWMh$50M;x8Y6>S#th6C&i-Y&JjmOB88Mf5nv^@ye zebjaOFwR-wM%qbDn13J8!Q4dn=Zk9M*&&kyZ;1j2*bGg;1(NP3xsFcJZY>z(+zCF$;;w(bW4HaF-m#XhXP4ruS04-KDLgEagIiV9TE! zINo*FZ$yP{n4-7FK1Lx=)veRaio zZSx8L8;;YG1&hxKOPjMB)fRN+_JQO*q}f>w-JfVl2)_^md|59lr`=yhP8!dvuKD>N z50OkeflH7J`j0RINr3x{pGLW^TqnL!6g~@WQIGMMYBvFl=qw`gm-c;ICqEFEa63up z#t8SJq+ps>+}02!yHqwO1~tJ*%=ZvNVF5|HxdvZxahUk%NN`R?_3R2LO9b{@qn%Xsu9}V;{=N22;))OrA+?4f>UCa(`qex z4(_x;*t~?OHgsYeAU_m8yW+koWIKZDG*BToL;e_}J+R`i0WPtyM|DZQfTZt+!R~`HO-Rn0PUf9~E)k! oh0JH7T!A=wXh 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 z�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