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>
URL: http://git.c3sl.ufpr.br/pub/scm/aufs/aufs2-standalone.git
-COMMIT: c656be344b5080b5a88cfc44977da2072c6b6f80
+COMMIT: 097bf62d6f49619359d34bf17f242df38562489a
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.
config AUFS_HFSNOTIFY
bool "fsnotify"
select FSNOTIFY
-config AUFS_HINOTIFY
- bool "inotify (DEPRECATED)"
- depends on INOTIFY
endchoice
config AUFS_EXPORT
# 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 \
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
* 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
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);
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 {
&& (!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;
}
|| 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;
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);
}
}
-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;
}
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;
}
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;
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 \
#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,
#ifdef __KERNEL__
+#include <linux/dcache.h>
#include <linux/types.h>
struct dentry;
/* ---------------------------------------------------------------------- */
+/* dcsub.c */
int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp);
void au_dpages_free(struct au_dcsub_pages *dpages);
typedef int (*au_dpages_test)(struct dentry *dentry, void *arg);
int 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__ */
*/
#include <linux/module.h>
+#include <linux/vt_kern.h>
#include "aufs.h"
int aufs_debug;
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)
#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>
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);
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)
#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;
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.
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;
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) {
#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
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,
file_sb_list_del(file);
au_set_h_fptr(file, bindex, NULL);
}
+
au_finfo_fin(file);
return 0;
}
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;
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);
}
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++)
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);
{
struct au_finfo *finfo;
+ au_nfiles_dec(file->f_dentry->d_sb);
+
finfo = au_fi(file);
AuDebugOn(finfo->fi_hdir);
AuRwDestroy(&finfo->fi_rwsem);
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;
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)
mark = &hn->hn_mark;
fsnotify_destroy_mark(mark);
fsnotify_put_mark(mark);
+
+ /* TODO: bad approach */
+ wait_event(au_hfsn_wq, hn->hn_mark_dead);
}
/* ---------------------------------------------------------------------- */
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 = {
+++ /dev/null
-/*
- * 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
-};
#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,
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;
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) {
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);
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;
}
#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;
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);
} 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);
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);
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);
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;
}
/*
* 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);
}
if (!err) {
- drop_nlink(inode);
+ vfsub_drop_nlink(inode);
epilog(dir, dentry, bindex);
/* update target timestamps */
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;
}
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;
}
#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 {
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;
return;
sb = inode->i_sb;
+ au_ninodes_dec(sb);
if (si_pid_test(sb))
au_xino_delete_inode(inode, unlinked);
else {
--- /dev/null
+header-y = aufs_type.h
#define __AUFS_TYPE_H__
#include <linux/ioctl.h>
-/* for those who didn't "make headers_install" */
-#ifdef __KERNEL__
#include <linux/kernel.h>
-#endif
#include <linux/limits.h>
#include <linux/types.h>
-#define AUFS_VERSION "2.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')
{
if (inode) {
AuDebugOn(!atomic_read(&inode->i_count));
- atomic_inc(&inode->i_count);
+ ihold(inode);
}
return inode;
}
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;
#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 */
#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;
#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
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);
- }
}
}
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
{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)
(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)
{
#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;
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
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;
}
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);
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);
dput(h_path.dentry);
out:
+ mutex_unlock(&h_dir->i_mutex);
return err;
}
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,
err = wkq_err;
} else
err = do_whplink(&tgtname, h_parent, h_dentry, br);
- mutex_unlock(&h_dir->i_mutex);
return err;
}
#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;
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;
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;
}
#include <linux/module.h>
#include <linux/seq_file.h>
#include <linux/statfs.h>
+#include <linux/vmalloc.h>
+#include <linux/writeback.h>
#include "aufs.h"
/*
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;
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);
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;
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);
/* ---------------------------------------------------------------------- */
+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.
*/
/* ---------------------------------------------------------------------- */
-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)
.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,
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;
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 */
#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);
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)
{
#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
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;
{
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*/
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) {
#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.
#define while_file_list_for_each_entry \
}
-#endif /* CONFIG_SMP */
+#endif
+
+/* ---------------------------------------------------------------------- */
/* lock subclass for lower inode */
/* default MAX_LOCKDEP_SUBCLASSES(8) is not enough */
/* ---------------------------------------------------------------------- */
+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);
#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;
aufs_bindex_t bindex, bend;
int err;
unsigned long long b, bavail;
+ struct path h_path;
/* reduce the stack usage */
struct kstatfs *st;
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;
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 */
}
/* 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);
struct au_wkinfo {
struct work_struct wk;
- struct super_block *sb;
+ struct kobject *kobj;
unsigned int flags; /* see wkq.h */
{
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);
}
}
}
+/*
+ * 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;
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);
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)
if (unlikely(err))
au_wkq[i].wkq = NULL;
}
- if (!err)
- au_dbg_verify_wkq();
- else
+ if (unlikely(err))
au_wkq_fin();
return err;
#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);
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;
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);
* 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)