diff options
author | Andy Whitcroft <apw@canonical.com> | 2010-11-22 15:51:22 +0000 |
---|---|---|
committer | John Rigby <john.rigby@linaro.org> | 2011-09-23 08:47:33 -0600 |
commit | 5abe14bec7860b9684adca0a9a692442a024d689 (patch) | |
tree | 9f8260dd571aee3d47a13c18a049577e6217b8fb /ubuntu | |
parent | 7280367b3ef11ba2e806a3a7cb4bd99d11140ac6 (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')
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) |