aboutsummaryrefslogtreecommitdiff
path: root/ubuntu
diff options
context:
space:
mode:
authorAndy Whitcroft <apw@canonical.com>2010-11-22 15:51:22 +0000
committerJohn Rigby <john.rigby@linaro.org>2011-09-23 08:47:33 -0600
commit5abe14bec7860b9684adca0a9a692442a024d689 (patch)
tree9f8260dd571aee3d47a13c18a049577e6217b8fb /ubuntu
parent7280367b3ef11ba2e806a3a7cb4bd99d11140ac6 (diff)
UBUNTU: ubuntu: AUFS -- update to 097bf62d6f49619359d34bf17f242df38562489a
commit 097bf62d6f49619359d34bf17f242df38562489a Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Sat Nov 20 03:53:46 2010 +0900 aufs: for 2.6.37, convert get_sb into mount Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit 790de652f1cb83fbf6570209b96726445a2b5467 Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Sat Nov 20 03:53:25 2010 +0900 aufs: for 2.6.37, llseek dir too Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit 9e02a87b93b452ccff5003c3b5d086b44dd03ffd Author: Andy Whitcroft <apw@canonical.com> Date: Mon Nov 8 19:51:06 2010 +0000 AUFS -- track changes to llseek in v2.6.37-rc1 The commit below changed the default llseek function to no_llseek, reinstate the previous default for aufs2: commit 776c163b1b93c8dfa5edba885bc2bfbc2d228a5f Author: Arnd Bergmann <arnd@arndb.de> Date: Wed Jul 7 23:10:11 2010 +0200 vfs: make no_llseek the default Signed-off-by: Andy Whitcroft <apw@canonical.com> commit ec0cdbd350ddcd220fd3c1e0082e13435c73c9b9 Author: Andy Whitcroft <apw@canonical.com> Date: Mon Nov 8 19:51:05 2010 +0000 AUFS -- track changes to work queue initialisation The commit below modified the static initialisers for work queues, track those changes in aufs2: commit ca1cab37d91cbe8a8333732540d43cabb54cfa85 Author: Andrew Morton <akpm@linux-foundation.org> Date: Tue Oct 26 14:22:34 2010 -0700 workqueues: s/ON_STACK/ONSTACK/ Signed-off-by: Andy Whitcroft <apw@canonical.com> commit 83b979887788312197d63ade9f3ca09f1d66c6ff Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Sat Nov 20 02:24:41 2010 +0900 aufs: for 2.6.37, ihold Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit bfb074e1feabb7348f7dfb332928a2b48cbc67eb Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Sat Nov 20 01:54:19 2010 +0900 aufs: version string for aufs2.1-37 Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit 5dc527205e7581b41a4fa2f0d5ae4e741439a75c Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Sat Nov 20 00:48:26 2010 +0900 aufs: version string for aufs2.1-36 Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit 0a504fac95958f00c1737ff3de75163fad1df573 Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Fri Nov 19 23:09:38 2010 +0900 aufs stdalone: for 2.6.36, export file_sb_list_del Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit 6d6c06ea2102f0bba39272340104b780b3a43729 Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Fri Nov 19 23:06:55 2010 +0900 aufs: for 2.6.36, trying FMODE_NONOTIFY Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit 5db3ff4f186d2ce58c3079a6af5e1a44c06c5c37 Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Fri Nov 19 23:05:52 2010 +0900 aufs: for 2.6.36, vfsmount_lock Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit 830b34ac1f53b8bb160bf93af7af0ec17e009e81 Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Fri Nov 19 23:05:29 2010 +0900 aufs: for 2.6.36, sysrq handler Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit fe4d2cad1dfedea6b6898ea9416c41dd20be9cff Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Fri Nov 19 23:04:01 2010 +0900 aufs: for 2.6.36, file_list I don't like this "copy" approach. Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit e2e21ce7f80d5b3d99661aa98386bb6854c3751e Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Fri Nov 19 00:18:45 2010 +0900 aufs: tiny, braces for macro Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit 6badb1ed1fe179b544c25aaf22c2ea572c3b3894 Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Fri Nov 19 00:18:02 2010 +0900 aufs: tiny, rename a parameter Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit 18d5ed7fa331024a64f63487d53b76c1e3e5fe4e Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Fri Nov 19 00:17:17 2010 +0900 aufs: tiny, remove spaces from a macro Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit 870bf721a61b42701bb014068c2f8537cc436bad Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Fri Nov 19 00:14:15 2010 +0900 aufs: minor optimization, xib_next_bit Try the next bit of previously free. Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit 47dce097ac07764af41703379f11973ba93d53bb Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Thu Nov 18 23:34:55 2010 +0900 aufs: bugfix, reverting bwh after a failure of unlink/rmdir The branch index of removing the just created whiteout differs from the old branch index of whiteout. Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit 152e87e5cc6a8c7850bcbf8021e755dc68fbd305 Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Thu Nov 18 23:29:58 2010 +0900 aufs: tiny, debugging drop_nlink Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit daf58169a1b2241cb0a3d39d51f95c6a4765bb66 Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Thu Nov 18 23:19:47 2010 +0900 aufs: possible bugfix, prevent unmounting for no wait wkq Use si_kobj instead of super_block object. Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit 1c16d762868b72747895b204dfa901400a469344 Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Thu Nov 18 22:14:54 2010 +0900 aufs: tiny, remove unnecessary test for O_TRUNC Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit af65dba02af73c4624b7702699c022347eea400e Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Thu Nov 18 22:00:41 2010 +0900 aufs: possible bugfix, missing iput() in lookup error While I don't think d_splice_alias() easily return an error, if it happens, aufs should call iput(). Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit 5d1aaf10a8fa2184783d776d4516be3acd604a18 Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Thu Nov 18 21:58:32 2010 +0900 aufs: possible bugfix, keep br_id positive When si_last_br_id wraps around, current code may not handle it well. By shrinking its bit width, keep br_id positive. Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit 31b66581cfd3afe26c9df901554e6255376760b9 Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Thu Nov 18 21:24:53 2010 +0900 aufs: bugfix, missing supports for the pseudo-link maintenance mode ->lookup and ->getattr MAY also touch the pseudo-link. They should return an error in the pseudo-link maintenance mode at once. Since introducing a pseudo-link maintenance mode, all unnecessary au_plink_test() should be avoided. Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit 5f69f48727369ed2aa81af041193720f066047d4 Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Thu Nov 18 21:07:52 2010 +0900 aufs: bugfix, protect sb->sb_file from remount by file array In chaging a branch attribute, aufs verifies whether the branch is chagable by testing all opened files. During this file object traveral, file object may be reclamed outside of aufs. Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit 0b721b0f59dfaf18599e983a0c2bfa330c2cef57 Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Thu Nov 18 21:05:38 2010 +0900 aufs: a new counter si_nfiles Count the number of opened files and the tests at remounting will use it. Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit e793e0835fc4cc0a468678fe861bec63bc0ba97c Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Thu Nov 18 20:19:06 2010 +0900 aufs: bugfix, protect sb->sb_inodes from remount by inode array In deleting a branch, aufs verifies whether the branch is unused by testing all cached inodes. During this inode traveral, inode may be reclamed outside of aufs. Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit 9ae1dfbcc9a53cc8b9d734032c9949ed9482863a Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Thu Nov 18 20:17:44 2010 +0900 aufs: a new counter si_ninodes Count the number of cached inodes and the tests at remounting will use it. Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit da5f6d12ed4b683f518e03490c3540a7a601db0f Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Thu Nov 18 16:48:30 2010 +0900 aufs: possible bugfix, replace some d_unhashed() by au_d_removed() The root dir may be unhashed, but it is obviously alive. The simple test by just d_unhashed() may misunderstand as if it was removed. Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit 96524002220bc3a551c4b4e5aa5ff77ef015d42c Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Thu Nov 18 16:47:13 2010 +0900 aufs: bugfix, introduce a new wrapper au_d_removed() The root dentry is unhashed but is not unlinked obviously. Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit 7142b9ba7a087bc9cc910aba696c3aa43f7a85f7 Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Thu Nov 18 16:46:26 2010 +0900 aufs: bugfix, deadlock around au_plink_lkup() au_plink_lkup() can be called from both of normal and wkq context via au_cpup_single(). It may cause a deadlock. Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit e249247d36d2af19d67ec594d0cc7029e1249e31 Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Thu Nov 18 16:42:46 2010 +0900 aufs: bugfix, reverse loop in au_update_dbend() I am afraid there never have happend, but it is obviously a bug. Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit fd1917e1f1900b8a130c79f83ccc5dd5591263ae Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Tue Sep 21 14:01:10 2010 +0900 aufs: tiny, meaningless bit op Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit 2028ad2fdff9241c7f3f00988c4673aabd2769bb Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Mon Sep 20 21:06:41 2010 +0900 aufs: acquire vfsmount_lock By the commits, 306c22a 2010-03-09 aufs stdalone: begin supporting linux-2.6.24-rcN, stop exporting vfsmount_lock 6433436 2010-03-09 aufs: begin supporting linux-2.6.24-rcN, call iterate_mounts() exporting vfsmount_lock was removed and replaced by iterate_mounts() call. But vfsmount_lock is still necessary for aufs. Inserting an "extern" delcaration is not so smart, but I wonder why iterate_mounts() doen't provide anoter version which acquire vfsmount_lock internally. By the way, the linux version in these old commits were wrong. They should be 34 instead of 24. Don't make fun of me. Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit 0669d87f6aa78908290cddef2770bdf70ac52a02 Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Mon Sep 20 21:04:42 2010 +0900 aufs stdalone: re-export vfsmount_lock By the commits, 306c22a 2010-03-09 aufs stdalone: begin supporting linux-2.6.24-rcN, stop exporting vfsmount_lock 6433436 2010-03-09 aufs: begin supporting linux-2.6.24-rcN, call iterate_mounts() exporting vfsmount_lock was removed and replaced by iterate_mounts() call. But vfsmount_lock is still necessary. By the way, the linux version in these old commits were wrong. They should be 34 instead of 24. Don't make fun of me. Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit 22343eb479940bd550aa15ba0a13130e10483991 Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Mon Sep 20 06:18:09 2010 +0900 aufs: possible bugfix, deadlock around remount When one remount process uses /sbin/mount.aufs expectedly, but the other remount process doesn't, a deadlock may happen. Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit 47c851312601076f077217e221db7f48e660481c Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Fri Sep 17 18:57:47 2010 +0900 aufs: plm mode, follow the changes Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit 7b4207ff802db466c4f4015c806b977b8bd38ca4 Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Fri Sep 17 10:21:23 2010 +0900 aufs: tiny, update simply Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit 4d1785f36fd1ac5593ccc45ac69f8c339c023a75 Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Fri Sep 17 09:50:09 2010 +0900 aufs: tiny, use a var instead of calling a func twice Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit 5c45016dc812b8feed80d6542fb1c48715ebb2d0 Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Thu Sep 16 11:12:01 2010 +0900 aufs: bugfix, unset the return value in an error path Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit 6eab56fb7cf1bd41b70e25356d130d088211c60e Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Tue Sep 14 16:18:12 2010 +0900 aufs: plm mode, debugging feature (This commit is just a part of "intorudce the pseudo-link maintenance mode" series) - add a verbose flag to au_plink_put() in order to produce a warning when the pseudo-link is not flushed. - test the process has a right to access to plink by AuDebugOn(). Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit d0be3d45e4ebc92a3919862a5281ea5ab20021d4 Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Tue Sep 14 16:04:19 2010 +0900 aufs: plm mode, flags for si_read_lock() (This commit is just a part of "intorudce the pseudo-link maintenance mode" series) Handle the new flags AuLock_NOPLM/NOPLMW for most si_read_lock() call. New si_read_lock() waits the pseudo-link maintenance mode to exit, or return an error at once. Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit ee2f73c05bfec715b1eb0687e2b590d934860c11 Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Tue Sep 14 14:22:24 2010 +0900 aufs: plm mode, flags for si_write_lock() (This commit is just a part of "intorudce the pseudo-link maintenance mode" series) Replace some si_noflush_write_lock() calls by a new si_write_lock() which is added flags argument. New si_write_lock() waits the pseudo-link maintenance mode to exit. Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit a5cb0dc275e36411710a62ec46f80e19ea347d5d Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Mon Sep 13 18:05:07 2010 +0900 aufs: plm mode, move sbi lock funcs Move si_(read|write)_lock() from super.h to sbinfo.c. Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit 67580fa2a03212c7516b6225125d554dd3fcdf5a Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Tue Sep 14 04:55:44 2010 +0900 aufs: plm mode, a new interface under proc_fs (This commit is just a part of "intorudce the pseudo-link maintenance mode" series) Intorudce a new interface under procfs. Users have to update and install aufs2-util.git which handles the procfs entry. Now the pseudo-link feature totally depends upon CONFIG_PROC_FS. Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit 19fd2f6b872b51d920aee24ed2794174eaa891d0 Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Tue Sep 14 02:37:49 2010 +0900 aufs: plm mode, remove plink ioctl, new au_plink_maint() (This commit is just a part of "intorudce the pseudo-link maintenance mode" series) Replace the current pseudo-link maintenance mode via ioctl by a new scheme using procfs interface. This patch doesn't contain the new interface. You will see it in later commits. Removing au_plink_ioctl(), AUFS_CTL_PLINK_MAINT and AUFS_CTL_PLINK_CLEAN means that users have to update and install aufs2-util.git too. - rewrite au_plink_maint_enter() and au_plink_maint_leave(). - remove au_plink_maint_block(). - remove au_plink_maint_leave() from aufs_release_dir(). - extract a part of au_plink_ioctl() and create a new func au_plink_clean(). Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit d29dfef499b9a579afc143ea8d6b6a5d97703bb7 Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Tue Sep 14 02:08:15 2010 +0900 aufs: intorudce the pseudo-link maintenance mode, definition (This commit is just a part of "intorudce the pseudo-link maintenance mode" series) New flags AuLock_NOPLM and AuLock_NOPLMW, and a new function au_plink_maint() which will replace au_plink_maint_block() later. They behave as like F_SETLK and F_SETLKW for all over aufs. Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit e327326f094b7ac0cef381cb2c2dfdd1c3a080f3 Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Mon Sep 13 18:04:28 2010 +0900 aufs: intorudce the pseudo-link maintenance mode, doc Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit c5a615bad4cfd48f1bca344c7494d43aa571e75c Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Mon Sep 13 03:04:32 2010 +0900 aufs: bugfix, race around Magic SysRq, s_inodes and s_files Protect sb->s_inodes and ->s_files from aufs Magic SysRq handler. For allocating inodes, VFS calls s_op->alloc_inode() and then adds it to s_inodes. Also for destroying, VFS removes it from s_inodes first and then calls s_op->destory_inode(). With this sequence, it is guranteed that the inode in s_inodes is always correct and we can refer struct au_iinfo. But for files, VFS adds the file object to s_files before calling f_op->open(), and calls ->release() before removing it from s_files. It means the file in s_files MAY be incorrect and we may not refer struct au_finfo. To support the file which is not initialized yet, aufs tests file->private_data. And to address the file which is released but still in s_files, aufs removes it from s_files first in file release operation. Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit 3816652bca1aa498f19482dc6c7b89c4b9a0556a Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Mon Sep 13 02:58:04 2010 +0900 aufs stdalone: export to access inodes and files Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit 96138ab2b4ec9de86ff66430c593a68371acf466 Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Mon Sep 13 02:56:00 2010 +0900 aufs stdlone: new auto-config CONFIG_AUFS_SBILIST Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit e71e072386b5aff7109ded6563bd3d35e08dd834 Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Mon Sep 13 02:53:40 2010 +0900 aufs: introduce au_sbinfo list Make a new list of all au_sbinfo objects. This is important for next commit which fixes a bug around Magic SysRq and others. Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit ebba50d69a7ce5ba1f5ab7184151e5eedb45b70a Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Mon Sep 13 02:45:30 2010 +0900 aufs: possible bugfix, nwt may be queued just before unmounting Just before unmounting, UDBA hnotify might be fired (or other "no wait task"). Make sure all events are flushed in aufs_kill_sb(). Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit e4a9bd53629be12e368a67292427df65343459fd Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Mon Sep 13 02:40:19 2010 +0900 aufs: possible bugfix, sb may be destroyed before au_si_free() The lifetime of super_block is maintained by VFS, while au_sbinfo is maintained by aufs via kobject. In au_si_free(), sb might be already destroyed. Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit e69d64436220c1a7708bc420ac759a71fd7ff971 Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Mon Sep 13 02:33:14 2010 +0900 aufs: tiny, convert s_op->umount_begin() to ->kill_sb() Current ->umount_begin() already became less meaningful. Implement newly ->kill_sb() and convert umount_begin() into it. Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit 5ab35c5dc0a541f25948ec68ff4d330229d32303 Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Mon Sep 13 02:17:58 2010 +0900 aufs: bugfix, branch management before au_call_rmdir_whtmp() Between au_whtmp_kick_rmdir() and au_call_rmdir_whtmp() (which is a "no wait task"), users may execute branch management, and the target branch "bindex" may be broken. Pass the branch instead of its index. Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit 9c86f2ea994fd4936e6cbc8e525d0c8fb4ca7011 Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Wed Sep 15 13:57:53 2010 +0900 Revert "aufs: more verbose at deleting a branch" This reverts commit 6c34a3c246941b965f14a1638c11683c202b72d2. Some "no wait task"s makes a branch busy. We should not continue when it is found. commit 2484f972e57f7c3be76bb0e9deeab098d704c41e Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Thu Aug 26 11:29:53 2010 +0900 Revert "ifdef __KERNEL__ for kernel.h" This reverts commit ba8f448c3c5da969b4b51503a7ac0015785bac6c. "make headers_install" is essentially necessary. commit 0d1c50fe861b27db7e401bf372e4fa513fc42967 Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Fri Sep 10 01:42:14 2010 +0900 aufs: begin of aufs2.1 Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit 77e008addb63ba96f7e8163e83c264903e8fc17a Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Fri Sep 10 00:58:26 2010 +0900 aufs: end of aufs2 and doubling donations Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit 9d80cf726157b9a5e24fb45553f7753622c4fa4c Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Sun Sep 5 18:17:52 2010 +0900 aufs: tiny, convert sec <--> jiffies Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit edeaf060bb5acbb46fee915319ed0423a3e8ffd1 Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Sun Sep 5 17:30:08 2010 +0900 aufs: bugfix, test h_mnt before reference in au_unpin() Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit 0a625f79b6ff4f666e470c7c387e53adf4bb9c35 Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Sun Sep 5 17:28:40 2010 +0900 aufs: bugfix, unnecessary finfo_fin() in an error path in do_open_sp() Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit 3b258d73ecbf9d05466444e54f6d8e40af123b71 Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Sun Sep 5 17:26:17 2010 +0900 aufs: tiny, refine debug print for file object Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit 3fd3605306d3d6e3fd6958f481a877e9c7119d70 Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Sun Sep 5 17:24:15 2010 +0900 aufs: bugfix, unnecessary iput in an error path in alloc_root() Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit c55326e652a55cd92b602cb011e79b5c719bc910 Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Sun Sep 5 17:21:50 2010 +0900 aufs: bugfix, wakeup in an error path in au_wkq_nowait() Wake up other processes who are waiting for completion of the task. Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit 72e9d220041ecc8d9a9f15c9734274c61906e498 Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Sun Sep 5 17:18:15 2010 +0900 aufs: bugfix, use br_id instead of bindex in au_br_mod_files_ro() The file objects may not be refreshed yet, and its branch index is unreliable here. Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit c8c330e9d032f047e5871995158dbc28fc111d7a Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Sun Sep 5 13:43:57 2010 +0900 aufs: tiny, warn once about ima Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit e602a3ad860d34034ae8d98ef663d5d2954d70c0 Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Sun Sep 5 16:53:56 2010 +0900 aufs: tiny, replace pr_warn in sysrq by printk Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit aa66464222a900644ef7b73956f7c8ca9656f9f7 Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Sun Sep 5 12:47:44 2010 +0900 aufs: tiny, include vt_kern.h from fs/aufs/debug.h Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit 8c35854e8b2a7a92015f5d763b4e71f9cec124be Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Sun Sep 5 12:44:27 2010 +0900 aufs: tiny, printing in sysrq Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit c41ae7e6249e4c11660904a2ccce6462030a3d87 Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Sun Sep 5 12:38:09 2010 +0900 aufs: tiny, reuse a variable in aufs_open_dir() Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit 21c612ca43e499b0f6461286f32a038bd30c7e1e Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Sun Sep 5 12:37:06 2010 +0900 aufs: tiny, set lock class for debugging Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit e8dad573843d47a421ebaf913dc958a9db1c108b Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Sun Sep 5 12:22:37 2010 +0900 aufs: unnecessary atomic *_return funcs Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit b0eb67fb8a6ed66964d679294f4cdd60f5159b25 Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Thu Aug 26 11:27:37 2010 +0900 aufs: describe about make headers_install Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> commit 630defc8f3ab3f10848a7b8b1f14c7c53814da1e Author: J. R. Okajima <hooanon05@yahoo.co.jp> Date: Mon Aug 23 22:24:06 2010 +0900 aufs: tiny, rename sysaufs_ket to ..._kset Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp> Signed-off-by: Andy Whitcroft <apw@canonical.com>
Diffstat (limited to 'ubuntu')
-rw-r--r--ubuntu/aufs/BOM2
-rw-r--r--ubuntu/aufs/Kconfig4
-rw-r--r--ubuntu/aufs/Makefile5
-rw-r--r--ubuntu/aufs/branch.c149
-rw-r--r--ubuntu/aufs/branch.h2
-rw-r--r--ubuntu/aufs/conf.mk2
-rw-r--r--ubuntu/aufs/cpup.h6
-rw-r--r--ubuntu/aufs/dcsub.h9
-rw-r--r--ubuntu/aufs/debug.c19
-rw-r--r--ubuntu/aufs/debug.h5
-rw-r--r--ubuntu/aufs/dentry.c11
-rw-r--r--ubuntu/aufs/dinfo.c2
-rw-r--r--ubuntu/aufs/dir.c9
-rw-r--r--ubuntu/aufs/f_op.c1
-rw-r--r--ubuntu/aufs/file.c13
-rw-r--r--ubuntu/aufs/finfo.c3
-rw-r--r--ubuntu/aufs/hfsnotify.c33
-rw-r--r--ubuntu/aufs/hinotify.c231
-rw-r--r--ubuntu/aufs/hnotify.c8
-rw-r--r--ubuntu/aufs/i_op.c46
-rw-r--r--ubuntu/aufs/i_op_del.c16
-rw-r--r--ubuntu/aufs/i_op_ren.c6
-rw-r--r--ubuntu/aufs/iinfo.c2
-rw-r--r--ubuntu/aufs/include/linux/Kbuild1
-rw-r--r--ubuntu/aufs/include/linux/aufs_type.h5
-rw-r--r--ubuntu/aufs/inode.c2
-rw-r--r--ubuntu/aufs/inode.h32
-rw-r--r--ubuntu/aufs/opts.c16
-rw-r--r--ubuntu/aufs/opts.h10
-rw-r--r--ubuntu/aufs/plink.c51
-rw-r--r--ubuntu/aufs/rdu.c6
-rw-r--r--ubuntu/aufs/sbinfo.c5
-rw-r--r--ubuntu/aufs/super.c136
-rw-r--r--ubuntu/aufs/super.h44
-rw-r--r--ubuntu/aufs/vdir.c6
-rw-r--r--ubuntu/aufs/vfsub.c11
-rw-r--r--ubuntu/aufs/vfsub.h19
-rw-r--r--ubuntu/aufs/wbr_policy.c11
-rw-r--r--ubuntu/aufs/whout.c3
-rw-r--r--ubuntu/aufs/whout.h6
-rw-r--r--ubuntu/aufs/wkq.c25
-rw-r--r--ubuntu/aufs/wkq.h6
-rw-r--r--ubuntu/aufs/xino.c8
43 files changed, 518 insertions, 469 deletions
diff --git a/ubuntu/aufs/BOM b/ubuntu/aufs/BOM
index a25a63e2457..efa81f9de29 100644
--- a/ubuntu/aufs/BOM
+++ b/ubuntu/aufs/BOM
@@ -1,2 +1,2 @@
URL: http://git.c3sl.ufpr.br/pub/scm/aufs/aufs2-standalone.git
-COMMIT: c656be344b5080b5a88cfc44977da2072c6b6f80
+COMMIT: 097bf62d6f49619359d34bf17f242df38562489a
diff --git a/ubuntu/aufs/Kconfig b/ubuntu/aufs/Kconfig
index 989f2de806b..17f8f75a5a6 100644
--- a/ubuntu/aufs/Kconfig
+++ b/ubuntu/aufs/Kconfig
@@ -58,6 +58,7 @@ config AUFS_HNOTIFY
If you want to modify files on branches directly, eg. bypassing aufs,
and want aufs to detect the changes of them fully, then enable this
option and use 'udba=notify' mount option.
+ Currently there is only one available configuration, "fsnotify".
It will have a negative impact to the performance.
See detail in aufs.5.
@@ -67,9 +68,6 @@ choice
config AUFS_HFSNOTIFY
bool "fsnotify"
select FSNOTIFY
-config AUFS_HINOTIFY
- bool "inotify (DEPRECATED)"
- depends on INOTIFY
endchoice
config AUFS_EXPORT
diff --git a/ubuntu/aufs/Makefile b/ubuntu/aufs/Makefile
index c83dd25f1c1..8e9f7c83921 100644
--- a/ubuntu/aufs/Makefile
+++ b/ubuntu/aufs/Makefile
@@ -9,8 +9,8 @@ endif
# cf. include/linux/kernel.h
# enable pr_debug
ccflags-y += -DDEBUG
-ccflags-y += -D'pr_fmt(fmt)="aufs %s:%d:%s[%d]: " fmt, \
- __func__, __LINE__, current->comm, current->pid'
+# sparse doesn't allow spaces
+ccflags-y += -D'pr_fmt(fmt)=AUFS_NAME"\040%s:%d:%s[%d]:\040"fmt,__func__,__LINE__,current->comm,current->pid'
obj-$(CONFIG_AUFS_FS) += aufs.o
aufs-y := module.o sbinfo.o super.o branch.o xino.o sysaufs.o opts.o \
@@ -30,7 +30,6 @@ aufs-$(CONFIG_DEBUG_FS) += dbgaufs.o
aufs-$(CONFIG_AUFS_BDEV_LOOP) += loop.o
aufs-$(CONFIG_AUFS_HNOTIFY) += hnotify.o
aufs-$(CONFIG_AUFS_HFSNOTIFY) += hfsnotify.o
-aufs-$(CONFIG_AUFS_HINOTIFY) += hinotify.o
aufs-$(CONFIG_AUFS_EXPORT) += export.o
aufs-$(CONFIG_AUFS_POLL) += poll.o
aufs-$(CONFIG_AUFS_RDU) += rdu.o
diff --git a/ubuntu/aufs/branch.c b/ubuntu/aufs/branch.c
index a890ae1bd5d..4687a35d43f 100644
--- a/ubuntu/aufs/branch.c
+++ b/ubuntu/aufs/branch.c
@@ -321,11 +321,11 @@ static int au_wbr_init(struct au_branch *br, struct super_block *sb,
* a limit for rmdir/rename a dir
* cf. AUFS_MAX_NAMELEN in include/linux/aufs_type.h
*/
- h_dentry = path->dentry;
- err = statfs_by_dentry(h_dentry, &kst);
+ err = vfs_statfs(path, &kst);
if (unlikely(err))
goto out;
err = -EINVAL;
+ h_dentry = path->dentry;
if (kst.f_namelen >= NAME_MAX)
err = au_br_init_wh(sb, br, perm, h_dentry);
else
@@ -354,6 +354,7 @@ static int au_br_init(struct au_branch *br, struct super_block *sb,
br->br_xino_upper = AUFS_XINO_TRUNC_INIT;
atomic_set(&br->br_xino_running, 0);
br->br_id = au_new_br_id(sb);
+ AuDebugOn(br->br_id < 0);
if (au_br_writable(add->perm)) {
err = au_wbr_init(br, sb, add->perm, &add->path);
@@ -584,15 +585,23 @@ static int test_inode_busy(struct super_block *sb, aufs_bindex_t bindex,
unsigned int sigen, const unsigned int verbose)
{
int err;
- struct inode *i;
+ unsigned long long max, ull;
+ struct inode *i, **array;
aufs_bindex_t bstart, bend;
+ array = au_iarray_alloc(sb, &max);
+ err = PTR_ERR(array);
+ if (IS_ERR(array))
+ goto out;
+
err = 0;
- list_for_each_entry(i, &sb->s_inodes, i_sb_list) {
- AuDebugOn(!atomic_read(&i->i_count));
- if (!list_empty(&i->i_dentry))
+ AuDbg("b%d\n", bindex);
+ for (ull = 0; !err && ull < max; ull++) {
+ i = array[ull];
+ if (i->i_ino == AUFS_ROOT_INO)
continue;
+ /* AuDbgInode(i); */
if (au_iigen(i) == sigen)
ii_read_lock_child(i);
else {
@@ -614,12 +623,13 @@ static int test_inode_busy(struct super_block *sb, aufs_bindex_t bindex,
&& (!S_ISDIR(i->i_mode) || bstart == bend)) {
err = -EBUSY;
AuVerbose(verbose, "busy i%lu\n", i->i_ino);
- ii_read_unlock(i);
- break;
+ AuDbgInode(i);
}
ii_read_unlock(i);
}
+ au_iarray_free(array, max);
+out:
return err;
}
@@ -835,41 +845,78 @@ static int need_sigen_inc(int old, int new)
|| 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 super_block *sb = arg;
+
+ n = 0;
+ p = a;
+ lg_global_lock(files_lglock);
+ do_file_list_for_each_entry(sb, f) {
+ if (au_fi(f)
+ && !special_file(f->f_dentry->d_inode->i_mode)) {
+ get_file(f);
+ *p++ = f;
+ n++;
+ AuDebugOn(n > max);
+ }
+ } while_file_list_for_each_entry;
+ lg_global_unlock(files_lglock);
+
+ 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;
- unsigned long n, ul, bytes, files;
+ int err, do_warn;
+ unsigned long long ull, max;
aufs_bindex_t br_id;
- struct file *file, *hf, **a;
+ struct file *file, *hf, **array;
struct dentry *dentry;
struct inode *inode;
struct au_hfile *hfile;
- const int step_bytes = 1024, /* memory allocation unit */
- step_files = step_bytes / sizeof(*a);
- err = -ENOMEM;
- n = 0;
- bytes = step_bytes;
- files = step_files;
- a = kmalloc(bytes, GFP_NOFS);
- if (unlikely(!a))
+ array = au_farray_alloc(sb, &max);
+ err = PTR_ERR(array);
+ if (IS_ERR(array))
goto out;
- /* no need file_list_lock() since sbinfo is locked? defered? */
+ do_warn = 0;
br_id = au_sbr_id(sb, bindex);
- do_file_list_for_each_entry(sb, file) {
- if (special_file(file->f_dentry->d_inode->i_mode))
- continue;
+ for (ull = 0; ull < max; ull++) {
+ file = array[ull];
dentry = file->f_dentry;
inode = dentry->d_inode;
- AuDbg("%.*s\n", AuDLNPair(file->f_dentry));
+ /* AuDbg("%.*s\n", AuDLNPair(file->f_dentry)); */
fi_read_lock(file);
if (unlikely(au_test_mmapped(file))) {
err = -EBUSY;
+ AuDbgFile(file);
FiMustNoWaiters(file);
fi_read_unlock(file);
- goto out_free;
+ goto out_array;
}
hfile = &au_fi(file)->fi_htop;
@@ -877,39 +924,33 @@ static int au_br_mod_files_ro(struct super_block *sb, aufs_bindex_t bindex)
if (!S_ISREG(inode->i_mode)
|| !(file->f_mode & FMODE_WRITE)
|| hfile->hf_br->br_id != br_id
- || !(hf->f_mode & FMODE_WRITE)) {
- FiMustNoWaiters(file);
- fi_read_unlock(file);
- continue;
+ || !(hf->f_mode & FMODE_WRITE))
+ array[ull] = NULL;
+ else {
+ do_warn = 1;
+ get_file(file);
}
FiMustNoWaiters(file);
fi_read_unlock(file);
-
- if (n < files)
- a[n++] = hf;
- else {
- void *p;
-
- err = -ENOMEM;
- bytes += step_bytes;
- files += step_files;
- p = krealloc(a, bytes, GFP_NOFS);
- if (p) {
- a = p;
- a[n++] = hf;
- } else
- goto out_free;
- }
- } while_file_list_for_each_entry;
+ fput(file);
+ }
err = 0;
- if (n)
+ if (do_warn)
au_warn_ima();
- for (ul = 0; ul < n; ul++) {
+
+ for (ull = 0; ull < max; ull++) {
+ file = array[ull];
+ if (!file)
+ continue;
+
/* todo: already flushed? */
/* cf. fs/super.c:mark_files_ro() */
- hf = a[ul];
+ /* fi_read_lock(file); */
+ hfile = &au_fi(file)->fi_htop;
+ hf = hfile->hf_file;
+ /* fi_read_unlock(file); */
hf->f_mode &= ~FMODE_WRITE;
if (!file_check_writeable(hf)) {
file_release_write(hf);
@@ -917,14 +958,15 @@ static int au_br_mod_files_ro(struct super_block *sb, aufs_bindex_t bindex)
}
}
-out_free:
- kfree(a);
+out_array:
+ au_farray_free(array, max);
out:
+ AuTraceErr(err);
return err;
}
int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
- int *do_update)
+ int *do_refresh)
{
int err, rerr;
aufs_bindex_t bindex;
@@ -999,10 +1041,11 @@ int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
}
if (!err) {
- *do_update |= need_sigen_inc(br->br_perm, mod->perm);
+ *do_refresh |= need_sigen_inc(br->br_perm, mod->perm);
br->br_perm = mod->perm;
}
out:
+ AuTraceErr(err);
return err;
}
diff --git a/ubuntu/aufs/branch.h b/ubuntu/aufs/branch.h
index cf430a57f0a..ddbfbb81008 100644
--- a/ubuntu/aufs/branch.h
+++ b/ubuntu/aufs/branch.h
@@ -144,7 +144,7 @@ struct au_opt_del;
int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount);
struct au_opt_mod;
int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
- int *do_update);
+ int *do_refresh);
/* xino.c */
static const loff_t au_loff_max = LLONG_MAX;
diff --git a/ubuntu/aufs/conf.mk b/ubuntu/aufs/conf.mk
index 9a57d841c45..9217b48c1a3 100644
--- a/ubuntu/aufs/conf.mk
+++ b/ubuntu/aufs/conf.mk
@@ -9,7 +9,7 @@ endef
AuConfAll = BRANCH_MAX_127 BRANCH_MAX_511 BRANCH_MAX_1023 BRANCH_MAX_32767 \
SBILIST \
- HNOTIFY HFSNOTIFY HINOTIFY \
+ HNOTIFY HFSNOTIFY \
EXPORT INO_T_64 \
RDU \
SP_IATTR \
diff --git a/ubuntu/aufs/cpup.h b/ubuntu/aufs/cpup.h
index 506350d20b1..cd77860c114 100644
--- a/ubuntu/aufs/cpup.h
+++ b/ubuntu/aufs/cpup.h
@@ -46,8 +46,10 @@ void au_cpup_attr_all(struct inode *inode, int force);
#define AuCpup_KEEPLINO (1 << 1) /* do not clear the lower xino,
for link(2) */
#define au_ftest_cpup(flags, name) ((flags) & AuCpup_##name)
-#define au_fset_cpup(flags, name) { (flags) |= AuCpup_##name; }
-#define au_fclr_cpup(flags, name) { (flags) &= ~AuCpup_##name; }
+#define au_fset_cpup(flags, name) \
+ do { (flags) |= AuCpup_##name; } while (0)
+#define au_fclr_cpup(flags, name) \
+ do { (flags) &= ~AuCpup_##name; } while (0)
int au_copy_file(struct file *dst, struct file *src, loff_t len);
int au_sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
diff --git a/ubuntu/aufs/dcsub.h b/ubuntu/aufs/dcsub.h
index 0c87168f570..be25a134621 100644
--- a/ubuntu/aufs/dcsub.h
+++ b/ubuntu/aufs/dcsub.h
@@ -25,6 +25,7 @@
#ifdef __KERNEL__
+#include <linux/dcache.h>
#include <linux/types.h>
struct dentry;
@@ -41,6 +42,7 @@ struct au_dcsub_pages {
/* ---------------------------------------------------------------------- */
+/* dcsub.c */
int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp);
void au_dpages_free(struct au_dcsub_pages *dpages);
typedef int (*au_dpages_test)(struct dentry *dentry, void *arg);
@@ -50,5 +52,12 @@ int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry,
int do_include, au_dpages_test test, void *arg);
int au_test_subdir(struct dentry *d1, struct dentry *d2);
+/* ---------------------------------------------------------------------- */
+
+static inline int au_d_removed(struct dentry *d)
+{
+ return !IS_ROOT(d) && d_unhashed(d);
+}
+
#endif /* __KERNEL__ */
#endif /* __AUFS_DCSUB_H__ */
diff --git a/ubuntu/aufs/debug.c b/ubuntu/aufs/debug.c
index 74af9d4484c..ec8dc079edc 100644
--- a/ubuntu/aufs/debug.c
+++ b/ubuntu/aufs/debug.c
@@ -21,6 +21,7 @@
*/
#include <linux/module.h>
+#include <linux/vt_kern.h>
#include "aufs.h"
int aufs_debug;
@@ -377,26 +378,12 @@ void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen)
void au_dbg_verify_kthread(void)
{
- struct task_struct *tsk = current;
-
- if ((tsk->flags & PF_KTHREAD)
- && !strncmp(tsk->comm, AUFS_WKQ_NAME "/", sizeof(AUFS_WKQ_NAME))) {
+ if (current->flags & PF_WQ_WORKER) {
au_dbg_blocked();
- BUG();
+ WARN_ON(1);
}
}
-static void au_dbg_do_verify_wkq(void *args)
-{
- BUG_ON(current_fsuid());
- BUG_ON(rlimit(RLIMIT_FSIZE) != RLIM_INFINITY);
-}
-
-void au_dbg_verify_wkq(void)
-{
- au_wkq_wait(au_dbg_do_verify_wkq, NULL);
-}
-
/* ---------------------------------------------------------------------- */
void au_debug_sbinfo_init(struct au_sbinfo *sbinfo __maybe_unused)
diff --git a/ubuntu/aufs/debug.h b/ubuntu/aufs/debug.h
index 443f4c5f207..c6b2626dee7 100644
--- a/ubuntu/aufs/debug.h
+++ b/ubuntu/aufs/debug.h
@@ -27,10 +27,13 @@
#include <asm/system.h>
#include <linux/bug.h>
+/* #include <linux/err.h> */
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kallsyms.h>
+/* #include <linux/kernel.h> */
#include <linux/delay.h>
+/* #include <linux/kd.h> */
#include <linux/sysrq.h>
#include <linux/aufs_type.h>
@@ -133,7 +136,6 @@ void au_dbg_verify_dir_parent(struct dentry *dentry, unsigned int sigen);
void au_dbg_verify_nondir_parent(struct dentry *dentry, unsigned int sigen);
void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen);
void au_dbg_verify_kthread(void);
-void au_dbg_verify_wkq(void);
int __init au_debug_init(void);
void au_debug_sbinfo_init(struct au_sbinfo *sbinfo);
@@ -199,7 +201,6 @@ AuStubVoid(au_dbg_verify_nondir_parent, struct dentry *dentry,
unsigned int sigen)
AuStubVoid(au_dbg_verify_gen, struct dentry *parent, unsigned int sigen)
AuStubVoid(au_dbg_verify_kthread, void)
-AuStubVoid(au_dbg_verify_wkq, void)
AuStubInt0(__init au_debug_init, void)
AuStubVoid(au_debug_sbinfo_init, struct au_sbinfo *sbinfo)
diff --git a/ubuntu/aufs/dentry.c b/ubuntu/aufs/dentry.c
index d669312c155..2743e26f5ee 100644
--- a/ubuntu/aufs/dentry.c
+++ b/ubuntu/aufs/dentry.c
@@ -82,8 +82,10 @@ static void au_call_lkup_one(void *args)
#define AuLkup_ALLOW_NEG 1
#define au_ftest_lkup(flags, name) ((flags) & AuLkup_##name)
-#define au_fset_lkup(flags, name) { (flags) |= AuLkup_##name; }
-#define au_fclr_lkup(flags, name) { (flags) &= ~AuLkup_##name; }
+#define au_fset_lkup(flags, name) \
+ do { (flags) |= AuLkup_##name; } while (0)
+#define au_fclr_lkup(flags, name) \
+ do { (flags) &= ~AuLkup_##name; } while (0)
struct au_do_lookup_args {
unsigned int flags;
@@ -629,8 +631,9 @@ static int h_d_revalidate(struct dentry *dentry, struct inode *inode,
name = &dentry->d_name;
/*
- * Theoretically, REVAL test should be unnecessary in case of INOTIFY.
- * But inotify doesn't fire some necessary events,
+ * Theoretically, REVAL test should be unnecessary in case of
+ * {FS,I}NOTIFY.
+ * But {fs,i}notify doesn't fire some necessary events,
* IN_ATTRIB for atime/nlink/pageio
* IN_DELETE for NFS dentry
* Let's do REVAL test too.
diff --git a/ubuntu/aufs/dinfo.c b/ubuntu/aufs/dinfo.c
index b57ef24d883..4a638dc92b5 100644
--- a/ubuntu/aufs/dinfo.c
+++ b/ubuntu/aufs/dinfo.c
@@ -373,7 +373,7 @@ void au_update_dbend(struct dentry *dentry)
struct dentry *h_dentry;
bstart = au_dbstart(dentry);
- for (bindex = au_dbend(dentry); bindex <= bstart; bindex--) {
+ for (bindex = au_dbend(dentry); bindex >= bstart; bindex--) {
h_dentry = au_h_dptr(dentry, bindex);
if (!h_dentry)
continue;
diff --git a/ubuntu/aufs/dir.c b/ubuntu/aufs/dir.c
index b7a93029d39..d97ec02e0eb 100644
--- a/ubuntu/aufs/dir.c
+++ b/ubuntu/aufs/dir.c
@@ -203,10 +203,12 @@ static int aufs_release_dir(struct inode *inode __maybe_unused,
struct file *file)
{
struct au_vdir *vdir_cache;
+ struct super_block *sb;
struct au_finfo *finfo;
struct au_fidir *fidir;
aufs_bindex_t bindex, bend;
+ sb = file->f_dentry->d_sb;
finfo = au_fi(file);
fidir = finfo->fi_hdir;
if (fidir) {
@@ -426,8 +428,10 @@ out:
#define AuTestEmpty_CALLED (1 << 1)
#define AuTestEmpty_SHWH (1 << 2)
#define au_ftest_testempty(flags, name) ((flags) & AuTestEmpty_##name)
-#define au_fset_testempty(flags, name) { (flags) |= AuTestEmpty_##name; }
-#define au_fclr_testempty(flags, name) { (flags) &= ~AuTestEmpty_##name; }
+#define au_fset_testempty(flags, name) \
+ do { (flags) |= AuTestEmpty_##name; } while (0)
+#define au_fclr_testempty(flags, name) \
+ do { (flags) &= ~AuTestEmpty_##name; } while (0)
#ifndef CONFIG_AUFS_SHWH
#undef AuTestEmpty_SHWH
@@ -625,6 +629,7 @@ int au_test_empty(struct dentry *dentry, struct au_nhash *whlist)
const struct file_operations aufs_dir_fop = {
.owner = THIS_MODULE,
+ .llseek = default_llseek,
.read = generic_read_dir,
.readdir = aufs_readdir,
.unlocked_ioctl = aufs_ioctl_dir,
diff --git a/ubuntu/aufs/f_op.c b/ubuntu/aufs/f_op.c
index 67f2a5b0159..829a67e3c2d 100644
--- a/ubuntu/aufs/f_op.c
+++ b/ubuntu/aufs/f_op.c
@@ -85,6 +85,7 @@ int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file)
file_sb_list_del(file);
au_set_h_fptr(file, bindex, NULL);
}
+
au_finfo_fin(file);
return 0;
}
diff --git a/ubuntu/aufs/file.c b/ubuntu/aufs/file.c
index 33ce3c7cdfe..15e38ce31c6 100644
--- a/ubuntu/aufs/file.c
+++ b/ubuntu/aufs/file.c
@@ -54,8 +54,10 @@ struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
h_inode = h_dentry->d_inode;
if (au_test_nfsd() && !h_inode)
goto out;
- if (unlikely((!d_unhashed(dentry) && d_unhashed(h_dentry))
- || !h_inode))
+ if (unlikely((!d_unhashed(dentry) && au_d_removed(h_dentry))
+ || !h_inode
+ /* || !dentry->d_inode->i_nlink */
+ ))
goto out;
sb = dentry->d_sb;
@@ -365,7 +367,8 @@ static int au_file_refresh_by_inode(struct file *file, int *need_reopen)
di_read_lock_parent(parent, AuLock_IR);
hi_wh = au_hi_wh(inode, bstart);
- if (au_opt_test(au_mntflags(sb), PLINK)
+ if (!S_ISDIR(inode->i_mode)
+ && au_opt_test(au_mntflags(sb), PLINK)
&& au_plink_test(inode)
&& !d_unhashed(dentry)) {
err = au_test_and_cpup_dirs(dentry, bstart);
@@ -434,7 +437,7 @@ static void au_do_refresh_dir(struct file *file)
}
p = fidir->fd_hfile;
- if (!au_test_mmapped(file) && !d_unhashed(file->f_dentry)) {
+ if (!au_test_mmapped(file) && !au_d_removed(file->f_dentry)) {
bend = au_sbend(sb);
for (finfo->fi_btop = 0; finfo->fi_btop <= bend;
finfo->fi_btop++, p++)
@@ -498,7 +501,7 @@ static int refresh_file(struct file *file, int (*reopen)(struct file *file))
need_reopen = 1;
if (!au_test_mmapped(file))
err = au_file_refresh_by_inode(file, &need_reopen);
- if (!err && need_reopen && !d_unhashed(dentry))
+ if (!err && need_reopen && !au_d_removed(dentry))
err = reopen(file);
if (!err) {
au_update_figen(file);
diff --git a/ubuntu/aufs/finfo.c b/ubuntu/aufs/finfo.c
index d618e46ed13..0ffb5538fd1 100644
--- a/ubuntu/aufs/finfo.c
+++ b/ubuntu/aufs/finfo.c
@@ -126,6 +126,8 @@ void au_finfo_fin(struct file *file)
{
struct au_finfo *finfo;
+ au_nfiles_dec(file->f_dentry->d_sb);
+
finfo = au_fi(file);
AuDebugOn(finfo->fi_hdir);
AuRwDestroy(&finfo->fi_rwsem);
@@ -158,6 +160,7 @@ int au_finfo_init(struct file *file, struct au_fidir *fidir)
goto out;
err = 0;
+ au_nfiles_inc(dentry->d_sb);
au_rw_write_lock(&finfo->fi_rwsem);
finfo->fi_btop = -1;
finfo->fi_hdir = fidir;
diff --git a/ubuntu/aufs/hfsnotify.c b/ubuntu/aufs/hfsnotify.c
index 7636a88bf35..621b5380704 100644
--- a/ubuntu/aufs/hfsnotify.c
+++ b/ubuntu/aufs/hfsnotify.c
@@ -26,25 +26,32 @@
static const __u32 AuHfsnMask = (FS_MOVED_TO | FS_MOVED_FROM | FS_DELETE
| FS_CREATE | FS_EVENT_ON_CHILD);
static struct fsnotify_group *au_hfsn_group;
+static DECLARE_WAIT_QUEUE_HEAD(au_hfsn_wq);
static void au_hfsn_free_mark(struct fsnotify_mark *mark)
{
-#if 0
struct au_hnotify *hn = container_of(mark, struct au_hnotify,
hn_mark);
- au_cache_free_hnotify(hn);
-#endif
AuDbg("here\n");
+ hn->hn_mark_dead = 1;
+ smp_mb();
+ wake_up_all(&au_hfsn_wq);
}
static int au_hfsn_alloc(struct au_hnotify *hn, struct inode *h_inode)
{
struct fsnotify_mark *mark;
+ hn->hn_mark_dead = 0;
mark = &hn->hn_mark;
fsnotify_init_mark(mark, au_hfsn_free_mark);
mark->mask = AuHfsnMask;
- return fsnotify_add_mark(mark, au_hfsn_group, h_inode, NULL, 1);
+ /*
+ * by udba rename or rmdir, aufs assign a new inode to the known
+ * h_inode, so specify 1 to allow dups.
+ */
+ return fsnotify_add_mark(mark, au_hfsn_group, h_inode, /*mnt*/NULL,
+ /*allow_dups*/1);
}
static void au_hfsn_free(struct au_hnotify *hn)
@@ -54,6 +61,9 @@ static void au_hfsn_free(struct au_hnotify *hn)
mark = &hn->hn_mark;
fsnotify_destroy_mark(mark);
fsnotify_put_mark(mark);
+
+ /* TODO: bad approach */
+ wait_event(au_hfsn_wq, hn->hn_mark_dead);
}
/* ---------------------------------------------------------------------- */
@@ -152,28 +162,21 @@ static int au_hfsn_handle_event(struct fsnotify_group *group,
AuDebugOn(!inode_mark);
hnotify = container_of(inode_mark, struct au_hnotify, hn_mark);
err = au_hnotify(h_dir, hnotify, mask, &h_child_qstr, h_inode);
- fsnotify_put_mark(inode_mark);
out:
return err;
}
-/* copied from linux/fs/notify/inotify/inotify_fsnotify.c */
+/* copied from linux/fs/notify/inotify/inotify_fsnotiry.c */
/* it should be exported to modules */
-static bool au_hfsn_should_send_event(struct fsnotify_group *group, struct inode *inode,
+static bool au_hfsn_should_send_event(struct fsnotify_group *group,
+ struct inode *h_inode,
struct fsnotify_mark *inode_mark,
struct fsnotify_mark *vfsmount_mark,
__u32 mask, void *data, int data_type)
{
- bool send;
-
mask = (mask & ~FS_EVENT_ON_CHILD);
- send = (inode_mark->mask & mask);
-
- /* find took a reference */
- fsnotify_put_mark(inode_mark);
-
- return send;
+ return inode_mark->mask & mask;
}
static struct fsnotify_ops au_hfsn_ops = {
diff --git a/ubuntu/aufs/hinotify.c b/ubuntu/aufs/hinotify.c
deleted file mode 100644
index c2d900b3088..00000000000
--- a/ubuntu/aufs/hinotify.c
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * Copyright (C) 2005-2010 Junjiro R. Okajima
- *
- * This program, aufs is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-/*
- * inotify for the lower directories (deprecated)
- */
-
-#include "aufs.h"
-
-static const __u32 AuHinMask = (IN_MOVE | IN_DELETE | IN_CREATE);
-static struct inotify_handle *au_hin_handle;
-
-/* ---------------------------------------------------------------------- */
-
-static int au_hin_alloc(struct au_hnotify *hn, struct inode *h_inode)
-{
- int err;
- s32 wd;
- struct inotify_watch *watch;
-
- err = -EEXIST;
- wd = inotify_find_watch(au_hin_handle, h_inode, &watch);
- if (wd >= 0) {
- put_inotify_watch(watch);
- goto out;
- }
-
- err = 0;
- inotify_init_watch(&hn->hn_watch);
- wd = inotify_add_watch(au_hin_handle, &hn->hn_watch, h_inode,
- AuHinMask);
- if (unlikely(wd < 0)) {
- err = wd;
- put_inotify_watch(&hn->hn_watch);
- }
-
-out:
- return err;
-}
-
-static void au_hin_free(struct au_hnotify *hn)
-{
- int err;
-
- err = 0;
- if (atomic_read(&hn->hn_watch.count))
- err = inotify_rm_watch(au_hin_handle, &hn->hn_watch);
- if (unlikely(err))
- /* it means the watch is already removed */
- pr_warning("failed inotify_rm_watch() %d\n", err);
-}
-
-/* ---------------------------------------------------------------------- */
-
-static void au_hin_ctl(struct au_hinode *hinode, int do_set)
-{
- struct inode *h_inode;
- struct inotify_watch *watch;
-
- h_inode = hinode->hi_inode;
- IMustLock(h_inode);
-
- /* todo: try inotify_find_update_watch()? */
- watch = &hinode->hi_notify->hn_watch;
- mutex_lock(&h_inode->inotify_mutex);
- /* mutex_lock(&watch->ih->mutex); */
- if (do_set) {
- AuDebugOn(watch->mask & AuHinMask);
- watch->mask |= AuHinMask;
- } else {
- AuDebugOn(!(watch->mask & AuHinMask));
- watch->mask &= ~AuHinMask;
- }
- /* mutex_unlock(&watch->ih->mutex); */
- mutex_unlock(&h_inode->inotify_mutex);
-}
-
-/* ---------------------------------------------------------------------- */
-
-#ifdef AuDbgHnotify
-static char *in_name(u32 mask)
-{
-#ifdef CONFIG_AUFS_DEBUG
-#define test_ret(flag) if (mask & flag) \
- return #flag;
- test_ret(IN_ACCESS);
- test_ret(IN_MODIFY);
- test_ret(IN_ATTRIB);
- test_ret(IN_CLOSE_WRITE);
- test_ret(IN_CLOSE_NOWRITE);
- test_ret(IN_OPEN);
- test_ret(IN_MOVED_FROM);
- test_ret(IN_MOVED_TO);
- test_ret(IN_CREATE);
- test_ret(IN_DELETE);
- test_ret(IN_DELETE_SELF);
- test_ret(IN_MOVE_SELF);
- test_ret(IN_UNMOUNT);
- test_ret(IN_Q_OVERFLOW);
- test_ret(IN_IGNORED);
- return "";
-#undef test_ret
-#else
- return "??";
-#endif
-}
-#endif
-
-static u32 au_hin_conv_mask(u32 mask)
-{
- u32 conv;
-
- conv = 0;
-#define do_conv(flag) do { \
- conv |= (mask & IN_ ## flag) ? FS_ ## flag : 0; \
- } while (0)
- do_conv(ACCESS);
- do_conv(MODIFY);
- do_conv(ATTRIB);
- do_conv(CLOSE_WRITE);
- do_conv(CLOSE_NOWRITE);
- do_conv(OPEN);
- do_conv(MOVED_FROM);
- do_conv(MOVED_TO);
- do_conv(CREATE);
- do_conv(DELETE);
- do_conv(DELETE_SELF);
- do_conv(MOVE_SELF);
- do_conv(UNMOUNT);
- do_conv(Q_OVERFLOW);
-#undef do_conv
-#define do_conv(flag) do { \
- conv |= (mask & IN_ ## flag) ? FS_IN_ ## flag : 0; \
- } while (0)
- do_conv(IGNORED);
- /* do_conv(ISDIR); */
- /* do_conv(ONESHOT); */
-#undef do_conv
-
- return conv;
-}
-
-static void aufs_inotify(struct inotify_watch *watch, u32 wd __maybe_unused,
- u32 mask, u32 cookie __maybe_unused,
- const char *h_child_name, struct inode *h_child_inode)
-{
- struct au_hnotify *hnotify;
- struct qstr h_child_qstr = {
- .name = h_child_name
- };
-
- /* if IN_UNMOUNT happens, there must be another bug */
- AuDebugOn(mask & IN_UNMOUNT);
- if (mask & (IN_IGNORED | IN_UNMOUNT)) {
- put_inotify_watch(watch);
- return;
- }
-
-#ifdef AuDbgHnotify
- au_debug(1);
- if (1 || !h_child_name || strcmp(h_child_name, AUFS_XINO_FNAME)) {
- AuDbg("i%lu, wd %d, mask 0x%x %s, cookie 0x%x, hcname %s,"
- " hi%lu\n",
- watch->inode->i_ino, wd, mask, in_name(mask), cookie,
- h_child_name ? h_child_name : "",
- h_child_inode ? h_child_inode->i_ino : 0);
- WARN_ON(1);
- }
- au_debug(0);
-#endif
-
- if (h_child_name)
- h_child_qstr.len = strlen(h_child_name);
- hnotify = container_of(watch, struct au_hnotify, hn_watch);
- mask = au_hin_conv_mask(mask);
- au_hnotify(watch->inode, hnotify, mask, &h_child_qstr, h_child_inode);
-}
-
-static void aufs_inotify_destroy(struct inotify_watch *watch __maybe_unused)
-{
- return;
-}
-
-static struct inotify_operations aufs_inotify_ops = {
- .handle_event = aufs_inotify,
- .destroy_watch = aufs_inotify_destroy
-};
-
-/* ---------------------------------------------------------------------- */
-
-static int __init au_hin_init(void)
-{
- int err;
-
- err = 0;
- au_hin_handle = inotify_init(&aufs_inotify_ops);
- if (IS_ERR(au_hin_handle))
- err = PTR_ERR(au_hin_handle);
-
- AuTraceErr(err);
- return err;
-}
-
-static void au_hin_fin(void)
-{
- inotify_destroy(au_hin_handle);
-}
-
-const struct au_hnotify_op au_hnotify_op = {
- .ctl = au_hin_ctl,
- .alloc = au_hin_alloc,
- .free = au_hin_free,
-
- .fin = au_hin_fin,
- .init = au_hin_init
-};
diff --git a/ubuntu/aufs/hnotify.c b/ubuntu/aufs/hnotify.c
index 18d17075a35..535a5ceeec9 100644
--- a/ubuntu/aufs/hnotify.c
+++ b/ubuntu/aufs/hnotify.c
@@ -281,8 +281,10 @@ static int hn_gen_by_name(struct dentry *dentry, const unsigned int isdir)
#define AuHnJob_TRYXINO0 (1 << 4)
#define AuHnJob_MNTPNT (1 << 5)
#define au_ftest_hnjob(flags, name) ((flags) & AuHnJob_##name)
-#define au_fset_hnjob(flags, name) { (flags) |= AuHnJob_##name; }
-#define au_fclr_hnjob(flags, name) { (flags) &= ~AuHnJob_##name; }
+#define au_fset_hnjob(flags, name) \
+ do { (flags) |= AuHnJob_##name; } while (0)
+#define au_fclr_hnjob(flags, name) \
+ do { (flags) &= ~AuHnJob_##name; } while (0)
enum {
AuHn_CHILD,
@@ -451,7 +453,7 @@ static void au_hn_bh(void *_args)
AuDebugOn(!sb);
sbinfo = au_sbi(sb);
AuDebugOn(!sbinfo);
- si_write_lock(sb, !AuLock_FLUSH | AuLock_NOPLMW);
+ si_write_lock(sb, AuLock_NOPLMW);
ii_read_lock_parent(a->dir);
bfound = -1;
diff --git a/ubuntu/aufs/i_op.c b/ubuntu/aufs/i_op.c
index d8ad9af0abc..bbda6e4a2f2 100644
--- a/ubuntu/aufs/i_op.c
+++ b/ubuntu/aufs/i_op.c
@@ -62,10 +62,8 @@ static int h_permission(struct inode *h_inode, int mask,
if (!err)
err = devcgroup_inode_permission(h_inode, mask);
- if (!err) {
- mask &= (MAY_READ | MAY_WRITE | MAY_EXEC | MAY_APPEND);
+ if (!err)
err = security_inode_permission(h_inode, mask);
- }
#if 0
if (!err) {
@@ -159,14 +157,18 @@ static struct dentry *aufs_lookup(struct inode *dir, struct dentry *dentry,
IMustLock(dir);
sb = dir->i_sb;
- si_read_lock(sb, AuLock_FLUSH);
+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
+ ret = ERR_PTR(err);
+ if (unlikely(err))
+ goto out;
+
ret = ERR_PTR(-ENAMETOOLONG);
if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
- goto out;
+ goto out_si;
err = au_di_init(dentry);
ret = ERR_PTR(err);
if (unlikely(err))
- goto out;
+ goto out_si;
parent = dentry->d_parent; /* dir inode is locked */
di_read_lock_parent(parent, AuLock_IR);
@@ -186,13 +188,16 @@ static struct dentry *aufs_lookup(struct inode *dir, struct dentry *dentry,
goto out_unlock;
ret = d_splice_alias(inode, dentry);
- if (unlikely(IS_ERR(ret) && inode))
+ if (unlikely(IS_ERR(ret) && inode)) {
ii_write_unlock(inode);
+ iput(inode);
+ }
out_unlock:
di_write_unlock(dentry);
-out:
+out_si:
si_read_unlock(sb);
+out:
return ret;
}
@@ -475,8 +480,10 @@ static int au_reval_for_attr(struct dentry *dentry, unsigned int sigen)
#define AuIcpup_DID_CPUP 1
#define au_ftest_icpup(flags, name) ((flags) & AuIcpup_##name)
-#define au_fset_icpup(flags, name) { (flags) |= AuIcpup_##name; }
-#define au_fclr_icpup(flags, name) { (flags) &= ~AuIcpup_##name; }
+#define au_fset_icpup(flags, name) \
+ do { (flags) |= AuIcpup_##name; } while (0)
+#define au_fclr_icpup(flags, name) \
+ do { (flags) &= ~AuIcpup_##name; } while (0)
struct au_icpup_args {
unsigned char flags;
@@ -539,7 +546,7 @@ static int au_pin_and_icpup(struct dentry *dentry, struct iattr *ia,
h_file = NULL;
hi_wh = NULL;
- if (au_ftest_icpup(a->flags, DID_CPUP) && d_unhashed(dentry)) {
+ if (au_ftest_icpup(a->flags, DID_CPUP) && au_d_removed(dentry)) {
hi_wh = au_hi_wh(inode, a->btgt);
if (!hi_wh) {
err = au_sio_cpup_wh(dentry, a->btgt, sz, /*file*/NULL);
@@ -630,6 +637,7 @@ static int aufs_setattr(struct dentry *dentry, struct iattr *ia)
} else {
/* fchmod() doesn't pass ia_file */
a->udba = au_opt_udba(sb);
+ /* no au_d_removed(), to set UDBA_NONE for root */
if (d_unhashed(dentry))
a->udba = AuOpt_UDBA_NONE;
di_write_lock_child(dentry);
@@ -734,15 +742,16 @@ static int aufs_getattr(struct vfsmount *mnt __maybe_unused,
struct vfsmount *h_mnt;
struct dentry *h_dentry;
- err = 0;
sb = dentry->d_sb;
inode = dentry->d_inode;
- si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
+ if (unlikely(err))
+ goto out;
mnt_flags = au_mntflags(sb);
udba_none = !!au_opt_test(mnt_flags, UDBA_NONE);
/* support fstat(2) */
- if (!d_unhashed(dentry) && !udba_none) {
+ if (!au_d_removed(dentry) && !udba_none) {
unsigned int sigen = au_sigen(sb);
if (au_digen(dentry) == sigen && au_iigen(inode) == sigen)
di_read_lock_child(dentry, AuLock_IR);
@@ -752,7 +761,7 @@ static int aufs_getattr(struct vfsmount *mnt __maybe_unused,
err = au_reval_for_attr(dentry, sigen);
di_downgrade_lock(dentry, AuLock_IR);
if (unlikely(err))
- goto out;
+ goto out_unlock;
}
} else
di_read_lock_child(dentry, AuLock_IR);
@@ -784,13 +793,16 @@ static int aufs_getattr(struct vfsmount *mnt __maybe_unused,
au_refresh_iattr(inode, st, h_dentry->d_inode->i_nlink);
goto out_fill; /* success */
}
- goto out;
+ AuTraceErr(err);
+ goto out_unlock;
out_fill:
generic_fillattr(inode, st);
-out:
+out_unlock:
di_read_unlock(dentry, AuLock_IR);
si_read_unlock(sb);
+out:
+ AuTraceErr(err);
return err;
}
diff --git a/ubuntu/aufs/i_op_del.c b/ubuntu/aufs/i_op_del.c
index 1aa09d7d9a9..5b31bbd8876 100644
--- a/ubuntu/aufs/i_op_del.c
+++ b/ubuntu/aufs/i_op_del.c
@@ -280,17 +280,17 @@ static void epilog(struct inode *dir, struct dentry *dentry,
/*
* when an error happened, remove the created whiteout and revert everything.
*/
-static int do_revert(int err, struct inode *dir, aufs_bindex_t bwh,
- struct dentry *wh_dentry, struct dentry *dentry,
- struct au_dtime *dt)
+static int do_revert(int err, struct inode *dir, aufs_bindex_t bindex,
+ aufs_bindex_t bwh, struct dentry *wh_dentry,
+ struct dentry *dentry, struct au_dtime *dt)
{
int rerr;
struct path h_path = {
.dentry = wh_dentry,
- .mnt = au_sbr_mnt(dir->i_sb, bwh)
+ .mnt = au_sbr_mnt(dir->i_sb, bindex)
};
- rerr = au_wh_unlink_dentry(au_h_iptr(dir, bwh), &h_path, dentry);
+ rerr = au_wh_unlink_dentry(au_h_iptr(dir, bindex), &h_path, dentry);
if (!rerr) {
au_set_dbwh(dentry, bwh);
au_dtime_revert(dt);
@@ -346,7 +346,7 @@ int aufs_unlink(struct inode *dir, struct dentry *dentry)
}
if (!err) {
- drop_nlink(inode);
+ vfsub_drop_nlink(inode);
epilog(dir, dentry, bindex);
/* update target timestamps */
@@ -363,7 +363,7 @@ int aufs_unlink(struct inode *dir, struct dentry *dentry)
if (wh_dentry) {
int rerr;
- rerr = do_revert(err, dir, bwh, wh_dentry, dentry, &dt);
+ rerr = do_revert(err, dir, bindex, bwh, wh_dentry, dentry, &dt);
if (rerr)
err = rerr;
}
@@ -451,7 +451,7 @@ int aufs_rmdir(struct inode *dir, struct dentry *dentry)
if (wh_dentry) {
int rerr;
- rerr = do_revert(err, dir, bwh, wh_dentry, dentry, &dt);
+ rerr = do_revert(err, dir, bindex, bwh, wh_dentry, dentry, &dt);
if (rerr)
err = rerr;
}
diff --git a/ubuntu/aufs/i_op_ren.c b/ubuntu/aufs/i_op_ren.c
index bbd9ebafcf5..89efe679fea 100644
--- a/ubuntu/aufs/i_op_ren.c
+++ b/ubuntu/aufs/i_op_ren.c
@@ -35,8 +35,10 @@ enum { AuPARENT, AuCHILD, AuParentChild };
#define AuRen_DIROPQ (1 << 6)
#define AuRen_CPUP (1 << 7)
#define au_ftest_ren(flags, name) ((flags) & AuRen_##name)
-#define au_fset_ren(flags, name) { (flags) |= AuRen_##name; }
-#define au_fclr_ren(flags, name) { (flags) &= ~AuRen_##name; }
+#define au_fset_ren(flags, name) \
+ do { (flags) |= AuRen_##name; } while (0)
+#define au_fclr_ren(flags, name) \
+ do { (flags) &= ~AuRen_##name; } while (0)
struct au_ren_args {
struct {
diff --git a/ubuntu/aufs/iinfo.c b/ubuntu/aufs/iinfo.c
index 1678ba4fdbd..6bccfdf18e4 100644
--- a/ubuntu/aufs/iinfo.c
+++ b/ubuntu/aufs/iinfo.c
@@ -180,6 +180,7 @@ int au_iinfo_init(struct inode *inode)
nbr = 1;
iinfo->ii_hinode = kcalloc(nbr, sizeof(*iinfo->ii_hinode), GFP_NOFS);
if (iinfo->ii_hinode) {
+ au_ninodes_inc(sb);
for (i = 0; i < nbr; i++)
iinfo->ii_hinode[i].hi_id = -1;
@@ -227,6 +228,7 @@ void au_iinfo_fin(struct inode *inode)
return;
sb = inode->i_sb;
+ au_ninodes_dec(sb);
if (si_pid_test(sb))
au_xino_delete_inode(inode, unlinked);
else {
diff --git a/ubuntu/aufs/include/linux/Kbuild b/ubuntu/aufs/include/linux/Kbuild
new file mode 100644
index 00000000000..e1b2bd375ea
--- /dev/null
+++ b/ubuntu/aufs/include/linux/Kbuild
@@ -0,0 +1 @@
+header-y = aufs_type.h
diff --git a/ubuntu/aufs/include/linux/aufs_type.h b/ubuntu/aufs/include/linux/aufs_type.h
index b338e44cd40..c9e2845a13c 100644
--- a/ubuntu/aufs/include/linux/aufs_type.h
+++ b/ubuntu/aufs/include/linux/aufs_type.h
@@ -20,14 +20,11 @@
#define __AUFS_TYPE_H__
#include <linux/ioctl.h>
-/* for those who didn't "make headers_install" */
-#ifdef __KERNEL__
#include <linux/kernel.h>
-#endif
#include <linux/limits.h>
#include <linux/types.h>
-#define AUFS_VERSION "2.1-standalone.tree-36-UNRELEASED-20101103"
+#define AUFS_VERSION "2.1-standalone.tree-37-rcN-20101122"
/* todo? move this to linux-2.6.19/include/magic.h */
#define AUFS_SUPER_MAGIC ('a' << 24 | 'u' << 16 | 'f' << 8 | 's')
diff --git a/ubuntu/aufs/inode.c b/ubuntu/aufs/inode.c
index 98c4b37bd1b..fe4ee9bd626 100644
--- a/ubuntu/aufs/inode.c
+++ b/ubuntu/aufs/inode.c
@@ -26,7 +26,7 @@ struct inode *au_igrab(struct inode *inode)
{
if (inode) {
AuDebugOn(!atomic_read(&inode->i_count));
- atomic_inc(&inode->i_count);
+ ihold(inode);
}
return inode;
}
diff --git a/ubuntu/aufs/inode.h b/ubuntu/aufs/inode.h
index 8985120e017..ecb91be37d2 100644
--- a/ubuntu/aufs/inode.h
+++ b/ubuntu/aufs/inode.h
@@ -35,11 +35,11 @@ struct vfsmount;
struct au_hnotify {
#ifdef CONFIG_AUFS_HNOTIFY
#ifdef CONFIG_AUFS_HFSNOTIFY
+ /* never use fsnotify_add_vfsmount_mark() */
struct fsnotify_mark hn_mark;
-#else
- struct inotify_watch hn_watch;
+ int hn_mark_dead;
#endif
- struct inode *hn_aufs_inode; /* no get/put */
+ struct inode *hn_aufs_inode; /* no get/put */
#endif
} ____cacheline_aligned_in_smp;
@@ -75,8 +75,10 @@ struct au_icntnr {
#define AuPin_DI_LOCKED 1
#define AuPin_MNT_WRITE (1 << 1)
#define au_ftest_pin(flags, name) ((flags) & AuPin_##name)
-#define au_fset_pin(flags, name) { (flags) |= AuPin_##name; }
-#define au_fclr_pin(flags, name) { (flags) &= ~AuPin_##name; }
+#define au_fset_pin(flags, name) \
+ do { (flags) |= AuPin_##name; } while (0)
+#define au_fclr_pin(flags, name) \
+ do { (flags) &= ~AuPin_##name; } while (0)
struct au_pin {
/* input */
@@ -134,8 +136,10 @@ extern struct inode_operations aufs_iop, aufs_symlink_iop, aufs_dir_iop;
#define AuWrDir_ADD_ENTRY 1
#define AuWrDir_ISDIR (1 << 1)
#define au_ftest_wrdir(flags, name) ((flags) & AuWrDir_##name)
-#define au_fset_wrdir(flags, name) { (flags) |= AuWrDir_##name; }
-#define au_fclr_wrdir(flags, name) { (flags) &= ~AuWrDir_##name; }
+#define au_fset_wrdir(flags, name) \
+ do { (flags) |= AuWrDir_##name; } while (0)
+#define au_fclr_wrdir(flags, name) \
+ do { (flags) &= ~AuWrDir_##name; } while (0)
struct au_wr_dir_args {
aufs_bindex_t force_btgt;
@@ -187,8 +191,10 @@ unsigned int au_hi_flags(struct inode *inode, int isdir);
#define AuHi_XINO 1
#define AuHi_HNOTIFY (1 << 1)
#define au_ftest_hi(flags, name) ((flags) & AuHi_##name)
-#define au_fset_hi(flags, name) { (flags) |= AuHi_##name; }
-#define au_fclr_hi(flags, name) { (flags) &= ~AuHi_##name; }
+#define au_fset_hi(flags, name) \
+ do { (flags) |= AuHi_##name; } while (0)
+#define au_fclr_hi(flags, name) \
+ do { (flags) &= ~AuHi_##name; } while (0)
#ifndef CONFIG_AUFS_HNOTIFY
#undef AuHi_HNOTIFY
@@ -413,12 +419,10 @@ static inline void au_pin_set_parent_lflag(struct au_pin *pin,
unsigned char lflag)
{
if (pin) {
- /* dirty macros require brackets */
- if (lflag) {
+ if (lflag)
au_fset_pin(pin->flags, DI_LOCKED);
- } else {
+ else
au_fclr_pin(pin->flags, DI_LOCKED);
- }
}
}
@@ -453,7 +457,7 @@ int au_hnotify(struct inode *h_dir, struct au_hnotify *hnotify, u32 mask,
int __init au_hnotify_init(void);
void au_hnotify_fin(void);
-/* hinotify.c */
+/* hfsnotify.c */
extern const struct au_hnotify_op au_hnotify_op;
static inline
diff --git a/ubuntu/aufs/opts.c b/ubuntu/aufs/opts.c
index d0aef5ca272..bdb2712f628 100644
--- a/ubuntu/aufs/opts.c
+++ b/ubuntu/aufs/opts.c
@@ -217,30 +217,16 @@ static match_table_t udbalevel = {
{AuOpt_UDBA_HNOTIFY, "notify"}, /* abstraction */
#ifdef CONFIG_AUFS_HFSNOTIFY
{AuOpt_UDBA_HNOTIFY, "fsnotify"},
-#else
- {AuOpt_UDBA_HNOTIFY, "inotify"},
#endif
#endif
{-1, NULL}
};
-static void au_warn_inotify(int val, char *str)
-{
-#ifdef CONFIG_AUFS_HINOTIFY
- if (val == AuOpt_UDBA_HNOTIFY
- && !strcmp(str, "inotify"))
- AuWarn1("udba=inotify is deprecated, use udba=notify\n");
-#endif
-}
-
static int noinline_for_stack udba_val(char *str)
{
- int val;
substring_t args[MAX_OPT_ARGS];
- val = match_token(str, udbalevel, args);
- au_warn_inotify(val, str);
- return val;
+ return match_token(str, udbalevel, args);
}
const char *au_optstr_udba(int udba)
diff --git a/ubuntu/aufs/opts.h b/ubuntu/aufs/opts.h
index dc727ae4046..03ce3351c49 100644
--- a/ubuntu/aufs/opts.h
+++ b/ubuntu/aufs/opts.h
@@ -78,7 +78,9 @@ struct super_block;
(flags) &= ~AuOptMask_UDBA; \
((flags) |= AuOpt_##name); \
} while (0)
-#define au_opt_clr(flags, name) { ((flags) &= ~AuOpt_##name); }
+#define au_opt_clr(flags, name) do { \
+ ((flags) &= ~AuOpt_##name); \
+} while (0)
static inline unsigned int au_opts_plink(unsigned int mntflags)
{
@@ -173,8 +175,10 @@ struct au_opt {
#define AuOpts_TRUNC_XIB (1 << 3)
#define AuOpts_REFRESH_DYAOP (1 << 4)
#define au_ftest_opts(flags, name) ((flags) & AuOpts_##name)
-#define au_fset_opts(flags, name) { (flags) |= AuOpts_##name; }
-#define au_fclr_opts(flags, name) { (flags) &= ~AuOpts_##name; }
+#define au_fset_opts(flags, name) \
+ do { (flags) |= AuOpts_##name; } while (0)
+#define au_fclr_opts(flags, name) \
+ do { (flags) &= ~AuOpts_##name; } while (0)
struct au_opts {
struct au_opt *opt;
diff --git a/ubuntu/aufs/plink.c b/ubuntu/aufs/plink.c
index 5aad81d4467..dd7eb1e49f9 100644
--- a/ubuntu/aufs/plink.c
+++ b/ubuntu/aufs/plink.c
@@ -200,12 +200,40 @@ static int plink_name(char *name, int len, struct inode *inode,
return rlen;
}
+struct au_do_plink_lkup_args {
+ struct dentry **errp;
+ struct qstr *tgtname;
+ struct dentry *h_parent;
+ struct au_branch *br;
+};
+
+static struct dentry *au_do_plink_lkup(struct qstr *tgtname,
+ struct dentry *h_parent,
+ struct au_branch *br)
+{
+ struct dentry *h_dentry;
+ struct mutex *h_mtx;
+
+ h_mtx = &h_parent->d_inode->i_mutex;
+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD2);
+ h_dentry = au_lkup_one(tgtname, h_parent, br, /*nd*/NULL);
+ mutex_unlock(h_mtx);
+ return h_dentry;
+}
+
+static void au_call_do_plink_lkup(void *args)
+{
+ struct au_do_plink_lkup_args *a = args;
+ *a->errp = au_do_plink_lkup(a->tgtname, a->h_parent, a->br);
+}
+
/* lookup the plink-ed @inode under the branch at @bindex */
struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex)
{
struct dentry *h_dentry, *h_parent;
struct au_branch *br;
struct inode *h_dir;
+ int wkq_err;
char a[PLINK_NAME_LEN];
struct qstr tgtname = {
.name = a
@@ -218,10 +246,20 @@ struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex)
h_dir = h_parent->d_inode;
tgtname.len = plink_name(a, sizeof(a), inode, bindex);
- /* always superio. */
- mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_CHILD2);
- h_dentry = au_sio_lkup_one(&tgtname, h_parent, br);
- mutex_unlock(&h_dir->i_mutex);
+ if (current_fsuid()) {
+ struct au_do_plink_lkup_args args = {
+ .errp = &h_dentry,
+ .tgtname = &tgtname,
+ .h_parent = h_parent,
+ .br = br
+ };
+
+ wkq_err = au_wkq_wait(au_call_do_plink_lkup, &args);
+ if (unlikely(wkq_err))
+ h_dentry = ERR_PTR(wkq_err);
+ } else
+ h_dentry = au_do_plink_lkup(&tgtname, h_parent, br);
+
return h_dentry;
}
@@ -236,6 +274,7 @@ static int do_whplink(struct qstr *tgt, struct dentry *h_parent,
struct inode *h_dir;
h_dir = h_parent->d_inode;
+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_CHILD2);
again:
h_path.dentry = au_lkup_one(tgt, h_parent, br, /*nd*/NULL);
err = PTR_ERR(h_path.dentry);
@@ -244,6 +283,7 @@ again:
err = 0;
/* wh.plink dir is not monitored */
+ /* todo: is it really safe? */
if (h_path.dentry->d_inode
&& h_path.dentry->d_inode != h_dentry->d_inode) {
err = vfsub_unlink(h_dir, &h_path, /*force*/0);
@@ -257,6 +297,7 @@ again:
dput(h_path.dentry);
out:
+ mutex_unlock(&h_dir->i_mutex);
return err;
}
@@ -292,7 +333,6 @@ static int whplink(struct dentry *h_dentry, struct inode *inode,
tgtname.len = plink_name(a, sizeof(a), inode, bindex);
/* always superio. */
- mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_CHILD2);
if (current_fsuid()) {
struct do_whplink_args args = {
.errp = &err,
@@ -306,7 +346,6 @@ static int whplink(struct dentry *h_dentry, struct inode *inode,
err = wkq_err;
} else
err = do_whplink(&tgtname, h_parent, h_dentry, br);
- mutex_unlock(&h_dir->i_mutex);
return err;
}
diff --git a/ubuntu/aufs/rdu.c b/ubuntu/aufs/rdu.c
index 60ee58e3a5d..fedbc384a1a 100644
--- a/ubuntu/aufs/rdu.c
+++ b/ubuntu/aufs/rdu.c
@@ -32,8 +32,10 @@
#define AuRdu_CONT (1 << 1)
#define AuRdu_FULL (1 << 2)
#define au_ftest_rdu(flags, name) ((flags) & AuRdu_##name)
-#define au_fset_rdu(flags, name) { (flags) |= AuRdu_##name; }
-#define au_fclr_rdu(flags, name) { (flags) &= ~AuRdu_##name; }
+#define au_fset_rdu(flags, name) \
+ do { (flags) |= AuRdu_##name; } while (0)
+#define au_fclr_rdu(flags, name) \
+ do { (flags) &= ~AuRdu_##name; } while (0)
struct au_rdu_arg {
struct aufs_rdu *rdu;
diff --git a/ubuntu/aufs/sbinfo.c b/ubuntu/aufs/sbinfo.c
index 9b46ad26fee..1eefcb816b3 100644
--- a/ubuntu/aufs/sbinfo.c
+++ b/ubuntu/aufs/sbinfo.c
@@ -86,6 +86,10 @@ int au_si_alloc(struct super_block *sb)
spin_lock_init(&sbinfo->au_si_pid.tree_lock);
INIT_RADIX_TREE(&sbinfo->au_si_pid.tree, GFP_ATOMIC | __GFP_NOFAIL);
+ atomic_long_set(&sbinfo->si_ninodes, 0);
+
+ atomic_long_set(&sbinfo->si_nfiles, 0);
+
sbinfo->si_bend = -1;
sbinfo->si_wbr_copyup = AuWbrCopyup_Def;
@@ -171,6 +175,7 @@ aufs_bindex_t au_new_br_id(struct super_block *sb)
sbinfo = au_sbi(sb);
for (i = 0; i <= AUFS_BRANCH_MAX; i++) {
br_id = ++sbinfo->si_last_br_id;
+ AuDebugOn(br_id < 0);
if (br_id && au_br_index(sb, br_id) < 0)
return br_id;
}
diff --git a/ubuntu/aufs/super.c b/ubuntu/aufs/super.c
index ed6b8ed7923..7aba5f24309 100644
--- a/ubuntu/aufs/super.c
+++ b/ubuntu/aufs/super.c
@@ -25,6 +25,8 @@
#include <linux/module.h>
#include <linux/seq_file.h>
#include <linux/statfs.h>
+#include <linux/vmalloc.h>
+#include <linux/writeback.h>
#include "aufs.h"
/*
@@ -298,7 +300,7 @@ static int au_statfs_sum(struct super_block *sb, struct kstatfs *buf)
u64 blocks, bfree, bavail, files, ffree;
aufs_bindex_t bend, bindex, i;
unsigned char shared;
- struct vfsmount *h_mnt;
+ struct path h_path;
struct super_block *h_sb;
blocks = 0;
@@ -310,8 +312,8 @@ static int au_statfs_sum(struct super_block *sb, struct kstatfs *buf)
err = 0;
bend = au_sbend(sb);
for (bindex = bend; bindex >= 0; bindex--) {
- h_mnt = au_sbr_mnt(sb, bindex);
- h_sb = h_mnt->mnt_sb;
+ h_path.mnt = au_sbr_mnt(sb, bindex);
+ h_sb = h_path.mnt->mnt_sb;
shared = 0;
for (i = bindex + 1; !shared && i <= bend; i++)
shared = (au_sbr_sb(sb, i) == h_sb);
@@ -319,7 +321,8 @@ static int au_statfs_sum(struct super_block *sb, struct kstatfs *buf)
continue;
/* sb->s_root for NFS is unreliable */
- err = statfs_by_dentry(h_mnt->mnt_root, buf);
+ h_path.dentry = h_path.mnt->mnt_root;
+ err = vfs_statfs(&h_path, buf);
if (unlikely(err))
goto out;
@@ -343,15 +346,18 @@ out:
static int aufs_statfs(struct dentry *dentry, struct kstatfs *buf)
{
int err;
+ struct path h_path;
struct super_block *sb;
/* lock free root dinfo */
sb = dentry->d_sb;
si_noflush_read_lock(sb);
- if (!au_opt_test(au_mntflags(sb), SUM))
+ if (!au_opt_test(au_mntflags(sb), SUM)) {
/* sb->s_root for NFS is unreliable */
- err = statfs_by_dentry(au_sbr_mnt(sb, 0)->mnt_root, buf);
- else
+ h_path.mnt = au_sbr_mnt(sb, 0);
+ h_path.dentry = h_path.mnt->mnt_root;
+ err = vfs_statfs(&h_path, buf);
+ } else
err = au_statfs_sum(sb, buf);
si_read_unlock(sb);
@@ -382,6 +388,91 @@ static void aufs_put_super(struct super_block *sb)
/* ---------------------------------------------------------------------- */
+void au_array_free(void *array)
+{
+ if (array) {
+ if (!is_vmalloc_addr(array))
+ kfree(array);
+ else
+ vfree(array);
+ }
+}
+
+void *au_array_alloc(unsigned long long *hint, au_arraycb_t cb, void *arg)
+{
+ void *array;
+ unsigned long long n;
+
+ array = NULL;
+ n = 0;
+ if (!*hint)
+ goto out;
+
+ if (*hint > ULLONG_MAX / sizeof(array)) {
+ array = ERR_PTR(-EMFILE);
+ pr_err("hint %llu\n", *hint);
+ goto out;
+ }
+
+ array = kmalloc(sizeof(array) * *hint, GFP_NOFS);
+ if (unlikely(!array))
+ array = vmalloc(sizeof(array) * *hint);
+ if (unlikely(!array)) {
+ array = ERR_PTR(-ENOMEM);
+ goto out;
+ }
+
+ n = cb(array, *hint, arg);
+ AuDebugOn(n > *hint);
+
+out:
+ *hint = n;
+ return array;
+}
+
+static unsigned long long au_iarray_cb(void *a,
+ unsigned long long max __maybe_unused,
+ void *arg)
+{
+ unsigned long long n;
+ struct inode **p, *inode;
+ struct list_head *head;
+
+ n = 0;
+ p = a;
+ head = arg;
+ spin_lock(&inode_lock);
+ list_for_each_entry(inode, head, i_sb_list) {
+ if (!is_bad_inode(inode)
+ && au_ii(inode)->ii_bstart >= 0) {
+ au_igrab(inode);
+ *p++ = inode;
+ n++;
+ AuDebugOn(n > max);
+ }
+ }
+ spin_unlock(&inode_lock);
+
+ return n;
+}
+
+struct inode **au_iarray_alloc(struct super_block *sb, unsigned long long *max)
+{
+ *max = atomic_long_read(&au_sbi(sb)->si_ninodes);
+ return au_array_alloc(max, au_iarray_cb, &sb->s_inodes);
+}
+
+void au_iarray_free(struct inode **a, unsigned long long max)
+{
+ unsigned long long ull;
+
+ for (ull = 0; ull < max; ull++)
+ iput(a[ull]);
+ au_array_free(a);
+}
+
+/* ---------------------------------------------------------------------- */
+
/*
* refresh dentry and inode at remount time.
*/
@@ -806,24 +897,27 @@ out:
/* ---------------------------------------------------------------------- */
-static int aufs_get_sb(struct file_system_type *fs_type, int flags,
- const char *dev_name __maybe_unused, void *raw_data,
- struct vfsmount *mnt)
+static struct dentry *aufs_mount(struct file_system_type *fs_type, int flags,
+ const char *dev_name __maybe_unused,
+ void *raw_data)
{
- int err;
+ struct dentry *root;
struct super_block *sb;
/* all timestamps always follow the ones on the branch */
/* mnt->mnt_flags |= MNT_NOATIME | MNT_NODIRATIME; */
- err = get_sb_nodev(fs_type, flags, raw_data, aufs_fill_super, mnt);
- if (!err) {
- sb = mnt->mnt_sb;
- si_write_lock(sb, !AuLock_FLUSH);
- sysaufs_brs_add(sb, 0);
- si_write_unlock(sb);
- au_sbilist_add(sb);
- }
- return err;
+ root = mount_nodev(fs_type, flags, raw_data, aufs_fill_super);
+ if (IS_ERR(root))
+ goto out;
+
+ sb = root->d_sb;
+ si_write_lock(sb, !AuLock_FLUSH);
+ sysaufs_brs_add(sb, 0);
+ si_write_unlock(sb);
+ au_sbilist_add(sb);
+
+out:
+ return root;
}
static void aufs_kill_sb(struct super_block *sb)
@@ -856,7 +950,7 @@ struct file_system_type aufs_fs_type = {
.fs_flags =
FS_RENAME_DOES_D_MOVE /* a race between rename and others */
| FS_REVAL_DOT, /* for NFS branch and udba */
- .get_sb = aufs_get_sb,
+ .mount = aufs_mount,
.kill_sb = aufs_kill_sb,
/* no need to __module_get() and module_put(). */
.owner = THIS_MODULE,
diff --git a/ubuntu/aufs/super.h b/ubuntu/aufs/super.h
index 2c8d20adcda..0cc087beadb 100644
--- a/ubuntu/aufs/super.h
+++ b/ubuntu/aufs/super.h
@@ -74,6 +74,11 @@ struct au_sbinfo {
struct radix_tree_root tree;
} au_si_pid;
+ /*
+ * dirty approach to protect sb->sb_inodes and ->s_files from remount.
+ */
+ atomic_long_t si_ninodes, si_nfiles;
+
/* branch management */
unsigned int si_generation;
@@ -81,7 +86,10 @@ struct au_sbinfo {
unsigned char au_si_status;
aufs_bindex_t si_bend;
- aufs_bindex_t si_last_br_id;
+
+ /* dirty trick to keep br_id plus */
+ unsigned int si_last_br_id :
+ sizeof(aufs_bindex_t) * BITS_PER_BYTE - 1;
struct au_branch **si_branch;
/* policy to select a writable branch */
@@ -205,14 +213,22 @@ static inline unsigned char au_do_ftest_si(struct au_sbinfo *sbi,
#define AuLock_NOPLM (1 << 5) /* return err in plm mode */
#define AuLock_NOPLMW (1 << 6) /* wait for plm mode ends */
#define au_ftest_lock(flags, name) ((flags) & AuLock_##name)
-#define au_fset_lock(flags, name) { (flags) |= AuLock_##name; }
-#define au_fclr_lock(flags, name) { (flags) &= ~AuLock_##name; }
+#define au_fset_lock(flags, name) \
+ do { (flags) |= AuLock_##name; } while (0)
+#define au_fclr_lock(flags, name) \
+ do { (flags) &= ~AuLock_##name; } while (0)
/* ---------------------------------------------------------------------- */
/* super.c */
extern struct file_system_type aufs_fs_type;
struct inode *au_iget_locked(struct super_block *sb, ino_t ino);
+typedef unsigned long long (*au_arraycb_t)(void *array, unsigned long long max,
+ void *arg);
+void au_array_free(void *array);
+void *au_array_alloc(unsigned long long *hint, au_arraycb_t cb, void *arg);
+struct inode **au_iarray_alloc(struct super_block *sb, unsigned long long *max);
+void au_iarray_free(struct inode **a, unsigned long long max);
/* sbinfo.c */
void au_si_free(struct kobject *kobj);
@@ -465,6 +481,28 @@ static inline unsigned int au_sigen(struct super_block *sb)
return au_sbi(sb)->si_generation;
}
+static inline void au_ninodes_inc(struct super_block *sb)
+{
+ atomic_long_inc(&au_sbi(sb)->si_ninodes);
+}
+
+static inline void au_ninodes_dec(struct super_block *sb)
+{
+ AuDebugOn(!atomic_long_read(&au_sbi(sb)->si_ninodes));
+ atomic_long_dec(&au_sbi(sb)->si_ninodes);
+}
+
+static inline void au_nfiles_inc(struct super_block *sb)
+{
+ atomic_long_inc(&au_sbi(sb)->si_nfiles);
+}
+
+static inline void au_nfiles_dec(struct super_block *sb)
+{
+ AuDebugOn(!atomic_long_read(&au_sbi(sb)->si_nfiles));
+ atomic_long_dec(&au_sbi(sb)->si_nfiles);
+}
+
static inline struct au_branch *au_sbr(struct super_block *sb,
aufs_bindex_t bindex)
{
diff --git a/ubuntu/aufs/vdir.c b/ubuntu/aufs/vdir.c
index 07941062ace..5777ca463e3 100644
--- a/ubuntu/aufs/vdir.c
+++ b/ubuntu/aufs/vdir.c
@@ -434,8 +434,10 @@ static int reinit_vdir(struct au_vdir *vdir)
#define AuFillVdir_WHABLE (1 << 1)
#define AuFillVdir_SHWH (1 << 2)
#define au_ftest_fillvdir(flags, name) ((flags) & AuFillVdir_##name)
-#define au_fset_fillvdir(flags, name) { (flags) |= AuFillVdir_##name; }
-#define au_fclr_fillvdir(flags, name) { (flags) &= ~AuFillVdir_##name; }
+#define au_fset_fillvdir(flags, name) \
+ do { (flags) |= AuFillVdir_##name; } while (0)
+#define au_fclr_fillvdir(flags, name) \
+ do { (flags) &= ~AuFillVdir_##name; } while (0)
#ifndef CONFIG_AUFS_SHWH
#undef AuFillVdir_SHWH
diff --git a/ubuntu/aufs/vfsub.c b/ubuntu/aufs/vfsub.c
index cd3fe788092..846a124a2e1 100644
--- a/ubuntu/aufs/vfsub.c
+++ b/ubuntu/aufs/vfsub.c
@@ -84,8 +84,8 @@ struct file *vfsub_dentry_open(struct path *path, int flags)
path_get(path);
file = dentry_open(path->dentry, path->mnt,
- flags | vfsub_fmode_to_uint(FMODE_NONOTIFY),
- current_cred());
+ flags /* | vfsub_fmode_to_uint(FMODE_NONOTIFY) */,
+ current_cred());
if (IS_ERR(file))
goto out;
@@ -102,8 +102,9 @@ struct file *vfsub_filp_open(const char *path, int oflags, int mode)
{
struct file *file;
- file = filp_open(path, oflags | vfsub_fmode_to_uint(FMODE_NONOTIFY),
- mode);
+ file = filp_open(path,
+ oflags /* | vfsub_fmode_to_uint(FMODE_NONOTIFY) */,
+ mode);
if (IS_ERR(file))
goto out;
vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
@@ -743,7 +744,7 @@ static void call_unlink(void *args)
dget(d);
h_inode = d->d_inode;
if (h_inode)
- atomic_inc(&h_inode->i_count);
+ ihold(h_inode);
*a->errp = vfs_unlink(a->dir, d);
if (!*a->errp) {
diff --git a/ubuntu/aufs/vfsub.h b/ubuntu/aufs/vfsub.h
index e97c1e5730f..4b44827c428 100644
--- a/ubuntu/aufs/vfsub.h
+++ b/ubuntu/aufs/vfsub.h
@@ -27,13 +27,14 @@
#include <linux/fs.h>
#include <linux/lglock.h>
+#include "debug.h"
-/* ---------------------------------------------------------------------- */
+/* copied from linux/fs/internal.h */
DECLARE_BRLOCK(vfsmount_lock);
-DECLARE_LGLOCK(files_lglock);
extern void file_sb_list_del(struct file *f);
-/* copied from fs/file_table.c */
+/* copied from linux/fs/file_table.c */
+DECLARE_LGLOCK(files_lglock);
#ifdef CONFIG_SMP
/*
* These macros iterate all files on all CPUs for a given superblock.
@@ -61,7 +62,9 @@ extern void file_sb_list_del(struct file *f);
#define while_file_list_for_each_entry \
}
-#endif /* CONFIG_SMP */
+#endif
+
+/* ---------------------------------------------------------------------- */
/* lock subclass for lower inode */
/* default MAX_LOCKDEP_SUBCLASSES(8) is not enough */
@@ -82,6 +85,14 @@ enum {
/* ---------------------------------------------------------------------- */
+static inline void vfsub_drop_nlink(struct inode *inode)
+{
+ AuDebugOn(!inode->i_nlink);
+ drop_nlink(inode);
+}
+
+/* ---------------------------------------------------------------------- */
+
int vfsub_update_h_iattr(struct path *h_path, int *did);
struct file *vfsub_dentry_open(struct path *path, int flags);
struct file *vfsub_filp_open(const char *path, int oflags, int mode);
diff --git a/ubuntu/aufs/wbr_policy.c b/ubuntu/aufs/wbr_policy.c
index f20cf97a429..bb57ae520fc 100644
--- a/ubuntu/aufs/wbr_policy.c
+++ b/ubuntu/aufs/wbr_policy.c
@@ -55,8 +55,10 @@ int au_cpdown_attr(struct path *h_path, struct dentry *h_src)
#define AuCpdown_MADE_DIR (1 << 2)
#define AuCpdown_DIROPQ (1 << 3)
#define au_ftest_cpdown(flags, name) ((flags) & AuCpdown_##name)
-#define au_fset_cpdown(flags, name) { (flags) |= AuCpdown_##name; }
-#define au_fclr_cpdown(flags, name) { (flags) &= ~AuCpdown_##name; }
+#define au_fset_cpdown(flags, name) \
+ do { (flags) |= AuCpdown_##name; } while (0)
+#define au_fclr_cpdown(flags, name) \
+ do { (flags) &= ~AuCpdown_##name; } while (0)
struct au_cpdown_dir_args {
struct dentry *parent;
@@ -407,6 +409,7 @@ static void au_mfs(struct dentry *dentry)
aufs_bindex_t bindex, bend;
int err;
unsigned long long b, bavail;
+ struct path h_path;
/* reduce the stack usage */
struct kstatfs *st;
@@ -429,7 +432,9 @@ static void au_mfs(struct dentry *dentry)
continue;
/* sb->s_root for NFS is unreliable */
- err = statfs_by_dentry(br->br_mnt->mnt_root, st);
+ h_path.mnt = br->br_mnt;
+ h_path.dentry = h_path.mnt->mnt_root;
+ err = vfs_statfs(&h_path, st);
if (unlikely(err)) {
AuWarn1("failed statfs, b%d, %d\n", bindex, err);
continue;
diff --git a/ubuntu/aufs/whout.c b/ubuntu/aufs/whout.c
index 31cdec9cd1c..284b8cc7c35 100644
--- a/ubuntu/aufs/whout.c
+++ b/ubuntu/aufs/whout.c
@@ -974,8 +974,9 @@ int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
if (!err) {
if (au_ibstart(dir) == bindex) {
+ /* todo: dir->i_mutex is necessary */
au_cpup_attr_timesizes(dir);
- drop_nlink(dir);
+ vfsub_drop_nlink(dir);
}
return 0; /* success */
}
diff --git a/ubuntu/aufs/whout.h b/ubuntu/aufs/whout.h
index df72838cf7a..b262ffd6e0c 100644
--- a/ubuntu/aufs/whout.h
+++ b/ubuntu/aufs/whout.h
@@ -45,8 +45,10 @@ int au_wh_init(struct dentry *h_parent, struct au_branch *br,
/* diropq flags */
#define AuDiropq_CREATE 1
#define au_ftest_diropq(flags, name) ((flags) & AuDiropq_##name)
-#define au_fset_diropq(flags, name) { (flags) |= AuDiropq_##name; }
-#define au_fclr_diropq(flags, name) { (flags) &= ~AuDiropq_##name; }
+#define au_fset_diropq(flags, name) \
+ do { (flags) |= AuDiropq_##name; } while (0)
+#define au_fclr_diropq(flags, name) \
+ do { (flags) &= ~AuDiropq_##name; } while (0)
struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
unsigned int flags);
diff --git a/ubuntu/aufs/wkq.c b/ubuntu/aufs/wkq.c
index b1ca42ecdc1..9739d3a1377 100644
--- a/ubuntu/aufs/wkq.c
+++ b/ubuntu/aufs/wkq.c
@@ -44,7 +44,7 @@ static struct {
struct au_wkinfo {
struct work_struct wk;
- struct super_block *sb;
+ struct kobject *kobj;
unsigned int flags; /* see wkq.h */
@@ -60,11 +60,14 @@ static void wkq_func(struct work_struct *wk)
{
struct au_wkinfo *wkinfo = container_of(wk, struct au_wkinfo, wk);
+ AuDebugOn(current_fsuid());
+ AuDebugOn(rlimit(RLIMIT_FSIZE) != RLIM_INFINITY);
+
wkinfo->func(wkinfo->args);
if (au_ftest_wkq(wkinfo->flags, WAIT))
complete(wkinfo->comp);
else {
- kobject_put(&au_sbi(wkinfo->sb)->si_kobj);
+ kobject_put(wkinfo->kobj);
module_put(THIS_MODULE);
kfree(wkinfo);
}
@@ -128,6 +131,12 @@ static void au_wkq_run(struct au_wkinfo *wkinfo, unsigned int flags)
}
}
+/*
+ * Be careful. It is easy to make deadlock happen.
+ * processA: lock, wkq and wait
+ * processB: wkq and wait, lock in wkq
+ * --> deadlock
+ */
int au_wkq_do_wait(unsigned int flags, au_wkq_func_t func, void *args)
{
int err;
@@ -165,12 +174,12 @@ int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb)
err = 0;
wkinfo = kmalloc(sizeof(*wkinfo), GFP_NOFS);
if (wkinfo) {
- wkinfo->sb = sb;
+ wkinfo->kobj = &au_sbi(sb)->si_kobj;
wkinfo->flags = !AuWkq_WAIT;
wkinfo->func = func;
wkinfo->args = args;
wkinfo->comp = NULL;
- kobject_get(&au_sbi(sb)->si_kobj);
+ kobject_get(wkinfo->kobj);
__module_get(THIS_MODULE);
au_wkq_run(wkinfo, !AuWkq_WAIT);
@@ -206,7 +215,9 @@ int __init au_wkq_init(void)
err = 0;
for (i = 0; !err && i < ARRAY_SIZE(au_wkq); i++) {
- au_wkq[i].wkq = create_workqueue(au_wkq[i].name);
+ BUILD_BUG_ON(!WQ_RESCUER);
+ au_wkq[i].wkq = alloc_workqueue(au_wkq[i].name, !WQ_RESCUER,
+ WQ_DFL_ACTIVE);
if (IS_ERR(au_wkq[i].wkq))
err = PTR_ERR(au_wkq[i].wkq);
else if (!au_wkq[i].wkq)
@@ -214,9 +225,7 @@ int __init au_wkq_init(void)
if (unlikely(err))
au_wkq[i].wkq = NULL;
}
- if (!err)
- au_dbg_verify_wkq();
- else
+ if (unlikely(err))
au_wkq_fin();
return err;
diff --git a/ubuntu/aufs/wkq.h b/ubuntu/aufs/wkq.h
index 75622828688..b216f03d6e3 100644
--- a/ubuntu/aufs/wkq.h
+++ b/ubuntu/aufs/wkq.h
@@ -50,8 +50,10 @@ typedef void (*au_wkq_func_t)(void *args);
#define AuWkq_WAIT 1
#define AuWkq_PRE (1 << 1)
#define au_ftest_wkq(flags, name) ((flags) & AuWkq_##name)
-#define au_fset_wkq(flags, name) { (flags) |= AuWkq_##name; }
-#define au_fclr_wkq(flags, name) { (flags) &= ~AuWkq_##name; }
+#define au_fset_wkq(flags, name) \
+ do { (flags) |= AuWkq_##name; } while (0)
+#define au_fclr_wkq(flags, name) \
+ do { (flags) &= ~AuWkq_##name; } while (0)
/* wkq.c */
int au_wkq_do_wait(unsigned int flags, au_wkq_func_t func, void *args);
diff --git a/ubuntu/aufs/xino.c b/ubuntu/aufs/xino.c
index 06833a40f2b..84e745a1310 100644
--- a/ubuntu/aufs/xino.c
+++ b/ubuntu/aufs/xino.c
@@ -168,7 +168,8 @@ struct file *au_xino_create2(struct file *base_file, struct file *copy_src)
path.mnt = base_file->f_vfsmnt;
file = vfsub_dentry_open(&path,
- O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE);
+ O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE
+ /* | FMODE_NONOTIFY */);
if (IS_ERR(file)) {
pr_err("%.*s open err %ld\n", AuLNPair(name), PTR_ERR(file));
goto out_dput;
@@ -612,7 +613,7 @@ ino_t au_xino_new_ino(struct super_block *sb)
out:
set_bit(free_bit, p);
- sbinfo->si_xib_next_bit++;
+ sbinfo->si_xib_next_bit = free_bit + 1;
pindex = sbinfo->si_xib_last_pindex;
mutex_unlock(&sbinfo->si_xib_mtx);
ino = xib_calc_ino(pindex, free_bit);
@@ -684,7 +685,8 @@ struct file *au_xino_create(struct super_block *sb, char *fname, int silent)
* hnotify is disabled so we have no notify events to ignore.
* when a user specified the xino, we cannot get au_hdir to be ignored.
*/
- file = vfsub_filp_open(fname, O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE,
+ file = vfsub_filp_open(fname, O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE
+ /* | FMODE_NONOTIFY */,
S_IRUGO | S_IWUGO);
if (IS_ERR(file)) {
if (!silent)