UBUNTU: ubuntu: AUFS -- update to 097bf62d6f49619359d34bf17f242df38562489a
authorAndy Whitcroft <apw@canonical.com>
Mon, 22 Nov 2010 15:51:22 +0000 (15:51 +0000)
committerLeann Ogasawara <leann.ogasawara@canonical.com>
Mon, 28 Mar 2011 13:51:25 +0000 (06:51 -0700)
    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>

43 files changed:
ubuntu/aufs/BOM
ubuntu/aufs/Kconfig
ubuntu/aufs/Makefile
ubuntu/aufs/branch.c
ubuntu/aufs/branch.h
ubuntu/aufs/conf.mk
ubuntu/aufs/cpup.h
ubuntu/aufs/dcsub.h
ubuntu/aufs/debug.c
ubuntu/aufs/debug.h
ubuntu/aufs/dentry.c
ubuntu/aufs/dinfo.c
ubuntu/aufs/dir.c
ubuntu/aufs/f_op.c
ubuntu/aufs/file.c
ubuntu/aufs/finfo.c
ubuntu/aufs/hfsnotify.c
ubuntu/aufs/hinotify.c [deleted file]
ubuntu/aufs/hnotify.c
ubuntu/aufs/i_op.c
ubuntu/aufs/i_op_del.c
ubuntu/aufs/i_op_ren.c
ubuntu/aufs/iinfo.c
ubuntu/aufs/include/linux/Kbuild [new file with mode: 0644]
ubuntu/aufs/include/linux/aufs_type.h
ubuntu/aufs/inode.c
ubuntu/aufs/inode.h
ubuntu/aufs/opts.c
ubuntu/aufs/opts.h
ubuntu/aufs/plink.c
ubuntu/aufs/rdu.c
ubuntu/aufs/sbinfo.c
ubuntu/aufs/super.c
ubuntu/aufs/super.h
ubuntu/aufs/vdir.c
ubuntu/aufs/vfsub.c
ubuntu/aufs/vfsub.h
ubuntu/aufs/wbr_policy.c
ubuntu/aufs/whout.c
ubuntu/aufs/whout.h
ubuntu/aufs/wkq.c
ubuntu/aufs/wkq.h
ubuntu/aufs/xino.c

index a25a63e..efa81f9 100644 (file)
@@ -1,2 +1,2 @@
 URL: http://git.c3sl.ufpr.br/pub/scm/aufs/aufs2-standalone.git
-COMMIT: c656be344b5080b5a88cfc44977da2072c6b6f80
+COMMIT: 097bf62d6f49619359d34bf17f242df38562489a
index 989f2de..17f8f75 100644 (file)
@@ -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
index c83dd25..8e9f7c8 100644 (file)
@@ -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
index a890ae1..4687a35 100644 (file)
@@ -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;
 }
index cf430a5..ddbfbb8 100644 (file)
@@ -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;
index 9a57d84..9217b48 100644 (file)
@@ -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 \
index 506350d..cd77860 100644 (file)
@@ -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,
index 0c87168..be25a13 100644 (file)
@@ -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__ */
index 74af9d4..ec8dc07 100644 (file)
@@ -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)
index 443f4c5..c6b2626 100644 (file)
 
 #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)
 
index d669312..2743e26 100644 (file)
@@ -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.
index b57ef24..4a638dc 100644 (file)
@@ -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;
index b7a9302..d97ec02 100644 (file)
@@ -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,
index 67f2a5b..829a67e 100644 (file)
@@ -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;
 }
index 33ce3c7..15e38ce 100644 (file)
@@ -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);
index d618e46..0ffb553 100644 (file)
@@ -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;
index 7636a88..621b538 100644 (file)
 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 (file)
index c2d900b..0000000
+++ /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
-};
index 18d1707..535a5ce 100644 (file)
@@ -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;
index d8ad9af..bbda6e4 100644 (file)
@@ -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;
 }
 
index 1aa09d7..5b31bbd 100644 (file)
@@ -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;
        }
index bbd9eba..89efe67 100644 (file)
@@ -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 {
index 1678ba4..6bccfdf 100644 (file)
@@ -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 (file)
index 0000000..e1b2bd3
--- /dev/null
@@ -0,0 +1 @@
+header-y = aufs_type.h
index b338e44..c9e2845 100644 (file)
 #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')
index 98c4b37..fe4ee9b 100644 (file)
@@ -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;
 }
index 8985120..ecb91be 100644 (file)
@@ -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
index d0aef5c..bdb2712 100644 (file)
@@ -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)
index dc727ae..03ce335 100644 (file)
@@ -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;
index 5aad81d..dd7eb1e 100644 (file)
@@ -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;
 }
index 60ee58e..fedbc38 100644 (file)
 #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;
index 9b46ad2..1eefcb8 100644 (file)
@@ -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;
        }
index ed6b8ed..7aba5f2 100644 (file)
@@ -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,
index 2c8d20a..0cc087b 100644 (file)
@@ -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)
 {
index 0794106..5777ca4 100644 (file)
@@ -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
index cd3fe78..846a124 100644 (file)
@@ -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) {
index e97c1e5..4b44827 100644 (file)
 
 #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);
index f20cf97..bb57ae5 100644 (file)
@@ -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;
index 31cdec9..284b8cc 100644 (file)
@@ -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 */
        }
index df72838..b262ffd 100644 (file)
@@ -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);
index b1ca42e..9739d3a 100644 (file)
@@ -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;
index 7562282..b216f03 100644 (file)
@@ -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);
index 06833a4..84e745a 100644 (file)
@@ -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)