From 7f39df641306757b3deaf42ea196378c28dc98a0 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 8 Sep 2014 01:24:43 +0000 Subject: [PATCH] aufs: Update to aufs3.16-20140908 svn path=/dists/trunk/linux/; revision=21782 --- debian/changelog | 20 + debian/config/config | 1 + .../features/all/aufs3/aufs3-add.patch | 1807 ++++++++++++++--- .../features/all/aufs3/aufs3-base.patch | 33 +- .../features/all/aufs3/aufs3-kbuild.patch | 8 +- .../features/all/aufs3/aufs3-mmap.patch | 226 ++- .../aufs3-remove-circular-includes.patch | 222 -- .../features/all/aufs3/aufs3-standalone.patch | 12 +- debian/patches/series | 1 - 9 files changed, 1701 insertions(+), 629 deletions(-) delete mode 100644 debian/patches/features/all/aufs3/aufs3-remove-circular-includes.patch diff --git a/debian/changelog b/debian/changelog index dec9a9634..da7e9a38d 100644 --- a/debian/changelog +++ b/debian/changelog @@ -44,6 +44,26 @@ linux (3.16.2-1) UNRELEASED; urgency=medium - mnt: Add tests for unprivileged remount cases that have found to be faulty * [armel/kirkwood] mm: Enable HIGHMEM (Closes: #760786) + * aufs: Update to aufs3.16-20140908: + - bugfix, missing mnt_want_write in moo + - new ioctl BRINFO + - bugfix, restore the lost unlock in an error path + - allow deleting a branch who has an opened dir + - bugfix, stop passing an error code to dput() + - possible bugfix, ptr in an array + - implement fhsm (not enabled) + - si_files has all opened files + - bugfix, use id instead of index to identify a branch + - new move-down flag AUFS_MVDOWN_FHSM_LOWER + - branch attr 'fhsm' is independent from rw/ro attrib + - support for a branch ro+fhsm + - fhsm notify after fixing inode attrib + - bugfix, hfile test in br_del_file() + - bugfix, pinning in mvdown + - bugfix, instantiate-revalidate race + - possible bugfix, temporary d_inode + - fhsm and br_del, allow the root dir only + - bugfix, get a removed dentry from an inode [ Vagrant Cascadian ] * [armmp] Enable IMX_IPUV3_CORE (closes: #756810). diff --git a/debian/config/config b/debian/config/config index cba0c452a..c5e5f95bf 100644 --- a/debian/config/config +++ b/debian/config/config @@ -4173,6 +4173,7 @@ CONFIG_AUFS_BRANCH_MAX_127=y ## end choice # CONFIG_AUFS_HNOTIFY is not set CONFIG_AUFS_EXPORT=y +# CONFIG_AUFS_FHSM is not set # CONFIG_AUFS_RDU is not set # CONFIG_AUFS_SHWH is not set # CONFIG_AUFS_BR_RAMFS is not set diff --git a/debian/patches/features/all/aufs3/aufs3-add.patch b/debian/patches/features/all/aufs3/aufs3-add.patch index fb1bc4cdb..f015e0786 100644 --- a/debian/patches/features/all/aufs3/aufs3-add.patch +++ b/debian/patches/features/all/aufs3/aufs3-add.patch @@ -1,7 +1,7 @@ From: J. R. Okajima -Date: Thu Jul 10 02:32:20 2014 +0900 -Subject: aufs3.x-rcN-20140714 -Origin: http://sourceforge.net/p/aufs/aufs3-standalone/ci/501539c2f9478ef69fa42acfb43ef1420d9bb524/tree/ +Date: Thu Sep 4 19:46:58 2014 +0900 +Subject: aufs3.16-20140908 +Origin: http://sourceforge.net/p/aufs/aufs3-standalone/ci/888949daf96bf7e2b857dc38e22029513f94d4ae/tree/ Bug-Debian: https://bugs.debian.org/541828 Patch generated by debian/patches/features/all/aufs3/gen-patch @@ -94,8 +94,8 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + When the aufs mount option 'noxino' is specified, it + will be empty. About XINO files, see the aufs manual. --- a/Documentation/filesystems/aufs/README 1970-01-01 01:00:00.000000000 +0100 -+++ b/Documentation/filesystems/aufs/README 2014-07-15 14:04:48.720871625 +0100 -@@ -0,0 +1,368 @@ ++++ b/Documentation/filesystems/aufs/README 2014-09-08 00:38:33.510569903 +0100 +@@ -0,0 +1,370 @@ + +Aufs3 -- advanced multi layered unification filesystem version 3.x +http://aufs.sf.net @@ -447,6 +447,8 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch +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). ++Stefano Di Biase made a donation (2014/8). + +Thank you very much. +Donations are always, including future donations, very important and @@ -629,8 +631,8 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch +helper, instead of doing in kernel space. Actually I am still thinking +about it. But currently I have implemented it in kernel space. --- a/Documentation/filesystems/aufs/design/02struct.txt 1970-01-01 01:00:00.000000000 +0100 -+++ b/Documentation/filesystems/aufs/design/02struct.txt 2014-07-15 14:04:48.720871625 +0100 -@@ -0,0 +1,249 @@ ++++ b/Documentation/filesystems/aufs/design/02struct.txt 2014-09-08 00:38:33.510569903 +0100 +@@ -0,0 +1,251 @@ + +# Copyright (C) 2005-2014 Junjiro R. Okajima +# @@ -872,6 +874,8 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch +- free space on the lower branch will reduce. +- another access to the file may happen during moving-down, including + 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, @@ -1161,6 +1165,129 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + where the source and the target exists and selects the higher + one. If the selected branch is readonly, then aufs follows the + copyup policy. +--- a/Documentation/filesystems/aufs/design/06fhsm.txt 1970-01-01 01:00:00.000000000 +0100 ++++ b/Documentation/filesystems/aufs/design/06fhsm.txt 2014-09-08 00:38:33.510569903 +0100 +@@ -0,0 +1,120 @@ ++ ++# Copyright (C) 2011-2014 Junjiro R. Okajima ++# ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 2 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program; if not, write to the Free Software ++# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ ++ ++File-based Hierarchical Storage Management (FHSM) ++---------------------------------------------------------------------- ++Hierarchical Storage Management (or HSM) is a well-known feature in the ++storage world. Aufs provides this feature as file-based with multiple ++writable branches, based upon the principle of "Colder-Lower". ++Here the word "colder" means that the less used files, and "lower" means ++that the position in the order of the stacked branches. ++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. --- a/Documentation/filesystems/aufs/design/06mmap.txt 1970-01-01 01:00:00.000000000 +0100 +++ b/Documentation/filesystems/aufs/design/06mmap.txt 2014-01-20 03:24:33.508760970 +0000 @@ -0,0 +1,46 @@ @@ -1437,8 +1564,8 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch +/new. +Otherwise from /new. --- a/fs/aufs/Kconfig 1970-01-01 01:00:00.000000000 +0100 -+++ b/fs/aufs/Kconfig 2014-07-15 14:04:48.724871625 +0100 -@@ -0,0 +1,168 @@ ++++ b/fs/aufs/Kconfig 2014-09-08 00:38:33.510569903 +0100 +@@ -0,0 +1,177 @@ +config AUFS_FS + tristate "Aufs (Advanced multi layered unification filesystem) support" + help @@ -1528,6 +1655,15 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + /* typedef unsigned long/int __kernel_ino_t */ + /* alpha and s390x are int */ + ++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 @@ -1608,8 +1744,8 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + When aufs supports Magic SysRq, enabled automatically. +endif --- a/fs/aufs/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ b/fs/aufs/Makefile 2014-07-15 14:04:48.724871625 +0100 -@@ -0,0 +1,41 @@ ++++ b/fs/aufs/Makefile 2014-09-08 00:38:33.510569903 +0100 +@@ -0,0 +1,42 @@ + +include ${src}/magic.mk +ifeq (${CONFIG_AUFS_FS},m) @@ -1646,6 +1782,7 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch +aufs-$(CONFIG_AUFS_HNOTIFY) += hnotify.o +aufs-$(CONFIG_AUFS_HFSNOTIFY) += hfsnotify.o +aufs-$(CONFIG_AUFS_EXPORT) += export.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 @@ -1714,8 +1851,8 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch +#endif /* __KERNEL__ */ +#endif /* __AUFS_H__ */ --- a/fs/aufs/branch.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/fs/aufs/branch.c 2014-07-15 14:04:48.724871625 +0100 -@@ -0,0 +1,1238 @@ ++++ b/fs/aufs/branch.c 2014-09-08 00:38:33.510569903 +0100 +@@ -0,0 +1,1445 @@ +/* + * Copyright (C) 2005-2014 Junjiro R. Okajima + * @@ -1794,6 +1931,11 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + AuRwDestroy(&wbr->wbr_wh_rwsem); + } + ++ if (br->br_fhsm) { ++ au_br_fhsm_fin(br->br_fhsm); ++ kfree(br->br_fhsm); ++ } ++ + key = br->br_dykey; + for (i = 0; i < AuBrDynOp; i++, key++) + if (*key) @@ -1889,6 +2031,13 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + goto out_hnotify; + } + ++ add_branch->br_fhsm = NULL; ++ if (au_br_fhsm(perm)) { ++ err = au_fhsm_br_alloc(add_branch); ++ if (unlikely(err)) ++ goto out_wbr; ++ } ++ + err = au_sbr_realloc(au_sbi(sb), new_nbranch); + if (!err) + err = au_di_realloc(au_di(root), new_nbranch); @@ -1897,8 +2046,8 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + if (!err) + return add_branch; /* success */ + ++out_wbr: + kfree(add_branch->br_wbr); -+ +out_hnotify: + au_hnotify_fin_br(add_branch); +out_br: @@ -2281,6 +2430,54 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + +/* ---------------------------------------------------------------------- */ + ++static unsigned long long au_farray_cb(void *a, ++ unsigned long long max __maybe_unused, ++ void *arg) ++{ ++ unsigned long long n; ++ struct file **p, *f; ++ struct au_sphlhead *files; ++ struct au_finfo *finfo; ++ struct super_block *sb = arg; ++ ++ n = 0; ++ p = a; ++ files = &au_sbi(sb)->si_files; ++ spin_lock(&files->spin); ++ hlist_for_each_entry(finfo, &files->head, fi_hlist) { ++ f = finfo->fi_file; ++ if (file_count(f) ++ && !special_file(file_inode(f)->i_mode)) { ++ get_file(f); ++ *p++ = f; ++ n++; ++ AuDebugOn(n > max); ++ } ++ } ++ spin_unlock(&files->spin); ++ ++ return n; ++} ++ ++static struct file **au_farray_alloc(struct super_block *sb, ++ unsigned long long *max) ++{ ++ *max = atomic_long_read(&au_sbi(sb)->si_nfiles); ++ return au_array_alloc(max, au_farray_cb, sb); ++} ++ ++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]); ++ au_array_free(a); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ +/* + * delete a branch + */ @@ -2387,6 +2584,8 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + 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; + @@ -2441,6 +2640,137 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + 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, bend; ++ struct au_fidir *fidir; ++ struct au_hfile *hfile; ++ ++ err = 0; ++ root = IS_ROOT(file->f_dentry); ++ if (root) { ++ get_file(file); ++ to_free[*idx] = file; ++ (*idx)++; ++ goto out; ++ } ++ ++ matched = 0; ++ fidir = au_fi(file)->fi_hdir; ++ AuDebugOn(!fidir); ++ bend = au_fbend_dir(file); ++ for (bindex = au_fbstart(file); bindex <= bend; 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 bstart; ++ struct file *file, **array; ++ struct inode *inode; ++ 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); ++ bstart = au_fbstart(file); ++ inode = file_inode(file); ++ if (!S_ISDIR(inode->i_mode)) { ++ 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, bstart, bend, 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(!S_ISDIR(file_inode(file)->i_mode)); ++ bfound = -1; ++ fidir = au_fi(file)->fi_hdir; ++ AuDebugOn(!fidir); ++ fi_write_lock(file); ++ bstart = au_fbstart(file); ++ bend = au_fbend_dir(file); ++ for (bindex = bstart; bindex <= bend; 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 == bstart) { ++ for (bstart++; bstart <= bend; bstart++) ++ if (au_hf_dir(file, bstart)) { ++ au_set_fbstart(file, bstart); ++ 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 bend) @@ -2533,17 +2863,29 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + au_br_do_free(br); +} + ++static unsigned long long empty_cb(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, bend, br_id; + unsigned char do_wh, verbose; + struct au_branch *br; + struct au_wbr *wbr; ++ struct dentry *root; ++ struct file **to_free; + + err = 0; -+ bindex = au_find_dbindex(sb->s_root, del->h_path.dentry); ++ 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 */ @@ -2563,10 +2905,20 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + } + br = au_sbr(sb, bindex); + AuDebugOn(!path_equal(&br->br_path, &del->h_path)); -+ i = atomic_read(&br->br_count); -+ if (unlikely(i)) { -+ AuVerbose(verbose, "%d file(s) opened\n", i); -+ goto out; ++ ++ br_id = br->br_id; ++ opened = atomic_read(&br->br_count); ++ if (unlikely(opened)) { ++ to_free = au_array_alloc(&opened, empty_cb, 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; @@ -2580,7 +2932,7 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + } + } + -+ err = test_children_busy(sb->s_root, bindex, verbose); ++ err = test_children_busy(root, bindex, verbose); + if (unlikely(err)) { + if (do_wh) + goto out_wh; @@ -2588,7 +2940,16 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + } + + err = 0; -+ br_id = br->br_id; ++ if (to_free) { ++ /* ++ * now we confirmed the branch is deletable. ++ * let's free the remaining opened dirs on the branch. ++ */ ++ di_write_unlock(root); ++ br_del_file(to_free, opened, br_id); ++ di_write_lock_child(root); ++ } ++ + if (!remount) + au_br_do_del(sb, bindex, br); + else { @@ -2598,10 +2959,10 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + } + + if (!bindex) { -+ au_cpup_attr_all(sb->s_root->d_inode, /*force*/1); ++ au_cpup_attr_all(root->d_inode, /*force*/1); + sb->s_maxbytes = au_sbr_sb(sb, 0)->s_maxbytes; + } else -+ au_sub_nlink(sb->s_root->d_inode, del->h_path.dentry->d_inode); ++ au_sub_nlink(root->d_inode, del->h_path.dentry->d_inode); + if (au_opt_test(mnt_flags, PLINK)) + au_plink_half_refresh(sb, br_id); + @@ -2616,6 +2977,8 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + 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; +} + @@ -2715,52 +3078,6 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + || do_need_sigen_inc(new, old); +} + -+static unsigned long long au_farray_cb(void *a, -+ unsigned long long max __maybe_unused, -+ void *arg) -+{ -+ unsigned long long n; -+ struct file **p, *f; -+ struct au_sphlhead *files; -+ struct au_finfo *finfo; -+ struct super_block *sb = arg; -+ -+ n = 0; -+ p = a; -+ files = &au_sbi(sb)->si_files; -+ spin_lock(&files->spin); -+ hlist_for_each_entry(finfo, &files->head, fi_hlist) { -+ f = finfo->fi_file; -+ if (file_count(f) -+ && !special_file(file_inode(f)->i_mode)) { -+ get_file(f); -+ *p++ = f; -+ n++; -+ AuDebugOn(n > max); -+ } -+ } -+ spin_unlock(&files->spin); -+ -+ return n; -+} -+ -+static struct file **au_farray_alloc(struct super_block *sb, -+ unsigned long long *max) -+{ -+ *max = atomic_long_read(&au_sbi(sb)->si_nfiles); -+ return au_array_alloc(max, au_farray_cb, sb); -+} -+ -+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]); -+ au_array_free(a); -+} -+ +static int au_br_mod_files_ro(struct super_block *sb, aufs_bindex_t bindex) +{ + int err, do_warn; @@ -2784,6 +3101,8 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + 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); @@ -2859,6 +3178,7 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + 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); @@ -2880,11 +3200,21 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + 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; ++ goto out_bf; + + if (!au_br_writable(mod->perm)) { + /* rw --> ro, file might be mmapped */ @@ -2920,18 +3250,32 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + } + } + } ++ if (unlikely(err)) ++ goto out_bf; + -+ if (!err) { -+ if ((br->br_perm & AuBrAttr_UNPIN) -+ && !(mod->perm & AuBrAttr_UNPIN)) -+ au_br_dflags_force(br); -+ else if (!(br->br_perm & AuBrAttr_UNPIN) -+ && (mod->perm & AuBrAttr_UNPIN)) -+ au_br_dflags_restore(br); -+ *do_refresh |= need_sigen_inc(br->br_perm, mod->perm); -+ br->br_perm = mod->perm; -+ } ++ if (au_br_fhsm(br->br_perm)) { ++ if (!au_br_fhsm(mod->perm)) { ++ /* fhsm --> non-fhsm */ ++ au_br_fhsm_fin(br->br_fhsm); ++ kfree(br->br_fhsm); ++ br->br_fhsm = NULL; ++ } ++ } else if (au_br_fhsm(mod->perm)) ++ /* non-fhsm --> fhsm */ ++ br->br_fhsm = bf; + ++ if ((br->br_perm & AuBrAttr_UNPIN) ++ && !(mod->perm & AuBrAttr_UNPIN)) ++ au_br_dflags_force(br); ++ else if (!(br->br_perm & AuBrAttr_UNPIN) ++ && (mod->perm & AuBrAttr_UNPIN)) ++ au_br_dflags_restore(br); ++ *do_refresh |= need_sigen_inc(br->br_perm, mod->perm); ++ br->br_perm = mod->perm; ++ goto out; /* success */ ++ ++out_bf: ++ kfree(bf); +out: + AuTraceErr(err); + return err; @@ -2955,8 +3299,8 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + return err; +} --- a/fs/aufs/branch.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/fs/aufs/branch.h 2014-07-15 14:04:48.724871625 +0100 -@@ -0,0 +1,290 @@ ++++ b/fs/aufs/branch.h 2014-09-08 00:38:33.510569903 +0100 +@@ -0,0 +1,268 @@ +/* + * Copyright (C) 2005-2014 Junjiro R. Okajima + * @@ -3002,6 +3346,16 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch +#endif +}; + ++/* File-based Hierarchical Storage Management */ ++struct au_br_fhsm { ++#ifdef CONFIG_AUFS_FHSM ++ struct mutex bf_lock; ++ unsigned long bf_jiffy; ++ struct aufs_stfs bf_stfs; ++ int bf_readable; ++#endif ++}; ++ +/* members for writable branch only */ +enum {AuBrWh_BASE, AuBrWh_PLINK, AuBrWh_ORPH, AuBrWh_Last}; +struct au_wbr { @@ -3052,6 +3406,7 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + atomic_t br_count; + + struct au_wbr *br_wbr; ++ struct au_br_fhsm *br_fhsm; + + /* xino truncation */ + atomic_t br_xino_running; @@ -3083,53 +3438,6 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + return au_br_mnt(br)->mnt_sb; +} + -+/* branch permissions and attributes */ -+#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_UNPIN (1 << 5) /* rename-able top dir of -+ branch */ -+ -+#define AuBrRAttr_WH (1 << 6) /* whiteout-able */ -+#define AuBrRAttr_Mask AuBrRAttr_WH -+ -+#define AuBrWAttr_NoLinkWH (1 << 7) /* un-hardlinkable whiteouts */ -+#define AuBrWAttr_MOO (1 << 8) /* move-up on open */ -+#define AuBrWAttr_Mask (AuBrWAttr_NoLinkWH | AuBrWAttr_MOO) -+ -+#define AuBrAttr_CMOO_Mask (AuBrAttr_COO_Mask | AuBrWAttr_MOO) -+ -+/* the longest combination */ -+#define AuBrPermStrSz sizeof(AUFS_BRPERM_RW \ -+ "+" AUFS_BRATTR_COO_REG \ -+ "+" AUFS_BRATTR_UNPIN \ -+ "+" 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_rdonly(struct au_branch *br) +{ + return ((au_br_sb(br)->s_flags & MS_RDONLY) @@ -3137,11 +3445,6 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + ? -EROFS : 0; +} + -+static inline int au_br_cmoo(int brperm) -+{ -+ return brperm & AuBrAttr_CMOO_Mask; -+} -+ +static inline int au_br_hnotifyable(int brperm __maybe_unused) +{ +#ifdef CONFIG_AUFS_HNOTIFY @@ -3245,11 +3548,30 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch +#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__ */ --- a/fs/aufs/conf.mk 1970-01-01 01:00:00.000000000 +0100 -+++ b/fs/aufs/conf.mk 2014-07-15 14:04:48.724871625 +0100 -@@ -0,0 +1,36 @@ ++++ b/fs/aufs/conf.mk 2014-09-08 00:38:33.510569903 +0100 +@@ -0,0 +1,37 @@ + +AuConfStr = CONFIG_AUFS_FS=${CONFIG_AUFS_FS} + @@ -3263,6 +3585,7 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + SBILIST \ + HNOTIFY HFSNOTIFY \ + EXPORT INO_T_64 \ ++ FHSM \ + RDU \ + SHWH \ + BR_RAMFS \ @@ -3287,8 +3610,8 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + +-include ${srctree}/${src}/conf_priv.mk --- a/fs/aufs/cpup.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/fs/aufs/cpup.c 2014-07-15 14:04:48.724871625 +0100 -@@ -0,0 +1,1289 @@ ++++ b/fs/aufs/cpup.c 2014-09-08 00:38:33.510569903 +0100 +@@ -0,0 +1,1301 @@ +/* + * Copyright (C) 2005-2014 Junjiro R. Okajima + * @@ -3788,7 +4111,7 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + int err; + umode_t mode; + unsigned int mnt_flags; -+ unsigned char isdir; ++ unsigned char isdir, isreg, force; + const unsigned char do_dt = !!au_ftest_cpup(cpg->flags, DTIME); + struct au_dtime dt; + struct path h_path; @@ -3819,10 +4142,12 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + } + 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, mode | S_IWUSR, + /*want_excl*/true); + if (!err) @@ -3871,6 +4196,16 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + 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; @@ -5531,8 +5866,8 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch +#endif /* __KERNEL__ */ +#endif /* __AUFS_DCSUB_H__ */ --- a/fs/aufs/debug.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/fs/aufs/debug.c 2014-07-15 14:04:48.728871625 +0100 -@@ -0,0 +1,519 @@ ++++ b/fs/aufs/debug.c 2014-09-08 00:38:33.514569904 +0100 +@@ -0,0 +1,520 @@ +/* + * Copyright (C) 2005-2014 Junjiro R. Okajima + * @@ -5591,6 +5926,7 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch +MODULE_PARM_DESC(debug, "debug print"); +module_param_named(debug, aufs_debug, atomic_t, S_IRUGO | S_IWUSR | S_IWGRP); + ++DEFINE_MUTEX(au_dbg_mtx); /* just to serialize the dbg msgs */ +char *au_plevel = KERN_DEBUG; +#define dpri(fmt, ...) do { \ + if ((au_plevel \ @@ -6053,8 +6389,8 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + return 0; +} --- a/fs/aufs/debug.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/fs/aufs/debug.h 2014-01-20 03:24:33.508760970 +0000 -@@ -0,0 +1,247 @@ ++++ b/fs/aufs/debug.h 2014-09-08 00:38:33.514569904 +0100 +@@ -0,0 +1,262 @@ +/* + * Copyright (C) 2005-2014 Junjiro R. Okajima + * @@ -6167,6 +6503,7 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch +struct au_finfo; +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); @@ -6195,38 +6532,52 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch +int __init au_debug_init(void); +void au_debug_sbinfo_init(struct au_sbinfo *sbinfo); +#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 AuDbgSleep(sec) do { \ @@ -6303,8 +6654,8 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch +#endif /* __KERNEL__ */ +#endif /* __AUFS_DEBUG_H__ */ --- a/fs/aufs/dentry.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/fs/aufs/dentry.c 2014-07-15 14:04:48.728871625 +0100 -@@ -0,0 +1,1094 @@ ++++ b/fs/aufs/dentry.c 2014-09-08 00:38:33.514569904 +0100 +@@ -0,0 +1,1096 @@ +/* + * Copyright (C) 2005-2014 Junjiro R. Okajima + * @@ -7311,10 +7662,6 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + if (unlikely(!au_di(dentry))) + goto out; + -+ inode = dentry->d_inode; -+ if (inode && is_bad_inode(inode)) -+ goto out; -+ + valid = 1; + sb = dentry->d_sb; + /* @@ -7328,6 +7675,12 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + AuTraceErr(err); + goto out; + } ++ inode = dentry->d_inode; ++ if (unlikely(inode && is_bad_inode(inode))) { ++ err = -EINVAL; ++ AuTraceErr(err); ++ goto out_dgrade; ++ } + if (unlikely(au_dbrange_test(dentry))) { + err = -EINVAL; + AuTraceErr(err); @@ -8183,8 +8536,8 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + return -1; +} --- a/fs/aufs/dir.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/fs/aufs/dir.c 2014-07-15 14:04:48.728871625 +0100 -@@ -0,0 +1,643 @@ ++++ b/fs/aufs/dir.c 2014-09-08 00:38:33.514569904 +0100 +@@ -0,0 +1,645 @@ +/* + * Copyright (C) 2005-2014 Junjiro R. Okajima + * @@ -8404,6 +8757,8 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + finfo = au_fi(file); + fidir = finfo->fi_hdir; + if (fidir) { ++ au_sphl_del(&finfo->fi_hlist, ++ &au_sbi(file->f_dentry->d_sb)->si_files); + vdir_cache = fidir->fd_vdir_cache; /* lock-free */ + if (vdir_cache) + au_vdir_free(vdir_cache); @@ -9428,7 +9783,7 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch +#endif /* __KERNEL__ */ +#endif /* __AUFS_DYNOP_H__ */ --- a/fs/aufs/export.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/fs/aufs/export.c 2014-01-20 03:24:33.512760970 +0000 ++++ b/fs/aufs/export.c 2014-09-08 00:38:33.514569904 +0100 @@ -0,0 +1,831 @@ +/* + * Copyright (C) 2005-2014 Junjiro R. Okajima @@ -10146,7 +10501,7 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + ii_read_lock_child(inode); + bindex = au_ibstart(inode); + if (!dir) { -+ dentry = d_find_alias(inode); ++ dentry = d_find_any_alias(inode); + if (unlikely(!dentry)) + goto out_unlock; + AuDebugOn(au_test_anon(dentry)); @@ -10162,7 +10517,7 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + ii_read_unlock(dir); + if (unlikely(!h_dir)) + goto out_parent; -+ h_parent = d_find_alias(h_dir); ++ h_parent = d_find_any_alias(h_dir); + if (unlikely(!h_parent)) + goto out_hparent; + @@ -10262,8 +10617,8 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + atomic_set(&sbinfo->si_xigen_next, u); +} --- a/fs/aufs/f_op.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/fs/aufs/f_op.c 2014-07-15 14:04:48.728871625 +0100 -@@ -0,0 +1,791 @@ ++++ b/fs/aufs/f_op.c 2014-09-08 00:38:33.514569904 +0100 +@@ -0,0 +1,813 @@ +/* + * Copyright (C) 2005-2014 Junjiro R. Okajima + * @@ -10322,8 +10677,6 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + au_set_fbstart(file, bindex); + au_set_h_fptr(file, bindex, h_file); + au_update_figen(file); -+ finfo->fi_file = file; -+ au_sphl_add(&finfo->fi_hlist, &au_sbi(dentry->d_sb)->si_files); + /* todo: necessary? */ + /* file->f_ra = h_file->f_ra; */ + } @@ -10449,10 +10802,12 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + size_t count, loff_t *ppos) +{ + ssize_t err; ++ blkcnt_t blks; ++ aufs_bindex_t bstart; + struct au_pin pin; + struct dentry *dentry; ++ struct inode *inode, *h_inode; + struct super_block *sb; -+ struct inode *inode; + struct file *h_file; + char __user *buf = (char __user *)ubuf; + @@ -10473,8 +10828,11 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + goto out; + } + ++ bstart = au_fbstart(file); + h_file = au_hf_top(file); + get_file(h_file); ++ h_inode = h_file->f_dentry->d_inode; ++ blks = h_inode->i_blocks; + au_unpin(&pin); + di_read_unlock(dentry, AuLock_IR); + fi_write_unlock(file); @@ -10483,6 +10841,9 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + ii_write_lock_child(inode); + au_cpup_attr_timesizes(inode); + inode->i_mode = file_inode(h_file)->i_mode; ++ AuDbg("blks %llu, %llu\n", (u64)blks, (u64)h_inode->i_blocks); ++ if (err > 0) ++ au_fhsm_wrote(sb, bstart, /*force*/h_inode->i_blocks > blks); + ii_write_unlock(inode); + fput(h_file); + @@ -10570,9 +10931,11 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch +static ssize_t aufs_write_iter(struct kiocb *kio, struct iov_iter *iov_iter) +{ + ssize_t err; ++ blkcnt_t blks; ++ aufs_bindex_t bstart; + struct au_pin pin; + struct dentry *dentry; -+ struct inode *inode; ++ struct inode *inode, *h_inode; + struct file *file, *h_file; + struct super_block *sb; + @@ -10594,8 +10957,11 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + goto out; + } + ++ bstart = au_fbstart(file); + h_file = au_hf_top(file); + get_file(h_file); ++ h_inode = h_file->f_dentry->d_inode; ++ blks = h_inode->i_blocks; + au_unpin(&pin); + di_read_unlock(dentry, AuLock_IR); + fi_write_unlock(file); @@ -10604,6 +10970,9 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + ii_write_lock_child(inode); + au_cpup_attr_timesizes(inode); + inode->i_mode = file_inode(h_file)->i_mode; ++ AuDbg("blks %llu, %llu\n", (u64)blks, (u64)h_inode->i_blocks); ++ if (err > 0) ++ au_fhsm_wrote(sb, bstart, /*force*/h_inode->i_blocks > blks); + ii_write_unlock(inode); + fput(h_file); + @@ -10659,11 +11028,13 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + size_t len, unsigned int flags) +{ + ssize_t err; ++ blkcnt_t blks; ++ aufs_bindex_t bstart; + struct au_pin pin; + struct dentry *dentry; -+ struct inode *inode; -+ struct file *h_file; ++ struct inode *inode, *h_inode; + struct super_block *sb; ++ struct file *h_file; + + dentry = file->f_dentry; + sb = dentry->d_sb; @@ -10682,8 +11053,11 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + goto out; + } + ++ bstart = au_fbstart(file); + h_file = au_hf_top(file); + get_file(h_file); ++ h_inode = h_file->f_dentry->d_inode; ++ blks = h_inode->i_blocks; + au_unpin(&pin); + di_read_unlock(dentry, AuLock_IR); + fi_write_unlock(file); @@ -10692,6 +11066,9 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + ii_write_lock_child(inode); + au_cpup_attr_timesizes(inode); + inode->i_mode = file_inode(h_file)->i_mode; ++ AuDbg("blks %llu, %llu\n", (u64)blks, (u64)h_inode->i_blocks); ++ if (err > 0) ++ au_fhsm_wrote(sb, bstart, /*force*/h_inode->i_blocks > blks); + ii_write_unlock(inode); + fput(h_file); + @@ -11055,9 +11432,438 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch +#endif + .fallocate = aufs_fallocate +}; +--- a/fs/aufs/fhsm.c 1970-01-01 01:00:00.000000000 +0100 ++++ b/fs/aufs/fhsm.c 2014-09-08 00:38:33.514569904 +0100 +@@ -0,0 +1,426 @@ ++/* ++ * Copyright (C) 2011-2014 Junjiro R. Okajima ++ * ++ * This program, aufs is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++/* ++ * File-based Hierarchy Storage Management ++ */ ++ ++#include ++#include ++#include ++#include ++#include "aufs.h" ++ ++static aufs_bindex_t au_fhsm_bottom(struct super_block *sb) ++{ ++ struct au_sbinfo *sbinfo; ++ struct au_fhsm *fhsm; ++ ++ SiMustAnyLock(sb); ++ ++ sbinfo = au_sbi(sb); ++ fhsm = &sbinfo->si_fhsm; ++ AuDebugOn(!fhsm); ++ return fhsm->fhsm_bottom; ++} ++ ++void au_fhsm_set_bottom(struct super_block *sb, aufs_bindex_t bindex) ++{ ++ struct au_sbinfo *sbinfo; ++ struct au_fhsm *fhsm; ++ ++ SiMustWriteLock(sb); ++ ++ sbinfo = au_sbi(sb); ++ fhsm = &sbinfo->si_fhsm; ++ AuDebugOn(!fhsm); ++ fhsm->fhsm_bottom = bindex; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static int au_fhsm_test_jiffy(struct au_sbinfo *sbinfo, struct au_branch *br) ++{ ++ struct au_br_fhsm *bf; ++ ++ bf = br->br_fhsm; ++ MtxMustLock(&bf->bf_lock); ++ ++ return !bf->bf_readable ++ || time_after(jiffies, ++ bf->bf_jiffy + sbinfo->si_fhsm.fhsm_expire); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static void au_fhsm_notify(struct super_block *sb, int val) ++{ ++ struct au_sbinfo *sbinfo; ++ struct au_fhsm *fhsm; ++ ++ SiMustAnyLock(sb); ++ ++ sbinfo = au_sbi(sb); ++ fhsm = &sbinfo->si_fhsm; ++ if (au_fhsm_pid(fhsm) ++ && atomic_read(&fhsm->fhsm_readable) != -1) { ++ atomic_set(&fhsm->fhsm_readable, val); ++ if (val) ++ wake_up(&fhsm->fhsm_wqh); ++ } ++} ++ ++static int au_fhsm_stfs(struct super_block *sb, aufs_bindex_t bindex, ++ struct aufs_stfs *rstfs, int do_lock, int do_notify) ++{ ++ int err; ++ struct au_branch *br; ++ struct au_br_fhsm *bf; ++ ++ br = au_sbr(sb, bindex); ++ AuDebugOn(au_br_rdonly(br)); ++ bf = br->br_fhsm; ++ AuDebugOn(!bf); ++ ++ if (do_lock) ++ mutex_lock(&bf->bf_lock); ++ else ++ MtxMustLock(&bf->bf_lock); ++ ++ /* sb->s_root for NFS is unreliable */ ++ err = au_br_stfs(br, &bf->bf_stfs); ++ if (unlikely(err)) { ++ AuErr1("FHSM failed (%d), b%d, ignored.\n", bindex, err); ++ goto out; ++ } ++ ++ bf->bf_jiffy = jiffies; ++ bf->bf_readable = 1; ++ if (do_notify) ++ au_fhsm_notify(sb, /*val*/1); ++ if (rstfs) ++ *rstfs = bf->bf_stfs; ++ ++out: ++ if (do_lock) ++ mutex_unlock(&bf->bf_lock); ++ au_fhsm_notify(sb, /*val*/1); ++ ++ return err; ++} ++ ++void au_fhsm_wrote(struct super_block *sb, aufs_bindex_t bindex, int force) ++{ ++ int err; ++ struct au_sbinfo *sbinfo; ++ struct au_fhsm *fhsm; ++ struct au_branch *br; ++ struct au_br_fhsm *bf; ++ ++ AuDbg("b%d, force %d\n", bindex, force); ++ SiMustAnyLock(sb); ++ ++ sbinfo = au_sbi(sb); ++ fhsm = &sbinfo->si_fhsm; ++ if (!au_ftest_si(sbinfo, FHSM) ++ || fhsm->fhsm_bottom == bindex) ++ return; ++ ++ br = au_sbr(sb, bindex); ++ bf = br->br_fhsm; ++ AuDebugOn(!bf); ++ mutex_lock(&bf->bf_lock); ++ if (force ++ || au_fhsm_pid(fhsm) ++ || au_fhsm_test_jiffy(sbinfo, br)) ++ err = au_fhsm_stfs(sb, bindex, /*rstfs*/NULL, /*do_lock*/0, ++ /*do_notify*/1); ++ mutex_unlock(&bf->bf_lock); ++} ++ ++void au_fhsm_wrote_all(struct super_block *sb, int force) ++{ ++ aufs_bindex_t bindex, bend; ++ struct au_branch *br; ++ ++ /* exclude the bottom */ ++ bend = au_fhsm_bottom(sb); ++ for (bindex = 0; bindex < bend; bindex++) { ++ br = au_sbr(sb, bindex); ++ if (au_br_fhsm(br->br_perm)) ++ au_fhsm_wrote(sb, bindex, force); ++ } ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static unsigned int au_fhsm_poll(struct file *file, ++ struct poll_table_struct *wait) ++{ ++ unsigned int mask; ++ struct au_sbinfo *sbinfo; ++ struct au_fhsm *fhsm; ++ ++ mask = 0; ++ sbinfo = file->private_data; ++ fhsm = &sbinfo->si_fhsm; ++ poll_wait(file, &fhsm->fhsm_wqh, wait); ++ if (atomic_read(&fhsm->fhsm_readable)) ++ mask = POLLIN /* | POLLRDNORM */; ++ ++ AuTraceErr((int)mask); ++ return mask; ++} ++ ++static int au_fhsm_do_read_one(struct aufs_stbr __user *stbr, ++ struct aufs_stfs *stfs, __s16 brid) ++{ ++ int err; ++ ++ err = copy_to_user(&stbr->stfs, stfs, sizeof(*stfs)); ++ if (!err) ++ err = __put_user(brid, &stbr->brid); ++ if (unlikely(err)) ++ err = -EFAULT; ++ ++ return err; ++} ++ ++static ssize_t au_fhsm_do_read(struct super_block *sb, ++ struct aufs_stbr __user *stbr, size_t count) ++{ ++ ssize_t err; ++ int nstbr; ++ aufs_bindex_t bindex, bend; ++ struct au_branch *br; ++ struct au_br_fhsm *bf; ++ ++ /* except the bottom branch */ ++ err = 0; ++ nstbr = 0; ++ bend = au_fhsm_bottom(sb); ++ for (bindex = 0; !err && bindex < bend; 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, bend; ++ 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; ++ bend = au_fhsm_bottom(sb); ++ for (bindex = 0; bindex < bend; bindex++) { ++ br = au_sbr(sb, bindex); ++ if (au_br_fhsm(br->br_perm)) ++ nfhsm++; ++ } ++ err = -EMSGSIZE; ++ if (nfhsm * sizeof(struct aufs_stbr) <= count) { ++ atomic_set(&fhsm->fhsm_readable, 0); ++ err = au_fhsm_do_read(sbinfo->si_sb, (void __user *)buf, ++ count); ++ } ++ } ++ au_rw_read_unlock(&sbinfo->si_rwsem); ++ if (!readable) ++ goto need_data; ++ ++out: ++ return err; ++} ++ ++static int au_fhsm_release(struct inode *inode, struct file *file) ++{ ++ struct au_sbinfo *sbinfo; ++ struct au_fhsm *fhsm; ++ ++ /* sb may already be dead */ ++ sbinfo = file->private_data; ++ fhsm = &sbinfo->si_fhsm; ++ spin_lock(&fhsm->fhsm_spin); ++ fhsm->fhsm_pid = 0; ++ spin_unlock(&fhsm->fhsm_spin); ++ kobject_put(&sbinfo->si_kobj); ++ ++ return 0; ++} ++ ++static const struct file_operations au_fhsm_fops = { ++ .owner = THIS_MODULE, ++ .llseek = noop_llseek, ++ .read = au_fhsm_read, ++ .poll = au_fhsm_poll, ++ .release = au_fhsm_release ++}; ++ ++int au_fhsm_fd(struct super_block *sb, int oflags) ++{ ++ int err, fd; ++ struct au_sbinfo *sbinfo; ++ struct au_fhsm *fhsm; ++ ++ err = -EPERM; ++ if (unlikely(!capable(CAP_SYS_ADMIN))) ++ goto out; ++ ++ err = -EINVAL; ++ if (unlikely(oflags & ~(O_CLOEXEC | O_NONBLOCK))) ++ goto out; ++ ++ err = 0; ++ sbinfo = au_sbi(sb); ++ fhsm = &sbinfo->si_fhsm; ++ spin_lock(&fhsm->fhsm_spin); ++ if (!fhsm->fhsm_pid) ++ fhsm->fhsm_pid = current->pid; ++ else ++ err = -EBUSY; ++ spin_unlock(&fhsm->fhsm_spin); ++ if (unlikely(err)) ++ goto out; ++ ++ oflags |= O_RDONLY; ++ /* oflags |= FMODE_NONOTIFY; */ ++ fd = anon_inode_getfd("[aufs_fhsm]", &au_fhsm_fops, sbinfo, oflags); ++ err = fd; ++ if (unlikely(fd < 0)) ++ goto out_pid; ++ ++ /* succeed reglardless 'fhsm' status */ ++ kobject_get(&sbinfo->si_kobj); ++ si_noflush_read_lock(sb); ++ if (au_ftest_si(sbinfo, FHSM)) ++ au_fhsm_wrote_all(sb, /*force*/0); ++ si_read_unlock(sb); ++ goto out; /* success */ ++ ++out_pid: ++ spin_lock(&fhsm->fhsm_spin); ++ fhsm->fhsm_pid = 0; ++ spin_unlock(&fhsm->fhsm_spin); ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++int au_fhsm_br_alloc(struct au_branch *br) ++{ ++ int err; ++ ++ err = 0; ++ br->br_fhsm = kmalloc(sizeof(*br->br_fhsm), GFP_NOFS); ++ if (br->br_fhsm) ++ au_br_fhsm_init(br->br_fhsm); ++ else ++ err = -ENOMEM; ++ ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++void au_fhsm_fin(struct super_block *sb) ++{ ++ au_fhsm_notify(sb, /*val*/-1); ++} ++ ++void au_fhsm_init(struct au_sbinfo *sbinfo) ++{ ++ struct au_fhsm *fhsm; ++ ++ fhsm = &sbinfo->si_fhsm; ++ spin_lock_init(&fhsm->fhsm_spin); ++ init_waitqueue_head(&fhsm->fhsm_wqh); ++ atomic_set(&fhsm->fhsm_readable, 0); ++ fhsm->fhsm_expire ++ = msecs_to_jiffies(AUFS_FHSM_CACHE_DEF_SEC * MSEC_PER_SEC); ++ fhsm->fhsm_bottom = -1; ++} ++ ++void au_fhsm_set(struct au_sbinfo *sbinfo, unsigned int sec) ++{ ++ sbinfo->si_fhsm.fhsm_expire ++ = msecs_to_jiffies(sec * MSEC_PER_SEC); ++} ++ ++void au_fhsm_show(struct seq_file *seq, struct au_sbinfo *sbinfo) ++{ ++ unsigned int u; ++ ++ if (!au_ftest_si(sbinfo, FHSM)) ++ return; ++ ++ u = jiffies_to_msecs(sbinfo->si_fhsm.fhsm_expire) / MSEC_PER_SEC; ++ if (u != AUFS_FHSM_CACHE_DEF_SEC) ++ seq_printf(seq, ",fhsm_sec=%u", u); ++} --- a/fs/aufs/file.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/fs/aufs/file.c 2014-07-15 14:04:48.728871625 +0100 -@@ -0,0 +1,808 @@ ++++ b/fs/aufs/file.c 2014-09-08 00:38:33.514569904 +0100 +@@ -0,0 +1,833 @@ +/* + * Copyright (C) 2005-2014 Junjiro R. Okajima + * @@ -11172,6 +11978,7 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch +static int au_cmoo(struct dentry *dentry) +{ + int err, cmoo; ++ unsigned int udba; + struct path h_path; + struct au_pin pin; + struct au_cp_generic cpg = { @@ -11184,6 +11991,9 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + }; + struct inode *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; @@ -11200,6 +12010,14 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + goto out; + + sb = dentry->d_sb; ++ sbinfo = au_sbi(sb); ++ fhsm = &sbinfo->si_fhsm; ++ pid = au_fhsm_pid(fhsm); ++ if (pid ++ && (current->pid == pid ++ || current->real_parent->pid == pid)) ++ goto out; ++ + br = au_sbr(sb, cpg.bsrc); + cmoo = au_br_cmoo(br->br_perm); + if (!cmoo) @@ -11225,34 +12043,42 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + goto out_dgrade; + + di_downgrade_lock(parent, AuLock_IR); -+ err = au_pin(&pin, dentry, cpg.bdst, au_opt_udba(sb), ++ udba = au_opt_udba(sb); ++ err = au_pin(&pin, dentry, cpg.bdst, udba, + AuPin_DI_LOCKED | AuPin_MNT_WRITE); -+ if (!err) { -+ err = au_sio_cpup_simple(&cpg); -+ au_unpin(&pin); ++ 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(parent->d_inode, 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 (!err && (cmoo & AuBrWAttr_MOO)) { -+ /* todo: keep h_dentry? */ -+ h_path.mnt = au_br_mnt(br); -+ h_path.dentry = au_h_dptr(dentry, cpg.bsrc); -+ hdir = au_hi(parent->d_inode, cpg.bsrc); -+ delegated = NULL; -+ au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT2); -+ err = vfsub_unlink(hdir->hi_inode, &h_path, &delegated, -+ /*force*/1); -+ au_hn_imtx_unlock(hdir); -+ 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; -+ } ++ if (unlikely(err)) { ++ pr_err("unlink %pd after coo failed (%d), ignored\n", ++ dentry, err); ++ err = 0; + } -+ goto out_parent; ++ goto out_parent; /* success */ + +out_dgrade: + di_downgrade_lock(parent, AuLock_IR); @@ -11269,6 +12095,7 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch +{ + int err; + struct dentry *dentry; ++ struct au_finfo *finfo; + + err = au_finfo_init(file, fidir); + if (unlikely(err)) @@ -11282,9 +12109,15 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + err = open(file, vfsub_file_flags(file)); + di_read_unlock(dentry, AuLock_IR); + ++ finfo = au_fi(file); ++ if (!err) { ++ finfo->fi_file = file; ++ au_sphl_add(&finfo->fi_hlist, ++ &au_sbi(file->f_dentry->d_sb)->si_files); ++ } + fi_write_unlock(file); + if (unlikely(err)) { -+ au_fi(file)->fi_hdir = NULL; ++ finfo->fi_hdir = NULL; + au_finfo_fin(file); + } + @@ -11655,8 +12488,7 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + if (p->hf_file) { + if (file_inode(p->hf_file)) + break; -+ else -+ au_hfput(p, file); ++ au_hfput(p, file); + } + } else { + bend = au_br_index(sb, brid); @@ -11673,8 +12505,7 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + if (p->hf_file) { + if (file_inode(p->hf_file)) + break; -+ else -+ au_hfput(p, file); ++ au_hfput(p, file); + } + AuDebugOn(fidir->fd_bbot < finfo->fi_btop); +} @@ -12790,8 +13621,8 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch +#endif /* __KERNEL__ */ +#endif /* __AUFS_FSTYPE_H__ */ --- a/fs/aufs/hfsnotify.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/fs/aufs/hfsnotify.c 2014-07-15 14:04:48.728871625 +0100 -@@ -0,0 +1,281 @@ ++++ b/fs/aufs/hfsnotify.c 2014-09-08 00:38:33.514569904 +0100 +@@ -0,0 +1,288 @@ +/* + * Copyright (C) 2005-2014 Junjiro R. Okajima + * @@ -12854,10 +13685,12 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + * by udba rename or rmdir, aufs assign a new inode to the known + * h_inode, so specify 1 to allow dups. + */ ++ lockdep_off(); + err = fsnotify_add_mark(mark, br->br_hfsn->hfsn_group, hinode->hi_inode, + /*mnt*/NULL, /*allow_dups*/1); + /* even if err */ + fsnotify_put_mark(mark); ++ lockdep_on(); + + return err; +} @@ -12876,8 +13709,10 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + group = mark->group; + fsnotify_get_group(group); + spin_unlock(&mark->lock); ++ lockdep_off(); + fsnotify_destroy_mark(mark, group); + fsnotify_put_group(group); ++ lockdep_on(); + + /* free hn by myself */ + return 0; @@ -13004,8 +13839,11 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + struct au_br_hfsnotify *hfsn; + + hfsn = br->br_hfsn; -+ if (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) @@ -13133,7 +13971,7 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + } +} --- a/fs/aufs/hnotify.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/fs/aufs/hnotify.c 2014-07-15 14:04:48.732871625 +0100 ++++ b/fs/aufs/hnotify.c 2014-09-08 00:38:33.514569904 +0100 @@ -0,0 +1,714 @@ +/* + * Copyright (C) 2005-2014 Junjiro R. Okajima @@ -13364,7 +14202,7 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + spin_unlock(&inode->i_lock); + } else { + au_fset_si(au_sbi(inode->i_sb), FAILED_REFRESH_DIR); -+ d = d_find_alias(inode); ++ d = d_find_any_alias(inode); + if (!d) { + au_iigen_dec(inode); + goto out; @@ -13509,7 +14347,7 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + struct dentry *dentry, *d, *parent; + struct qstr *dname; + -+ parent = d_find_alias(dir); ++ parent = d_find_any_alias(dir); + if (!parent) + return NULL; + @@ -13850,8 +14688,8 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + au_hn_destroy_cache(); +} --- a/fs/aufs/i_op.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/fs/aufs/i_op.c 2014-07-15 14:04:48.732871625 +0100 -@@ -0,0 +1,1140 @@ ++++ b/fs/aufs/i_op.c 2014-09-08 00:39:05.266571221 +0100 +@@ -0,0 +1,1142 @@ +/* + * Copyright (C) 2005-2014 Junjiro R. Okajima + * @@ -14057,11 +14895,11 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + + if (npositive) { + inode = au_new_inode(dentry, /*must_new*/0); -+ ret = (void *)inode; -+ } -+ if (IS_ERR(inode)) { -+ inode = NULL; -+ goto out_unlock; ++ if (IS_ERR(inode)) { ++ ret = (void *)inode; ++ inode = NULL; ++ goto out_unlock; ++ } + } + + ret = d_splice_alias(inode, dentry); @@ -14236,7 +15074,7 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + au_hn_imtx_unlock(p->hdir); +} + -+static int au_pin_hdir_lock(struct au_pin *p) ++int au_pin_hdir_lock(struct au_pin *p) +{ + int err; + @@ -14402,6 +15240,8 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + if (!err) + goto out; /* success */ + ++ au_unpin(p); ++ +out_err: + pr_err("err %d\n", err); + err = au_busy_or_stale(); @@ -14993,8 +15833,8 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + .update_time = aufs_update_time +}; --- a/fs/aufs/i_op_add.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/fs/aufs/i_op_add.c 2014-07-15 14:04:48.732871625 +0100 -@@ -0,0 +1,880 @@ ++++ b/fs/aufs/i_op_add.c 2014-09-08 00:38:33.514569904 +0100 +@@ -0,0 +1,891 @@ +/* + * Copyright (C) 2005-2014 Junjiro R. Okajima + * @@ -15030,17 +15870,19 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + 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 = wh_dentry->d_parent->d_inode; /* dir inode is locked */ + IMustLock(h_dir); + AuDebugOn(au_h_iptr(dir, bindex) != h_dir); + bwh = au_dbwh(dentry); + h_path.dentry = wh_dentry; -+ h_path.mnt = au_sbr_mnt(dir->i_sb, bindex); ++ h_path.mnt = au_sbr_mnt(sb, bindex); + err = au_wh_unlink_dentry(au_h_iptr(dir, bindex), &h_path, + dentry); + if (unlikely(err)) @@ -15055,6 +15897,7 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + if (au_ibstart(dir) == au_dbstart(dentry)) + au_cpup_attr_timesizes(dir); + dir->i_version++; ++ au_fhsm_wrote(sb, bindex, /*force*/0); + return 0; /* success */ + } + @@ -15536,7 +16379,10 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + 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 = src_dentry->d_inode; /* 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); @@ -15558,7 +16404,10 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + 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_dbend(dentry, bend); + } else { @@ -15737,6 +16586,8 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + 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: @@ -16386,8 +17237,8 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + return err; +} --- a/fs/aufs/i_op_ren.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/fs/aufs/i_op_ren.c 2014-01-20 03:24:33.512760970 +0000 -@@ -0,0 +1,1032 @@ ++++ b/fs/aufs/i_op_ren.c 2014-09-08 00:38:33.514569904 +0100 +@@ -0,0 +1,1034 @@ +/* + * Copyright (C) 2005-2014 Junjiro R. Okajima + * @@ -16672,7 +17523,8 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + au_hn_imtx_unlock(a->src_hinode); + if (IS_ERR(diropq)) + err = PTR_ERR(diropq); -+ dput(diropq); ++ else ++ dput(diropq); + + return err; +} @@ -16772,6 +17624,7 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + 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; + @@ -18196,8 +19049,8 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + return au_test_h_perm(h_inode, mask); +} --- a/fs/aufs/inode.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/fs/aufs/inode.h 2014-07-15 14:04:48.732871625 +0100 -@@ -0,0 +1,601 @@ ++++ b/fs/aufs/inode.h 2014-09-08 00:38:33.514569904 +0100 +@@ -0,0 +1,602 @@ +/* + * Copyright (C) 2005-2014 Junjiro R. Okajima + * @@ -18308,6 +19161,7 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch +}; + +void au_pin_hdir_unlock(struct au_pin *p); ++int au_pin_hdir_lock(struct au_pin *p); +int au_pin_hdir_relock(struct au_pin *p); +void au_pin_hdir_set_owner(struct au_pin *p, struct task_struct *task); +void au_pin_hdir_acquire_nest(struct au_pin *p); @@ -18800,8 +19654,8 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch +#endif /* __KERNEL__ */ +#endif /* __AUFS_INODE_H__ */ --- a/fs/aufs/ioctl.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/fs/aufs/ioctl.c 2014-01-20 03:24:33.516760970 +0000 -@@ -0,0 +1,201 @@ ++++ b/fs/aufs/ioctl.c 2014-09-08 00:38:33.514569904 +0100 +@@ -0,0 +1,219 @@ +/* + * Copyright (C) 2005-2014 Junjiro R. Okajima + * @@ -18824,6 +19678,7 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + * plink-management and readdir in userspace. + * assist the pathconf(3) wrapper library. + * move-down ++ * File-based Hierarchical Storage Management. + */ + +#include @@ -18925,6 +19780,7 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch +long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg) +{ + long err; ++ struct dentry *dentry; + + switch (cmd) { + case AUFS_CTL_RDU: @@ -18940,6 +19796,18 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + 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_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); @@ -18989,6 +19857,10 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + 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); + } @@ -19584,8 +20456,8 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch +#endif /* __KERNEL__ */ +#endif /* __AUFS_MODULE_H__ */ --- a/fs/aufs/mvdown.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/fs/aufs/mvdown.c 2014-07-15 14:04:48.732871625 +0100 -@@ -0,0 +1,653 @@ ++++ b/fs/aufs/mvdown.c 2014-09-08 00:38:33.514569904 +0100 +@@ -0,0 +1,694 @@ +/* + * Copyright (C) 2011-2014 Junjiro R. Okajima + * @@ -19615,6 +20487,7 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + 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; @@ -19623,7 +20496,6 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + struct super_block *sb; + aufs_bindex_t bopq, bwh, bfound; + unsigned char rename_lock; -+ struct au_pin pin; +}; + +#define mvd_errno mvdown.au_errno @@ -19637,12 +20509,14 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch +#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) \ @@ -19658,13 +20532,20 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + sb = a->sb; + bindex = a->mvd_bsrc; + bend = au_sbend(sb); -+ if (!(a->mvdown.flags & AUFS_MVDOWN_ROLOWER)) { ++ if (a->mvdown.flags & AUFS_MVDOWN_FHSM_LOWER) ++ for (bindex++; bindex <= bend; bindex++) { ++ br = au_sbr(sb, bindex); ++ if (au_br_fhsm(br->br_perm) ++ && (!(au_br_sb(br)->s_flags & MS_RDONLY))) ++ return bindex; ++ } ++ else if (!(a->mvdown.flags & AUFS_MVDOWN_ROLOWER)) + for (bindex++; bindex <= bend; bindex++) { + br = au_sbr(sb, bindex); + if (!au_br_rdonly(br)) + return bindex; + } -+ } else { ++ else + for (bindex++; bindex <= bend; bindex++) { + br = au_sbr(sb, bindex); + if (!(au_br_sb(br)->s_flags & MS_RDONLY)) { @@ -19674,7 +20555,6 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + return bindex; + } + } -+ } + + return -1; +} @@ -19713,22 +20593,44 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + + 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); -+ if (a->mvd_h_src_sb != a->mvd_h_dst_sb) { -+ a->rename_lock = 0; -+ err = au_pin(&a->pin, a->dentry, a->mvd_bdst, -+ au_opt_udba(a->sb), -+ AuPin_MNT_WRITE | AuPin_DI_LOCKED); -+ if (!err) { -+ a->mvd_h_src_dir = a->mvd_h_src_parent->d_inode; -+ mutex_lock_nested(&a->mvd_h_src_dir->i_mutex, -+ AuLsc_I_PARENT3); -+ } else -+ AU_MVD_PR(dmsg, "pin failed\n"); ++ 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; + } + -+ err = 0; ++ 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 = a->mvd_h_src_parent->d_inode; ++ 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 = a->mvd_h_src_parent->d_inode; ++ 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) { @@ -19737,7 +20639,20 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + 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; @@ -19745,12 +20660,16 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + +static void au_do_unlock(const unsigned char dmsg, struct au_mvd_args *a) +{ -+ if (!a->rename_lock) { -+ mutex_unlock(&a->mvd_h_src_dir->i_mutex); -+ au_unpin(&a->pin); -+ } else ++ 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 */ @@ -19762,7 +20681,7 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + .bdst = a->mvd_bdst, + .bsrc = a->mvd_bsrc, + .len = -1, -+ .pin = &a->pin, ++ .pin = &a->mvd_pin_dst, + .flags = AuCpup_DTIME | AuCpup_HOPEN + }; + @@ -19821,8 +20740,6 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + +/* + * unlink the topmost h_dentry -+ * Note: the target file MAY be modified by UDBA between this mutex_unlock() and -+ * mutex_lock() in vfs_unlink(). in this case, such changes may be lost. + */ +static int au_do_unlink(const unsigned char dmsg, struct au_mvd_args *a) +{ @@ -19895,6 +20812,8 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + 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; + @@ -20167,8 +21086,6 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + if (unlikely(!capable(CAP_SYS_ADMIN))) + goto out; + -+ WARN_ONCE(1, "move-down is still testing...\n"); -+ + err = -ENOMEM; + args = kmalloc(sizeof(*args), GFP_NOFS); + if (unlikely(!args)) @@ -20210,13 +21127,9 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + if (unlikely(err)) + goto out_parent; + -+ AuDbgDentry(dentry); -+ AuDbgInode(args->inode); + err = au_do_mvdown(dmsg, args); + if (unlikely(err)) + goto out_parent; -+ AuDbgDentry(dentry); -+ AuDbgInode(args->inode); + + au_cpup_attr_timesizes(args->dir); + au_cpup_attr_timesizes(args->inode); @@ -20240,8 +21153,8 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + return err; +} --- a/fs/aufs/opts.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/fs/aufs/opts.c 2014-07-15 14:04:48.732871625 +0100 -@@ -0,0 +1,1750 @@ ++++ b/fs/aufs/opts.c 2014-09-08 00:38:33.518569904 +0100 +@@ -0,0 +1,1799 @@ +/* + * Copyright (C) 2005-2014 Junjiro R. Okajima + * @@ -20289,6 +21202,7 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + Opt_diropq_a, Opt_diropq_w, + Opt_warn_perm, Opt_nowarn_perm, + Opt_wbr_copyup, Opt_wbr_create, ++ Opt_fhsm_sec, + Opt_refrof, Opt_norefrof, + Opt_verbose, Opt_noverbose, + Opt_sum, Opt_nosum, Opt_wsum, @@ -20346,6 +21260,12 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + {Opt_dio, "dio"}, + {Opt_nodio, "nodio"}, + ++#ifdef CONFIG_AUFS_FHSM ++ {Opt_fhsm_sec, "fhsm_sec=%d"}, ++#else ++ {Opt_ignore_silent, "fhsm_sec=%d"}, ++#endif ++ + {Opt_diropq_a, "diropq=always"}, + {Opt_diropq_a, "diropq=a"}, + {Opt_diropq_w, "diropq=whiteouted"}, @@ -20456,6 +21376,7 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + {AuBrAttr_COO_REG, AUFS_BRATTR_COO_REG}, + {AuBrAttr_COO_ALL, AUFS_BRATTR_COO_ALL}, + {AuBrAttr_UNPIN, AUFS_BRATTR_UNPIN}, ++ {AuBrAttr_FHSM, AUFS_BRATTR_FHSM}, + + /* ro/rr branch */ + {AuBrRAttr_WH, AUFS_BRRATTR_WH}, @@ -20947,6 +21868,9 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + 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; + default: + BUG(); + } @@ -21425,6 +22349,20 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + 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*/ @@ -21541,6 +22479,10 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + 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; @@ -21754,7 +22696,7 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch +int au_opts_verify(struct super_block *sb, unsigned long sb_flags, + unsigned int pending) +{ -+ int err; ++ int err, fhsm; + aufs_bindex_t bindex, bend; + unsigned char do_plink, skip, do_free; + struct au_branch *br; @@ -21785,6 +22727,7 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + " by the permission bits on the lower branch\n"); + + err = 0; ++ fhsm = 0; + root = sb->s_root; + dir = root->d_inode; + do_plink = !!au_opt_test(sbinfo->si_mntflags, PLINK); @@ -21827,6 +22770,11 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + if (wbr) + wbr_wh_read_unlock(wbr); + ++ if (au_br_fhsm(br->br_perm)) { ++ fhsm++; ++ AuDebugOn(!br->br_fhsm); ++ } ++ + if (skip) + continue; + @@ -21845,6 +22793,20 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + } + } + ++ if (fhsm >= 2) { ++ au_fset_si(sbinfo, FHSM); ++ for (bindex = bend; 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; +} + @@ -21993,8 +22955,8 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + return au_mntflags(sb) & AuOptMask_UDBA; +} --- a/fs/aufs/opts.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/fs/aufs/opts.h 2014-07-15 14:04:48.732871625 +0100 -@@ -0,0 +1,212 @@ ++++ b/fs/aufs/opts.h 2014-09-08 00:38:33.518569904 +0100 +@@ -0,0 +1,213 @@ +/* + * Copyright (C) 2005-2014 Junjiro R. Okajima + * @@ -22164,6 +23126,7 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + int udba; + struct au_opt_wbr_create wbr_create; + int wbr_copyup; ++ unsigned int fhsm_second; + }; +}; + @@ -23558,8 +24521,8 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch +#endif /* __KERNEL__ */ +#endif /* __AUFS_RWSEM_H__ */ --- a/fs/aufs/sbinfo.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/fs/aufs/sbinfo.c 2014-01-20 03:24:33.516760970 +0000 -@@ -0,0 +1,351 @@ ++++ b/fs/aufs/sbinfo.c 2014-09-08 00:38:33.518569904 +0100 +@@ -0,0 +1,353 @@ +/* + * Copyright (C) 2005-2014 Junjiro R. Okajima + * @@ -23659,6 +24622,8 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + 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; @@ -24026,8 +24991,8 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch +#endif /* __KERNEL__ */ +#endif /* __AUFS_SPL_H__ */ --- a/fs/aufs/super.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/fs/aufs/super.c 2014-07-15 14:04:48.736871625 +0100 -@@ -0,0 +1,998 @@ ++++ b/fs/aufs/super.c 2014-09-08 00:38:33.518569904 +0100 +@@ -0,0 +1,1004 @@ +/* + * Copyright (C) 2005-2014 Junjiro R. Okajima + * @@ -24309,6 +25274,8 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + AuUInt(RDBLK, rdblk, sbinfo->si_rdblk); + AuUInt(RDHASH, rdhash, sbinfo->si_rdhash); + ++ au_fhsm_show(m, sbinfo); ++ + AuBool(SUM, sum); + /* AuBool(SUM_W, wsum); */ + AuBool(WARN_PERM, warn_perm); @@ -24524,9 +25491,9 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + } + + sz = sizeof(array) * *hint; -+ array = kmalloc(sz, GFP_NOFS); ++ array = kzalloc(sz, GFP_NOFS); + if (unlikely(!array)) -+ array = vmalloc(sz); ++ array = vzalloc(sz); + if (unlikely(!array)) { + array = ERR_PTR(-ENOMEM); + goto out; @@ -24693,6 +25660,8 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + sigen = au_sigen(sb); + for (ull = 0; ull < max; ull++) { + inode = array[ull]; ++ if (unlikely(!inode)) ++ break; + if (au_iigen(inode, NULL) != sigen) { + ii_write_lock_child(inode); + e = au_refresh_hinode_self(inode); @@ -24826,6 +25795,7 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + au_dy_arefresh(do_dx); + } + ++ au_fhsm_wrote_all(sb, /*force*/1); /* ?? */ + aufs_write_unlock(root); + +out_mtx: @@ -25001,6 +25971,7 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + 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)) { @@ -25027,8 +25998,8 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + .owner = THIS_MODULE, +}; --- a/fs/aufs/super.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/fs/aufs/super.h 2014-07-15 14:04:48.736871625 +0100 -@@ -0,0 +1,582 @@ ++++ b/fs/aufs/super.h 2014-09-08 00:38:33.518569904 +0100 +@@ -0,0 +1,644 @@ +/* + * Copyright (C) 2005-2014 Junjiro R. Okajima + * @@ -25106,6 +26077,21 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + 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 */ @@ -25155,6 +26141,9 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + /* 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; @@ -25238,6 +26227,14 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + * if it is false, refreshing dirs at access time is unnecesary + */ +#define AuSi_FAILED_REFRESH_DIR 1 ++ ++#define AuSi_FHSM (1 << 1) /* fhsm is active now */ ++ ++#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) +{ @@ -25320,6 +26317,43 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch +/* 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) @@ -25436,8 +26470,7 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + bit = si_pid_bit(); + if (bit < PID_MAX_DEFAULT) + return test_bit(bit, au_sbi(sb)->au_si_pid.bitmap); -+ else -+ return si_pid_test_slow(sb); ++ return si_pid_test_slow(sb); +} + +static inline void si_pid_set(struct super_block *sb) @@ -25719,8 +26752,8 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + return err; +} --- a/fs/aufs/sysaufs.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/fs/aufs/sysaufs.h 2014-01-20 03:24:33.516760970 +0000 -@@ -0,0 +1,103 @@ ++++ b/fs/aufs/sysaufs.h 2014-09-08 00:38:33.518569904 +0100 +@@ -0,0 +1,107 @@ +/* + * Copyright (C) 2005-2014 Junjiro R. Okajima + * @@ -25792,6 +26825,10 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch +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); @@ -25825,8 +26862,8 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch +#endif /* __KERNEL__ */ +#endif /* __SYSAUFS_H__ */ --- a/fs/aufs/sysfs.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/fs/aufs/sysfs.c 2014-07-15 14:04:48.736871625 +0100 -@@ -0,0 +1,289 @@ ++++ b/fs/aufs/sysfs.c 2014-09-08 00:38:33.518569904 +0100 +@@ -0,0 +1,372 @@ +/* + * Copyright (C) 2005-2014 Junjiro R. Okajima + * @@ -25848,6 +26885,7 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + * sysfs interface + */ + ++#include +#include +#include "aufs.h" + @@ -26044,6 +27082,88 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + +/* ---------------------------------------------------------------------- */ + ++static int au_brinfo(struct super_block *sb, union aufs_brinfo __user *arg) ++{ ++ int err; ++ int16_t brid; ++ aufs_bindex_t bindex, bend; ++ size_t sz; ++ char *buf; ++ struct seq_file *seq; ++ struct au_branch *br; ++ ++ si_read_lock(sb, AuLock_FLUSH); ++ bend = au_sbend(sb); ++ err = bend + 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 <= bend; bindex++, arg++) { ++ err = !access_ok(VERIFY_WRITE, arg, sizeof(*arg)); ++ if (unlikely(err)) ++ break; ++ ++ br = au_sbr(sb, bindex); ++ brid = br->br_id; ++ BUILD_BUG_ON(sizeof(brid) != sizeof(arg->id)); ++ err = __put_user(brid, &arg->id); ++ if (unlikely(err)) ++ break; ++ ++ BUILD_BUG_ON(sizeof(br->br_perm) != sizeof(arg->perm)); ++ err = __put_user(br->br_perm, &arg->perm); ++ if (unlikely(err)) ++ break; ++ ++ au_seq_path(seq, &br->br_path); ++ err = seq_putc(seq, '\0'); ++ if (!err && seq->count <= sz) { ++ 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: ++ kfree(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_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_dentry->d_sb, compat_ptr(arg)); ++} ++#endif ++ ++/* ---------------------------------------------------------------------- */ ++ +void sysaufs_br_init(struct au_branch *br) +{ + int i; @@ -27169,8 +28289,8 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + return 0; +} --- a/fs/aufs/vfsub.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/fs/aufs/vfsub.c 2014-07-15 14:04:40.008871417 +0100 -@@ -0,0 +1,782 @@ ++++ b/fs/aufs/vfsub.c 2014-09-08 00:38:33.518569904 +0100 +@@ -0,0 +1,796 @@ +/* + * Copyright (C) 2005-2014 Junjiro R. Okajima + * @@ -27331,7 +28451,9 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + 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; @@ -27362,7 +28484,9 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + if (unlikely(err)) + goto out; + ++ lockdep_off(); + err = vfs_symlink(dir, path->dentry, symname); ++ lockdep_on(); + if (!err) { + struct path tmp = *path; + int did; @@ -27393,7 +28517,9 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + 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; @@ -27519,7 +28645,9 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + if (unlikely(err)) + goto out; + ++ lockdep_off(); + err = vfs_mkdir(dir, path->dentry, mode); ++ lockdep_on(); + if (!err) { + struct path tmp = *path; + int did; @@ -27765,9 +28893,11 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + int err, do_sio, wkq_err; + + do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE); -+ if (!do_sio) ++ if (!do_sio) { ++ lockdep_off(); + err = vfsub_mkdir(dir, path, mode); -+ else { ++ lockdep_on(); ++ } else { + struct au_vfsub_mkdir_args args = { + .errp = &err, + .dir = dir, @@ -27799,9 +28929,11 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + int err, do_sio, wkq_err; + + do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE); -+ if (!do_sio) ++ if (!do_sio) { ++ lockdep_off(); + err = vfsub_rmdir(dir, path); -+ else { ++ lockdep_on(); ++ } else { + struct au_vfsub_rmdir_args args = { + .errp = &err, + .dir = dir, @@ -27834,8 +28966,10 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + + *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*/ + } @@ -28241,8 +29375,8 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch +#endif /* __KERNEL__ */ +#endif /* __AUFS_VFSUB_H__ */ --- a/fs/aufs/wbr_policy.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/fs/aufs/wbr_policy.c 2014-07-15 14:04:48.736871625 +0100 -@@ -0,0 +1,764 @@ ++++ b/fs/aufs/wbr_policy.c 2014-09-08 00:38:33.518569904 +0100 +@@ -0,0 +1,765 @@ +/* + * Copyright (C) 2005-2014 Junjiro R. Okajima + * @@ -28410,6 +29544,7 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + au_set_ibend(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 */ @@ -29008,8 +30143,8 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + } +}; --- a/fs/aufs/whout.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/fs/aufs/whout.c 2014-07-15 14:04:48.736871625 +0100 -@@ -0,0 +1,1051 @@ ++++ b/fs/aufs/whout.c 2014-09-08 00:38:33.518569904 +0100 +@@ -0,0 +1,1056 @@ +/* + * Copyright (C) 2005-2014 Junjiro R. Okajima + * @@ -29602,6 +30737,8 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + wbr_wh_write_unlock(wbr); + au_hn_imtx_unlock(hdir); + di_read_unlock(a->sb->s_root, AuLock_IR); ++ if (!err) ++ au_fhsm_wrote(a->sb, bindex, /*force*/0); + +out: + if (wbr) @@ -29689,6 +30826,8 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + + /* 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); @@ -29813,9 +30952,10 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, au_sbr(sb, bindex)); + if (!IS_ERR(wh_dentry) && !wh_dentry->d_inode) { + err = link_or_create_wh(sb, bindex, wh_dentry); -+ if (!err) ++ if (!err) { + au_set_dbwh(dentry, bindex); -+ else { ++ au_fhsm_wrote(sb, bindex, /*force*/0); ++ } else { + dput(wh_dentry); + wh_dentry = ERR_PTR(err); + } @@ -31779,8 +32919,8 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + return err; +} --- a/include/uapi/linux/aufs_type.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/include/uapi/linux/aufs_type.h 2014-07-15 14:04:48.740871626 +0100 -@@ -0,0 +1,301 @@ ++++ b/include/uapi/linux/aufs_type.h 2014-09-08 00:39:05.266571221 +0100 +@@ -0,0 +1,380 @@ +/* + * Copyright (C) 2005-2014 Junjiro R. Okajima + * @@ -31822,7 +32962,7 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + +#include + -+#define AUFS_VERSION "3.x-rcN-20140714" ++#define AUFS_VERSION "3.16-20140908" + +/* todo? move this to linux-2.6.19/include/magic.h */ +#define AUFS_SUPER_MAGIC ('a' << 24 | 'u' << 16 | 'f' << 8 | 's') @@ -31876,6 +33016,7 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch +#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 */ @@ -31901,11 +33042,77 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch +#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_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 */ ++ ++#define AuBrRAttr_WH (1 << 7) /* whiteout-able */ ++#define AuBrRAttr_Mask AuBrRAttr_WH ++ ++#define AuBrWAttr_NoLinkWH (1 << 8) /* un-hardlinkable whiteouts */ ++#define AuBrWAttr_MOO (1 << 9) /* move-up on open */ ++#define AuBrWAttr_Mask (AuBrWAttr_NoLinkWH | AuBrWAttr_MOO) ++ ++#define AuBrAttr_CMOO_Mask (AuBrAttr_COO_Mask | AuBrWAttr_MOO) ++ ++#ifdef __KERNEL__ ++#ifndef CONFIG_AUFS_FHSM ++#undef AuBrAttr_FHSM ++#define AuBrAttr_FHSM 0 ++#endif ++#endif ++ ++/* the longest combination */ ++#define AuBrPermStrSz sizeof(AUFS_BRPERM_RW \ ++ "+" AUFS_BRATTR_COO_REG \ ++ "+" AUFS_BRATTR_FHSM \ ++ "+" AUFS_BRATTR_UNPIN \ ++ "+" 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 */ @@ -31914,14 +33121,11 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + AuCtl_RDU, + AuCtl_RDU_INO, + -+ /* pathconf wrapper */ -+ AuCtl_WBR_FD, -+ -+ /* busy inode */ -+ AuCtl_IBUSY, -+ -+ /* move-down */ -+ AuCtl_MVDOWN ++ 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 */ @@ -32035,9 +33239,10 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch +#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_STFS (1 << 9) /* req. stfs */ -+#define AUFS_MVDOWN_STFS_FAILED (1 << 10) /* output: stfs is unusable */ -+#define AUFS_MVDOWN_BOTTOM (1 << 11) /* output: no more lowers */ ++#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 { @@ -32072,6 +33277,18 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch + +/* ---------------------------------------------------------------------- */ + ++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) @@ -32080,5 +33297,7 @@ Patch generated by debian/patches/features/all/aufs3/gen-patch +#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/debian/patches/features/all/aufs3/aufs3-base.patch b/debian/patches/features/all/aufs3/aufs3-base.patch index 69cee6a91..333a088ef 100644 --- a/debian/patches/features/all/aufs3/aufs3-base.patch +++ b/debian/patches/features/all/aufs3/aufs3-base.patch @@ -1,13 +1,38 @@ From: J. R. Okajima -Date: Mon Jun 30 09:36:40 2014 +0900 -Subject: aufs3.x-rcN base patch -Origin: http://sourceforge.net/p/aufs/aufs3-standalone/ci/501539c2f9478ef69fa42acfb43ef1420d9bb524/tree/ +Date: Sat Aug 23 03:27:11 2014 +0900 +Subject: aufs3.16 base patch +Origin: http://sourceforge.net/p/aufs/aufs3-standalone/ci/888949daf96bf7e2b857dc38e22029513f94d4ae/tree/ Bug-Debian: https://bugs.debian.org/541828 Patch headers added by debian/patches/features/all/aufs3/gen-patch -aufs3.x-rcN base patch +aufs3.16 base patch +diff --git a/MAINTAINERS b/MAINTAINERS +index c2066f4..f07a989 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -1698,6 +1698,20 @@ F: include/linux/audit.h + F: include/uapi/linux/audit.h + F: kernel/audit* + ++AUFS (advanced multi layered unification filesystem) FILESYSTEM ++M: "J. R. Okajima" ++L: linux-unionfs@vger.kernel.org ++L: aufs-users@lists.sourceforge.net (members only) ++W: http://aufs.sourceforge.net ++T: git://git.code.sf.net/p/aufs/aufs3-linux ++T: git://github.com/sfjro/aufs3-linux.git ++S: Supported ++F: Documentation/filesystems/aufs/ ++F: Documentation/ABI/testing/debugfs-aufs ++F: Documentation/ABI/testing/sysfs-aufs ++F: fs/aufs/ ++F: include/uapi/linux/aufs_type.h ++ + AUXILIARY DISPLAY DRIVERS + M: Miguel Ojeda Sandonis + W: http://miguelojeda.es/auxdisplay.htm diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 6cb1beb..30efd68 100644 --- a/drivers/block/loop.c diff --git a/debian/patches/features/all/aufs3/aufs3-kbuild.patch b/debian/patches/features/all/aufs3/aufs3-kbuild.patch index 77cea2478..d1316a3e0 100644 --- a/debian/patches/features/all/aufs3/aufs3-kbuild.patch +++ b/debian/patches/features/all/aufs3/aufs3-kbuild.patch @@ -1,12 +1,12 @@ From: J. R. Okajima -Date: Sun Jun 15 19:47:55 2014 +0900 -Subject: aufs3.x-rcN kbuild patch -Origin: http://sourceforge.net/p/aufs/aufs3-standalone/ci/501539c2f9478ef69fa42acfb43ef1420d9bb524/tree/ +Date: Thu Aug 7 21:42:20 2014 +0900 +Subject: aufs3.16 kbuild patch +Origin: http://sourceforge.net/p/aufs/aufs3-standalone/ci/888949daf96bf7e2b857dc38e22029513f94d4ae/tree/ Bug-Debian: https://bugs.debian.org/541828 Patch headers added by debian/patches/features/all/aufs3/gen-patch -aufs3.x-rcN kbuild patch +aufs3.16 kbuild patch diff --git a/fs/Kconfig b/fs/Kconfig index 312393f..78632ed 100644 diff --git a/debian/patches/features/all/aufs3/aufs3-mmap.patch b/debian/patches/features/all/aufs3/aufs3-mmap.patch index f32562802..8b1266602 100644 --- a/debian/patches/features/all/aufs3/aufs3-mmap.patch +++ b/debian/patches/features/all/aufs3/aufs3-mmap.patch @@ -1,12 +1,12 @@ From: J. R. Okajima -Date: Thu Jul 10 02:32:20 2014 +0900 -Subject: aufs3.x-rcN mmap patch -Origin: http://sourceforge.net/p/aufs/aufs3-standalone/ci/501539c2f9478ef69fa42acfb43ef1420d9bb524/tree/ +Date: Thu Aug 7 21:42:20 2014 +0900 +Subject: aufs3.16 mmap patch +Origin: http://sourceforge.net/p/aufs/aufs3-standalone/ci/888949daf96bf7e2b857dc38e22029513f94d4ae/tree/ Bug-Debian: https://bugs.debian.org/541828 Patch headers added by debian/patches/features/all/aufs3/gen-patch -aufs3.x-rcN mmap patch +aufs3.16 mmap patch diff --git a/fs/buffer.c b/fs/buffer.c index eba6e4f..31f0b2d 100644 @@ -79,109 +79,34 @@ index 678455d..0ef7ef4 100644 ino = inode->i_ino; pgoff = (loff_t)vma->vm_pgoff << PAGE_SHIFT; diff --git a/include/linux/mm.h b/include/linux/mm.h -index e03dd29..f849643 100644 +index e03dd29..dd32624 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h -@@ -18,6 +18,9 @@ - #include - #include - #include -+#include -+#include -+#include - - struct mempolicy; - struct anon_vma; -@@ -1184,6 +1187,93 @@ static inline int fixup_user_fault(struct task_struct *tsk, +@@ -1184,6 +1184,28 @@ static inline int fixup_user_fault(struct task_struct *tsk, } #endif -+/* -+ * Mainly for aufs which mmap(2) diffrent file and wants to print different path -+ * in /proc/PID/maps. -+ */ -+/* #define AUFS_DEBUG_MMAP */ -+static inline void aufs_trace(struct file *f, struct file *pr, -+ const char func[], int line, const char func2[]) -+{ -+#ifdef AUFS_DEBUG_MMAP -+ if (pr) -+ pr_info("%s:%d: %s, %p\n", func, line, func2, -+ f ? (char *)f->f_dentry->d_name.name : "(null)"); -+#endif -+} ++#ifdef CONFIG_MMU ++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); + -+static inline 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; -+ -+ aufs_trace(f, pr, func, line, __func__); -+ return (f && pr) ? pr : f; -+} -+ -+static inline void vmr_do_fput(struct vm_region *region, -+ const char func[], int line) -+{ -+ struct file *f = region->vm_file, *pr = region->vm_prfile; -+ -+ aufs_trace(f, pr, func, line, __func__); -+ fput(f); -+ if (f && pr) -+ fput(pr); -+} -+ -+static inline 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; -+ -+ aufs_trace(f, pr, func, line, __func__); -+ file_update_time(f); -+ if (f && pr) -+ file_update_time(pr); -+} -+ -+static inline 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; -+ -+ aufs_trace(f, pr, func, line, __func__); -+ return (f && pr) ? pr : f; -+} -+ -+static inline 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; -+ -+ aufs_trace(f, pr, func, line, __func__); -+ get_file(f); -+ if (f && pr) -+ get_file(pr); -+} -+ -+static inline void vma_do_fput(struct vm_area_struct *vma, -+ const char func[], int line) -+{ -+ struct file *f = vma->vm_file, *pr = vma->vm_prfile; -+ -+ aufs_trace(f, pr, func, line, __func__); -+ fput(f); -+ if (f && pr) -+ fput(pr); -+} -+ -+#define vmr_pr_or_file(region) vmr_do_pr_or_file(region, __func__, \ -+ __LINE__) -+#define vmr_fput(region) vmr_do_fput(region, __func__, __LINE__) +#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__) ++#else ++extern struct file *vmr_do_pr_or_file(struct vm_region *, const char[], int); ++extern void vmr_do_fput(struct vm_region *, const char[], int); ++ ++#define vmr_pr_or_file(region) vmr_do_pr_or_file(region, __func__, \ ++ __LINE__) ++#define vmr_fput(region) vmr_do_fput(region, __func__, __LINE__) ++#endif /* CONFIG_MMU */ + extern int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write); extern int access_remote_vm(struct mm_struct *mm, unsigned long addr, @@ -219,11 +144,24 @@ index 6a13c46..714302c 100644 if (tmp->vm_flags & VM_DENYWRITE) atomic_dec(&inode->i_writecount); mutex_lock(&mapping->i_mmap_mutex); +diff --git a/mm/Makefile b/mm/Makefile +index 4064f3e..0003fdf 100644 +--- a/mm/Makefile ++++ b/mm/Makefile +@@ -18,7 +18,7 @@ obj-y := filemap.o mempool.o oom_kill.o fadvise.o \ + mm_init.o mmu_context.o percpu.o slab_common.o \ + compaction.o balloon_compaction.o vmacache.o \ + interval_tree.o list_lru.o workingset.o \ +- iov_iter.o $(mmu-y) ++ iov_iter.o prfile.o $(mmu-y) + + obj-y += init-mm.o + diff --git a/mm/filemap.c b/mm/filemap.c -index dafb06f..f8c0ba3 100644 +index 900edfa..f4dda0c 100644 --- a/mm/filemap.c +++ b/mm/filemap.c -@@ -2037,7 +2037,7 @@ int filemap_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) +@@ -2040,7 +2040,7 @@ int filemap_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) int ret = VM_FAULT_LOCKED; sb_start_pagefault(inode->i_sb); @@ -287,7 +225,7 @@ index a402f8f..134e15d 100644 return error; } diff --git a/mm/memory.c b/mm/memory.c -index d67fd9f..aa1e55d 100644 +index 8b44f76..69a72bf 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -2161,7 +2161,7 @@ reuse: @@ -422,3 +360,95 @@ index 4a852f6..b369644 100644 kmem_cache_free(vm_area_cachep, vma); kleave(" = %d", ret); return ret; +diff --git a/mm/prfile.c b/mm/prfile.c +new file mode 100644 +index 0000000..fc708d2 +--- /dev/null ++++ b/mm/prfile.c +@@ -0,0 +1,86 @@ ++/* ++ * Mainly for aufs which mmap(2) diffrent file and wants to print different path ++ * in /proc/PID/maps. ++ * Call these functions via macros defined in linux/mm.h. ++ * ++ * See Documentation/filesystems/aufs/design/06mmap.txt ++ * ++ * Copyright (c) 2014 Junjro R. Okajima ++ * Copyright (c) 2014 Ian Campbell ++ */ ++ ++#include ++#include ++#include ++ ++/* #define PRFILE_TRACE */ ++static inline void prfile_trace(struct file *f, struct file *pr, ++ const char func[], int line, const char func2[]) ++{ ++#ifdef PRFILE_TRACE ++ if (pr) ++ pr_info("%s:%d: %s, %p\n", func, line, func2, ++ f ? (char *)f->f_dentry->d_name.name : "(null)"); ++#endif ++} ++ ++#ifdef CONFIG_MMU ++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); ++} ++#else ++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/debian/patches/features/all/aufs3/aufs3-remove-circular-includes.patch b/debian/patches/features/all/aufs3/aufs3-remove-circular-includes.patch deleted file mode 100644 index f6bea9ec2..000000000 --- a/debian/patches/features/all/aufs3/aufs3-remove-circular-includes.patch +++ /dev/null @@ -1,222 +0,0 @@ -From: Ian Campbell -Date: Sun, 20 Jul 2014 16:13:35 +0100 -Subject: aufs3: remove include of linux/fs.h from linux/mm.h -Forwarded: http://sourceforge.net/p/aufs/mailman/message/32628514/ - -This include is added by aufs3-mmap.patch but causes circular dependencies on -arm64 as seen with the Debian kernel packages in http://buildd.debian-ports.org/status/fetch.php?pkg=linux&arch=arm64&ver=3.14.12-1&stamp=1405234443 which contains: - -In file included from /«PKGBUILDDIR»/include/linux/mm.h:23:0, - from /«PKGBUILDDIR»/include/linux/pid_namespace.h:6, - from /«PKGBUILDDIR»/include/linux/ptrace.h:9, - from /«PKGBUILDDIR»/arch/arm64/include/asm/compat.h:26, - from /«PKGBUILDDIR»/arch/arm64/include/asm/stat.h:23, - from /«PKGBUILDDIR»/include/linux/stat.h:5, - from /«PKGBUILDDIR»/include/linux/module.h:10, - from /«PKGBUILDDIR»/init/main.c:15: -/«PKGBUILDDIR»/include/linux/fs.h:1575:64: warning: 'struct kstat' declared inside parameter list [enabled by default] - int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *); - -According to http://article.gmane.org/gmane.linux.ports.arm.kernel/342042 -> The added mm.h->fs.h looks like a mistake, it should not be there, and we have -> in the past worked hard to separate mm.h, sched.h and fs.h from one another. - -Move all of the static inline functions added to mm.h by -aufs3-mmap.patch into a new file, mm/aufs_mmap.c, instead to avoid the -new includes in mm.h. - -Signed-off-by: Ian Campbell - ---- a/include/linux/mm.h -+++ b/include/linux/mm.h -@@ -18,9 +18,6 @@ - #include - #include - #include --#include --#include --#include - - struct mempolicy; - struct anon_vma; -@@ -1187,83 +1184,17 @@ static inline int fixup_user_fault(struc - } - #endif - --/* -- * Mainly for aufs which mmap(2) diffrent file and wants to print different path -- * in /proc/PID/maps. -- */ --/* #define AUFS_DEBUG_MMAP */ --static inline void aufs_trace(struct file *f, struct file *pr, -- const char func[], int line, const char func2[]) --{ --#ifdef AUFS_DEBUG_MMAP -- if (pr) -- pr_info("%s:%d: %s, %p\n", func, line, func2, -- f ? (char *)f->f_dentry->d_name.name : "(null)"); --#endif --} -- --static inline 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; -- -- aufs_trace(f, pr, func, line, __func__); -- return (f && pr) ? pr : f; --} -- --static inline void vmr_do_fput(struct vm_region *region, -- const char func[], int line) --{ -- struct file *f = region->vm_file, *pr = region->vm_prfile; -- -- aufs_trace(f, pr, func, line, __func__); -- fput(f); -- if (f && pr) -- fput(pr); --} -- --static inline 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; -- -- aufs_trace(f, pr, func, line, __func__); -- file_update_time(f); -- if (f && pr) -- file_update_time(pr); --} -- --static inline 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; -- -- aufs_trace(f, pr, func, line, __func__); -- return (f && pr) ? pr : f; --} -- --static inline 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; -- -- aufs_trace(f, pr, func, line, __func__); -- get_file(f); -- if (f && pr) -- get_file(pr); --} -- --static inline void vma_do_fput(struct vm_area_struct *vma, -- const char func[], int line) --{ -- struct file *f = vma->vm_file, *pr = vma->vm_prfile; -- -- aufs_trace(f, pr, func, line, __func__); -- fput(f); -- if (f && pr) -- fput(pr); --} -- -+extern struct file *vmr_do_pr_or_file(struct vm_region *region, -+ const char func[], int line); -+extern void vmr_do_fput(struct vm_region *region, const char func[], int line); -+extern void vma_do_file_update_time(struct vm_area_struct *vma, -+ const char func[], int line); -+extern struct file *vma_do_pr_or_file(struct vm_area_struct *vma, -+ const char func[], int line); -+extern void vma_do_get_file(struct vm_area_struct *vma, -+ const char func[], int line); -+extern void vma_do_fput(struct vm_area_struct *vma, const char func[], int line); -+ - #define vmr_pr_or_file(region) vmr_do_pr_or_file(region, __func__, \ - __LINE__) - #define vmr_fput(region) vmr_do_fput(region, __func__, __LINE__) ---- a/mm/Makefile -+++ b/mm/Makefile -@@ -21,6 +21,7 @@ obj-y := filemap.o mempool.o oom_kill. - iov_iter.o $(mmu-y) - - obj-y += init-mm.o -+obj-y += aufs_mmap.o - - ifdef CONFIG_NO_BOOTMEM - obj-y += nobootmem.o ---- /dev/null -+++ b/mm/aufs_mmap.c -@@ -0,0 +1,73 @@ -+#include -+#include -+#include -+ -+/* -+ * Mainly for aufs which mmap(2) diffrent file and wants to print different path -+ * in /proc/PID/maps. -+ */ -+/* #define AUFS_DEBUG_MMAP */ -+static inline void aufs_trace(struct file *f, struct file *pr, -+ const char func[], int line, const char func2[]) -+{ -+#ifdef AUFS_DEBUG_MMAP -+ if (pr) -+ pr_info("%s:%d: %s, %p\n", func, line, func2, -+ f ? (char *)f->f_dentry->d_name.name : "(null)"); -+#endif -+} -+ -+#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; -+ aufs_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; -+ aufs_trace(f, pr, func, line, __func__); -+ fput(f); -+ if (f && pr) -+ fput(pr); -+} -+#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; -+ aufs_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; -+ aufs_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; -+ aufs_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; -+ aufs_trace(f, pr, func, line, __func__); -+ fput(f); -+ if (f && pr) -+ fput(pr); -+} diff --git a/debian/patches/features/all/aufs3/aufs3-standalone.patch b/debian/patches/features/all/aufs3/aufs3-standalone.patch index ca5d77c40..c8ef3d05e 100644 --- a/debian/patches/features/all/aufs3/aufs3-standalone.patch +++ b/debian/patches/features/all/aufs3/aufs3-standalone.patch @@ -1,12 +1,12 @@ From: J. R. Okajima -Date: Fri Jun 20 09:25:26 2014 +0900 -Subject: aufs3.x-rcN standalone patch -Origin: http://sourceforge.net/p/aufs/aufs3-standalone/ci/501539c2f9478ef69fa42acfb43ef1420d9bb524/tree/ +Date: Thu Aug 7 21:42:20 2014 +0900 +Subject: aufs3.16 standalone patch +Origin: http://sourceforge.net/p/aufs/aufs3-standalone/ci/888949daf96bf7e2b857dc38e22029513f94d4ae/tree/ Bug-Debian: https://bugs.debian.org/541828 Patch headers added by debian/patches/features/all/aufs3/gen-patch -aufs3.x-rcN standalone patch +aufs3.16 standalone patch diff --git a/fs/inode.c b/fs/inode.c index b225c0f..73259c8 100644 @@ -121,7 +121,7 @@ index d90deaa..60b4239 100644 static int fsnotify_mark_destroy(void *ignored) { diff --git a/fs/open.c b/fs/open.c -index 36662d0..9a7e1e0 100644 +index d6fd3ac..5e99d8b 100644 --- a/fs/open.c +++ b/fs/open.c @@ -62,6 +62,7 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs, @@ -132,7 +132,7 @@ index 36662d0..9a7e1e0 100644 long vfs_truncate(struct path *path, loff_t length) { -@@ -299,6 +300,7 @@ int do_fallocate(struct file *file, int mode, loff_t offset, loff_t len) +@@ -298,6 +299,7 @@ int do_fallocate(struct file *file, int mode, loff_t offset, loff_t len) sb_end_write(inode->i_sb); return ret; } diff --git a/debian/patches/series b/debian/patches/series index fd4cdece8..4a43e77a0 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -24,7 +24,6 @@ features/all/aufs3/aufs3-mmap.patch features/all/aufs3/aufs3-standalone.patch features/all/aufs3/aufs3-add.patch # Debian-specific changes -features/all/aufs3/aufs3-remove-circular-includes.patch debian/aufs3-mark-as-staging.patch # Change some defaults for security reasons