Skip to content
Snippets Groups Projects
  1. May 13, 2014
    • Tejun Heo's avatar
      kernfs, sysfs, cgroup: restrict extra perm check on open to sysfs · 555724a8
      Tejun Heo authored
      
      The kernfs open method - kernfs_fop_open() - inherited extra
      permission checks from sysfs.  While the vfs layer allows ignoring the
      read/write permissions checks if the issuer has CAP_DAC_OVERRIDE,
      sysfs explicitly denied open regardless of the cap if the file doesn't
      have any of the UGO perms of the requested access or doesn't implement
      the requested operation.  It can be debated whether this was a good
      idea or not but the behavior is too subtle and dangerous to change at
      this point.
      
      After cgroup got converted to kernfs, this extra perm check also got
      applied to cgroup breaking libcgroup which opens write-only files with
      O_RDWR as root.  This patch gates the extra open permission check with
      a new flag KERNFS_ROOT_EXTRA_OPEN_PERM_CHECK and enables it for sysfs.
      For sysfs, nothing changes.  For cgroup, root now can perform any
      operation regardless of the permissions as it was before kernfs
      conversion.  Note that kernfs still fails unimplemented operations
      with -EINVAL.
      
      While at it, add comments explaining KERNFS_ROOT flags.
      
      Signed-off-by: default avatarTejun Heo <tj@kernel.org>
      Reported-by: default avatarAndrey Wagin <avagin@gmail.com>
      Tested-by: default avatarAndrey Wagin <avagin@gmail.com>
      Cc: Li Zefan <lizefan@huawei.com>
      References: http://lkml.kernel.org/g/CANaxB-xUm3rJ-Cbp72q-rQJO5mZe1qK6qXsQM=vh0U8upJ44+A@mail.gmail.com
      
      
      Fixes: 2bd59d48 ("cgroup: convert to kernfs")
      Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
      555724a8
  2. Apr 25, 2014
  3. Apr 16, 2014
  4. Apr 04, 2014
    • Johannes Weiner's avatar
      mm + fs: store shadow entries in page cache · 91b0abe3
      Johannes Weiner authored
      
      Reclaim will be leaving shadow entries in the page cache radix tree upon
      evicting the real page.  As those pages are found from the LRU, an
      iput() can lead to the inode being freed concurrently.  At this point,
      reclaim must no longer install shadow pages because the inode freeing
      code needs to ensure the page tree is really empty.
      
      Add an address_space flag, AS_EXITING, that the inode freeing code sets
      under the tree lock before doing the final truncate.  Reclaim will check
      for this flag before installing shadow pages.
      
      Signed-off-by: default avatarJohannes Weiner <hannes@cmpxchg.org>
      Reviewed-by: default avatarRik van Riel <riel@redhat.com>
      Reviewed-by: default avatarMinchan Kim <minchan@kernel.org>
      Cc: Andrea Arcangeli <aarcange@redhat.com>
      Cc: Bob Liu <bob.liu@oracle.com>
      Cc: Christoph Hellwig <hch@infradead.org>
      Cc: Dave Chinner <david@fromorbit.com>
      Cc: Greg Thelen <gthelen@google.com>
      Cc: Hugh Dickins <hughd@google.com>
      Cc: Jan Kara <jack@suse.cz>
      Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
      Cc: Luigi Semenzato <semenzato@google.com>
      Cc: Mel Gorman <mgorman@suse.de>
      Cc: Metin Doslu <metin@citusdata.com>
      Cc: Michel Lespinasse <walken@google.com>
      Cc: Ozgun Erdogan <ozgun@citusdata.com>
      Cc: Peter Zijlstra <peterz@infradead.org>
      Cc: Roman Gushchin <klamm@yandex-team.ru>
      Cc: Ryan Mallon <rmallon@gmail.com>
      Cc: Tejun Heo <tj@kernel.org>
      Cc: Vlastimil Babka <vbabka@suse.cz>
      Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
      Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
      91b0abe3
  5. Mar 09, 2014
    • Tejun Heo's avatar
      kernfs: cache atomic_write_len in kernfs_open_file · b7ce40cf
      Tejun Heo authored
      
      While implementing atomic_write_len, 4d3773c4 ("kernfs: implement
      kernfs_ops->atomic_write_len") moved data copy from userland inside
      kernfs_get_active() and kernfs_open_file->mutex so that
      kernfs_ops->atomic_write_len can be accessed before copying buffer
      from userland; unfortunately, this could lead to locking order
      inversion involving mmap_sem if copy_from_user() takes a page fault.
      
        ======================================================
        [ INFO: possible circular locking dependency detected ]
        3.14.0-rc4-next-20140228-sasha-00011-g4077c67-dirty #26 Tainted: G        W
        -------------------------------------------------------
        trinity-c236/10658 is trying to acquire lock:
         (&of->mutex#2){+.+.+.}, at: [<fs/kernfs/file.c:487>] kernfs_fop_mmap+0x54/0x120
      
        but task is already holding lock:
         (&mm->mmap_sem){++++++}, at: [<mm/util.c:397>] vm_mmap_pgoff+0x6e/0xe0
      
        which lock already depends on the new lock.
      
        the existing dependency chain (in reverse order) is:
      
       -> #1 (&mm->mmap_sem){++++++}:
      	 [<kernel/locking/lockdep.c:1945 kernel/locking/lockdep.c:2131>] validate_chain+0x6c5/0x7b0
      	 [<kernel/locking/lockdep.c:3182>] __lock_acquire+0x4cd/0x5a0
      	 [<arch/x86/include/asm/current.h:14 kernel/locking/lockdep.c:3602>] lock_acquire+0x182/0x1d0
      	 [<mm/memory.c:4188>] might_fault+0x7e/0xb0
      	 [<arch/x86/include/asm/uaccess.h:713 fs/kernfs/file.c:291>] kernfs_fop_write+0xd8/0x190
      	 [<fs/read_write.c:473>] vfs_write+0xe3/0x1d0
      	 [<fs/read_write.c:523 fs/read_write.c:515>] SyS_write+0x5d/0xa0
      	 [<arch/x86/kernel/entry_64.S:749>] tracesys+0xdd/0xe2
      
       -> #0 (&of->mutex#2){+.+.+.}:
      	 [<kernel/locking/lockdep.c:1840>] check_prev_add+0x13f/0x560
      	 [<kernel/locking/lockdep.c:1945 kernel/locking/lockdep.c:2131>] validate_chain+0x6c5/0x7b0
      	 [<kernel/locking/lockdep.c:3182>] __lock_acquire+0x4cd/0x5a0
      	 [<arch/x86/include/asm/current.h:14 kernel/locking/lockdep.c:3602>] lock_acquire+0x182/0x1d0
      	 [<kernel/locking/mutex.c:470 kernel/locking/mutex.c:571>] mutex_lock_nested+0x6a/0x510
      	 [<fs/kernfs/file.c:487>] kernfs_fop_mmap+0x54/0x120
      	 [<mm/mmap.c:1573>] mmap_region+0x310/0x5c0
      	 [<mm/mmap.c:1365>] do_mmap_pgoff+0x385/0x430
      	 [<mm/util.c:399>] vm_mmap_pgoff+0x8f/0xe0
      	 [<mm/mmap.c:1416 mm/mmap.c:1374>] SyS_mmap_pgoff+0x1b0/0x210
      	 [<arch/x86/kernel/sys_x86_64.c:72>] SyS_mmap+0x1d/0x20
      	 [<arch/x86/kernel/entry_64.S:749>] tracesys+0xdd/0xe2
      
        other info that might help us debug this:
      
         Possible unsafe locking scenario:
      
      	 CPU0                    CPU1
      	 ----                    ----
          lock(&mm->mmap_sem);
      				 lock(&of->mutex#2);
      				 lock(&mm->mmap_sem);
          lock(&of->mutex#2);
      
         *** DEADLOCK ***
      
        1 lock held by trinity-c236/10658:
         #0:  (&mm->mmap_sem){++++++}, at: [<mm/util.c:397>] vm_mmap_pgoff+0x6e/0xe0
      
        stack backtrace:
        CPU: 2 PID: 10658 Comm: trinity-c236 Tainted: G        W 3.14.0-rc4-next-20140228-sasha-00011-g4077c67-dirty #26
         0000000000000000 ffff88011911fa48 ffffffff8438e945 0000000000000000
         0000000000000000 ffff88011911fa98 ffffffff811a0109 ffff88011911fab8
         ffff88011911fab8 ffff88011911fa98 ffff880119128cc0 ffff880119128cf8
        Call Trace:
         [<lib/dump_stack.c:52>] dump_stack+0x52/0x7f
         [<kernel/locking/lockdep.c:1213>] print_circular_bug+0x129/0x160
         [<kernel/locking/lockdep.c:1840>] check_prev_add+0x13f/0x560
         [<include/linux/spinlock.h:343 mm/slub.c:1933>] ? deactivate_slab+0x511/0x550
         [<kernel/locking/lockdep.c:1945 kernel/locking/lockdep.c:2131>] validate_chain+0x6c5/0x7b0
         [<kernel/locking/lockdep.c:3182>] __lock_acquire+0x4cd/0x5a0
         [<mm/mmap.c:1552>] ? mmap_region+0x24a/0x5c0
         [<arch/x86/include/asm/current.h:14 kernel/locking/lockdep.c:3602>] lock_acquire+0x182/0x1d0
         [<fs/kernfs/file.c:487>] ? kernfs_fop_mmap+0x54/0x120
         [<kernel/locking/mutex.c:470 kernel/locking/mutex.c:571>] mutex_lock_nested+0x6a/0x510
         [<fs/kernfs/file.c:487>] ? kernfs_fop_mmap+0x54/0x120
         [<kernel/sched/core.c:2477>] ? get_parent_ip+0x11/0x50
         [<fs/kernfs/file.c:487>] ? kernfs_fop_mmap+0x54/0x120
         [<fs/kernfs/file.c:487>] kernfs_fop_mmap+0x54/0x120
         [<mm/mmap.c:1573>] mmap_region+0x310/0x5c0
         [<mm/mmap.c:1365>] do_mmap_pgoff+0x385/0x430
         [<mm/util.c:397>] ? vm_mmap_pgoff+0x6e/0xe0
         [<mm/util.c:399>] vm_mmap_pgoff+0x8f/0xe0
         [<kernel/rcu/update.c:97>] ? __rcu_read_unlock+0x44/0xb0
         [<fs/file.c:641>] ? dup_fd+0x3c0/0x3c0
         [<mm/mmap.c:1416 mm/mmap.c:1374>] SyS_mmap_pgoff+0x1b0/0x210
         [<arch/x86/kernel/sys_x86_64.c:72>] SyS_mmap+0x1d/0x20
         [<arch/x86/kernel/entry_64.S:749>] tracesys+0xdd/0xe2
      
      Fix it by caching atomic_write_len in kernfs_open_file during open so
      that it can be determined without accessing kernfs_ops in
      kernfs_fop_write().  This restores the structure of kernfs_fop_write()
      before 4d3773c4 with updated @len determination logic.
      
      Signed-off-by: default avatarTejun Heo <tj@kernel.org>
      Reported-by: default avatarSasha Levin <sasha.levin@oracle.com>
      References: http://lkml.kernel.org/g/53113485.2090407@oracle.com
      
      
      Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
      b7ce40cf
    • Richard Cochran's avatar
      kernfs: fix off by one error. · 88391d49
      Richard Cochran authored
      
      The hash values 0 and 1 are reserved for magic directory entries, but
      the code only prevents names hashing to 0. This patch fixes the test
      to also prevent hash value 1.
      
      Signed-off-by: default avatarRichard Cochran <richardcochran@gmail.com>
      Cc: <stable@vger.kernel.org>
      Reviewed-by: default avatar"Eric W. Biederman" <ebiederm@xmission.com>
      Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
      88391d49
  6. Feb 25, 2014
    • Li Zefan's avatar
      sysfs: fix namespace refcnt leak · fed95bab
      Li Zefan authored
      
      As mount() and kill_sb() is not a one-to-one match, we shoudn't get
      ns refcnt unconditionally in sysfs_mount(), and instead we should
      get the refcnt only when kernfs_mount() allocated a new superblock.
      
      v2:
      - Changed the name of the new argument, suggested by Tejun.
      - Made the argument optional, suggested by Tejun.
      
      v3:
      - Make the new argument as second-to-last arg, suggested by Tejun.
      
      Signed-off-by: default avatarLi Zefan <lizefan@huawei.com>
      Acked-by: default avatarTejun Heo <tj@kernel.org>
       ---
       fs/kernfs/mount.c      | 8 +++++++-
       fs/sysfs/mount.c       | 5 +++--
       include/linux/kernfs.h | 9 +++++----
       3 files changed, 15 insertions(+), 7 deletions(-)
      Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
      fed95bab
  7. Feb 14, 2014
  8. Feb 12, 2014
    • Tejun Heo's avatar
      cgroup: remove cgroup->name · e61734c5
      Tejun Heo authored
      
      cgroup->name handling became quite complicated over time involving
      dedicated struct cgroup_name for RCU protection.  Now that cgroup is
      on kernfs, we can drop all of it and simply use kernfs_name/path() and
      friends.  Replace cgroup->name and all related code with kernfs
      name/path constructs.
      
      * Reimplement cgroup_name() and cgroup_path() as thin wrappers on top
        of kernfs counterparts, which involves semantic changes.
        pr_cont_cgroup_name() and pr_cont_cgroup_path() added.
      
      * cgroup->name handling dropped from cgroup_rename().
      
      * All users of cgroup_name/path() updated to the new semantics.  Users
        which were formatting the string just to printk them are converted
        to use pr_cont_cgroup_name/path() instead, which simplifies things
        quite a bit.  As cgroup_name() no longer requires RCU read lock
        around it, RCU lockings which were protecting only cgroup_name() are
        removed.
      
      v2: Comment above oom_info_lock updated as suggested by Michal.
      
      v3: dummy_top doesn't have a kn associated and
          pr_cont_cgroup_name/path() ended up calling the matching kernfs
          functions with NULL kn leading to oops.  Test for NULL kn and
          print "/" if so.  This issue was reported by Fengguang Wu.
      
      v4: Rebased on top of 0ab02ca8 ("cgroup: protect modifications to
          cgroup_idr with cgroup_mutex").
      
      Signed-off-by: default avatarTejun Heo <tj@kernel.org>
      Acked-by: default avatarPeter Zijlstra <peterz@infradead.org>
      Acked-by: default avatarMichal Hocko <mhocko@suse.cz>
      Acked-by: default avatarLi Zefan <lizefan@huawei.com>
      Cc: Fengguang Wu <fengguang.wu@intel.com>
      Cc: Ingo Molnar <mingo@redhat.com>
      Cc: Johannes Weiner <hannes@cmpxchg.org>
      Cc: Balbir Singh <bsingharora@gmail.com>
      Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
      e61734c5
  9. Feb 11, 2014
  10. Feb 08, 2014
    • Tejun Heo's avatar
      kernfs: add CONFIG_KERNFS · ba341d55
      Tejun Heo authored
      
      As sysfs was kernfs's only user, kernfs has been piggybacking on
      CONFIG_SYSFS; however, kernfs is scheduled to grow a new user very
      soon.  Introduce a separate config option CONFIG_KERNFS which is to be
      selected by kernfs users.
      
      Signed-off-by: default avatarTejun Heo <tj@kernel.org>
      Cc: linux-fsdevel@vger.kernel.org
      Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
      ba341d55
    • Tejun Heo's avatar
      kernfs: implement kernfs_get_parent(), kernfs_name/path() and friends · 3eef34ad
      Tejun Heo authored
      
      kernfs_node->parent and ->name are currently marked as "published"
      indicating that kernfs users may access them directly; however, those
      fields may get updated by kernfs_rename[_ns]() and unrestricted access
      may lead to erroneous values or oops.
      
      Protect ->parent and ->name updates with a irq-safe spinlock
      kernfs_rename_lock and implement the following accessors for these
      fields.
      
      * kernfs_name()		- format the node's name into the specified buffer
      * kernfs_path()		- format the node's path into the specified buffer
      * pr_cont_kernfs_name()	- pr_cont a node's name (doesn't need buffer)
      * pr_cont_kernfs_path()	- pr_cont a node's path (doesn't need buffer)
      * kernfs_get_parent()	- pin and return a node's parent
      
      All can be called under any context.  The recursive sysfs_pathname()
      in fs/sysfs/dir.c is replaced with kernfs_path() and
      sysfs_rename_dir_ns() is updated to use kernfs_get_parent() instead of
      dereferencing parent directly.
      
      v2: Dummy definition of kernfs_path() for !CONFIG_KERNFS was missing
          static inline making it cause a lot of build warnings.  Add it.
      
      Signed-off-by: default avatarTejun Heo <tj@kernel.org>
      Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
      3eef34ad
    • Tejun Heo's avatar
      kernfs: implement kernfs_node_from_dentry(), kernfs_root_from_sb() and kernfs_rename() · 0c23b225
      Tejun Heo authored
      
      Implement helpers to determine node from dentry and root from
      super_block.  Also add a kernfs_rename_ns() wrapper which assumes NULL
      namespace.  These generally make sense and will be used by cgroup.
      
      v2: Some dummy implementations for !CONFIG_SYSFS was missing.  Fixed.
          Reported by kbuild test robot.
      
      Signed-off-by: default avatarTejun Heo <tj@kernel.org>
      Cc: kbuild test robot <fengguang.wu@intel.com>
      Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
      0c23b225
    • Tejun Heo's avatar
      kernfs: implement kernfs_ops->atomic_write_len · 4d3773c4
      Tejun Heo authored
      
      A write to a kernfs_node is buffered through a kernel buffer.  Writes
      <= PAGE_SIZE are performed atomically, while larger ones are executed
      in PAGE_SIZE chunks.  While this is enough for sysfs, cgroup which is
      scheduled to be converted to use kernfs needs a bit more control over
      it.
      
      This patch adds kernfs_ops->atomic_write_len.  If not set (zero), the
      behavior stays the same.  If set, writes upto the size are executed
      atomically and larger writes are rejected with -E2BIG.
      
      A different implementation strategy would be allowing configuring
      chunking size while making the original write size available to the
      write method; however, such strategy, while being more complicated,
      doesn't really buy anything.  If the write implementation has to
      handle chunking, the specific chunk size shouldn't matter all that
      much.
      
      Signed-off-by: default avatarTejun Heo <tj@kernel.org>
      Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
      4d3773c4
    • Tejun Heo's avatar
      kernfs: allow nodes to be created in the deactivated state · d35258ef
      Tejun Heo authored
      
      Currently, kernfs_nodes are made visible to userland on creation,
      which makes it difficult for kernfs users to atomically succeed or
      fail creation of multiple nodes.  In addition, if something fails
      after creating some nodes, the created nodes might already be in use
      and their active refs need to be drained for removal, which has the
      potential to introduce tricky reverse locking dependency on active_ref
      depending on how the error path is synchronized.
      
      This patch introduces per-root flag KERNFS_ROOT_CREATE_DEACTIVATED.
      If set, all nodes under the root are created in the deactivated state
      and stay invisible to userland until explicitly enabled by the new
      kernfs_activate() API.  Also, nodes which have never been activated
      are guaranteed to bypass draining on removal thus allowing error paths
      to not worry about lockding dependency on active_ref draining.
      
      Signed-off-by: default avatarTejun Heo <tj@kernel.org>
      Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
      d35258ef
    • Tejun Heo's avatar
      kernfs: add missing kernfs_active() checks in directory operations · b9c9dad0
      Tejun Heo authored
      
      kernfs_iop_lookup(), kernfs_dir_pos() and kernfs_dir_next_pos() were
      missing kernfs_active() tests before using the found kernfs_node.  As
      deactivated state is currently visible only while a node is being
      removed, this doesn't pose an actual problem.  e.g. lookup succeeding
      on a deactivated node doesn't harm anything as the eventual file
      operations are gonna fail and those failures are indistinguishible
      from the cases in which the lookups had happened before the node was
      deactivated.
      
      However, we're gonna allow new nodes to be created deactivated and
      then activated explicitly by the kernfs user when it sees fit.  This
      is to support atomically making multiple nodes visible to userland and
      thus those nodes must not be visible to userland before activated.
      
      Let's plug the lookup and readdir holes so that deactivated nodes are
      invisible to userland.
      
      Signed-off-by: default avatarTejun Heo <tj@kernel.org>
      Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
      b9c9dad0
    • Tejun Heo's avatar
      kernfs: implement kernfs_syscall_ops->remount_fs() and ->show_options() · 6a7fed4e
      Tejun Heo authored
      
      Add two super_block related syscall callbacks ->remount_fs() and
      ->show_options() to kernfs_syscall_ops.  These simply forward the
      matching super_operations.
      
      Signed-off-by: default avatarTejun Heo <tj@kernel.org>
      Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
      6a7fed4e
    • Tejun Heo's avatar
      kernfs: rename kernfs_dir_ops to kernfs_syscall_ops · 90c07c89
      Tejun Heo authored
      
      We're gonna need non-dir syscall callbacks, which will make dir_ops a
      misnomer.  Let's rename kernfs_dir_ops to kernfs_syscall_ops.
      
      This is pure rename.
      
      Signed-off-by: default avatarTejun Heo <tj@kernel.org>
      Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
      90c07c89
    • Tejun Heo's avatar
      kernfs: invoke dir_ops while holding active ref of the target node · 07c7530d
      Tejun Heo authored
      
      kernfs_dir_ops are currently being invoked without any active
      reference, which makes it tricky for the invoked operations to
      determine whether the objects associated those nodes are safe to
      access and will remain that way for the duration of such operations.
      
      kernfs already has active_ref mechanism to deal with this which makes
      the removal of a given node the synchronization point for gating the
      file operations.  There's no reason for dir_ops to be any different.
      Update the dir_ops handling so that active_ref is held while the
      dir_ops are executing.  This guarantees that while a dir_ops is
      executing the target nodes stay alive.
      
      As kernfs_dir_ops doesn't have any in-kernel user at this point, this
      doesn't affect anybody.
      
      Signed-off-by: default avatarTejun Heo <tj@kernel.org>
      Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
      07c7530d
    • Tejun Heo's avatar
      kernfs, sysfs, driver-core: implement kernfs_remove_self() and its wrappers · 6b0afc2a
      Tejun Heo authored
      
      Sometimes it's necessary to implement a node which wants to delete
      nodes including itself.  This isn't straightforward because of kernfs
      active reference.  While a file operation is in progress, an active
      reference is held and kernfs_remove() waits for all such references to
      drain before completing.  For a self-deleting node, this is a deadlock
      as kernfs_remove() ends up waiting for an active reference that itself
      is sitting on top of.
      
      This currently is worked around in the sysfs layer using
      sysfs_schedule_callback() which makes such removals asynchronous.
      While it works, it's rather cumbersome and inherently breaks
      synchronicity of the operation - the file operation which triggered
      the operation may complete before the removal is finished (or even
      started) and the removal may fail asynchronously.  If a removal
      operation is immmediately followed by another operation which expects
      the specific name to be available (e.g. removal followed by rename
      onto the same name), there's no way to make the latter operation
      reliable.
      
      The thing is there's no inherent reason for this to be asynchrnous.
      All that's necessary to do this synchronous is a dedicated operation
      which drops its own active ref and deactivates self.  This patch
      implements kernfs_remove_self() and its wrappers in sysfs and driver
      core.  kernfs_remove_self() is to be called from one of the file
      operations, drops the active ref the task is holding, removes the self
      node, and restores active ref to the dead node so that the ref is
      balanced afterwards.  __kernfs_remove() is updated so that it takes an
      early exit if the target node is already fully removed so that the
      active ref restored by kernfs_remove_self() after removal doesn't
      confuse the deactivation path.
      
      This makes implementing self-deleting nodes very easy.  The normal
      removal path doesn't even need to be changed to use
      kernfs_remove_self() for the self-deleting node.  The method can
      invoke kernfs_remove_self() on itself before proceeding the normal
      removal path.  kernfs_remove() invoked on the node by the normal
      deletion path will simply be ignored.
      
      This will replace sysfs_schedule_callback().  A subtle feature of
      sysfs_schedule_callback() is that it collapses multiple invocations -
      even if multiple removals are triggered, the removal callback is run
      only once.  An equivalent effect can be achieved by testing the return
      value of kernfs_remove_self() - only the one which gets %true return
      value should proceed with actual deletion.  All other instances of
      kernfs_remove_self() will wait till the enclosing kernfs operation
      which invoked the winning instance of kernfs_remove_self() finishes
      and then return %false.  This trivially makes all users of
      kernfs_remove_self() automatically show correct synchronous behavior
      even when there are multiple concurrent operations - all "echo 1 >
      delete" instances will finish only after the whole operation is
      completed by one of the instances.
      
      Note that manipulation of active ref is implemented in separate public
      functions - kernfs_[un]break_active_protection().
      kernfs_remove_self() is the only user at the moment but this will be
      used to cater to more complex cases.
      
      v2: For !CONFIG_SYSFS, dummy version kernfs_remove_self() was missing
          and sysfs_remove_file_self() had incorrect return type.  Fix it.
          Reported by kbuild test bot.
      
      v3: kernfs_[un]break_active_protection() separated out from
          kernfs_remove_self() and exposed as public API.
      
      Signed-off-by: default avatarTejun Heo <tj@kernel.org>
      Cc: Alan Stern <stern@rowland.harvard.edu>
      Cc: kbuild test robot <fengguang.wu@intel.com>
      Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
      6b0afc2a
    • Tejun Heo's avatar
      kernfs: remove KERNFS_REMOVED · 81c173cb
      Tejun Heo authored
      
      KERNFS_REMOVED is used to mark half-initialized and dying nodes so
      that they don't show up in lookups and deny adding new nodes under or
      renaming it; however, its role overlaps that of deactivation.
      
      It's necessary to deny addition of new children while removal is in
      progress; however, this role considerably intersects with deactivation
      - KERNFS_REMOVED prevents new children while deactivation prevents new
      file operations.  There's no reason to have them separate making
      things more complex than necessary.
      
      This patch removes KERNFS_REMOVED.
      
      * Instead of KERNFS_REMOVED, each node now starts its life
        deactivated.  This means that we now use both atomic_add() and
        atomic_sub() on KN_DEACTIVATED_BIAS, which is INT_MIN.  The compiler
        generates an overflow warnings when negating INT_MIN as the negation
        can't be represented as a positive number.  Nothing is actually
        broken but let's bump BIAS by one to avoid the warnings for archs
        which negates the subtrahend..
      
      * A new helper kernfs_active() which tests whether kn->active >= 0 is
        added for convenience and lockdep annotation.  All KERNFS_REMOVED
        tests are replaced with negated kernfs_active() tests.
      
      * __kernfs_remove() is updated to deactivate, but not drain, all nodes
        in the subtree instead of setting KERNFS_REMOVED.  This removes
        deactivation from kernfs_deactivate(), which is now renamed to
        kernfs_drain().
      
      * Sanity check on KERNFS_REMOVED in kernfs_put() is replaced with
        checks on the active ref.
      
      * Some comment style updates in the affected area.
      
      v2: Reordered before removal path restructuring.  kernfs_active()
          dropped and kernfs_get/put_active() used instead.  RB_EMPTY_NODE()
          used in the lookup paths.
      
      v3: Reverted most of v2 except for creating a new node with
          KN_DEACTIVATED_BIAS.
      
      Signed-off-by: default avatarTejun Heo <tj@kernel.org>
      Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
      81c173cb
    • Tejun Heo's avatar
      kernfs: remove KERNFS_ACTIVE_REF and add kernfs_lockdep() · 182fd64b
      Tejun Heo authored
      
      There currently are two mechanisms gating active ref lockdep
      annotations - KERNFS_LOCKDEP flag and KERNFS_ACTIVE_REF type mask.
      The former disables lockdep annotations in kernfs_get/put_active()
      while the latter disables all of kernfs_deactivate().
      
      While KERNFS_ACTIVE_REF also behaves as an optimization to skip the
      deactivation step for non-file nodes, the benefit is marginal and it
      needlessly diverges code paths.  Let's drop KERNFS_ACTIVE_REF.
      
      While at it, add a test helper kernfs_lockdep() to test KERNFS_LOCKDEP
      flag so that it's more convenient and the related code can be compiled
      out when not enabled.
      
      v2: Refreshed on top of ("kernfs: make kernfs_deactivate() honor
          KERNFS_LOCKDEP flag").  As the earlier patch already added
          KERNFS_LOCKDEP tests to kernfs_deactivate(), those additions are
          dropped from this patch and the existing ones are simply converted
          to kernfs_lockdep().
      
      Signed-off-by: default avatarTejun Heo <tj@kernel.org>
      Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
      182fd64b
    • Tejun Heo's avatar
      kernfs: remove kernfs_addrm_cxt · 988cd7af
      Tejun Heo authored
      
      kernfs_addrm_cxt and the accompanying kernfs_addrm_start/finish() were
      added because there were operations which should be performed outside
      kernfs_mutex after adding and removing kernfs_nodes.  The necessary
      operations were recorded in kernfs_addrm_cxt and performed by
      kernfs_addrm_finish(); however, after the recent changes which
      relocated deactivation and unmapping so that they're performed
      directly during removal, the only operation kernfs_addrm_finish()
      performs is kernfs_put(), which can be moved inside the removal path
      too.
      
      This patch moves the kernfs_put() of the base ref to __kernfs_remove()
      and remove kernfs_addrm_cxt and kernfs_addrm_start/finish().
      
      * kernfs_add_one() is updated to grab and release kernfs_mutex itself.
        sysfs_addrm_start/finish() invocations around it are removed from
        all users.
      
      * __kernfs_remove() puts an unlinked node directly instead of chaining
        it to kernfs_addrm_cxt.  Its callers are updated to grab and release
        kernfs_mutex instead of calling kernfs_addrm_start/finish() around
        it.
      
      v2: Rebased on top of "kernfs: associate a new kernfs_node with its
          parent on creation" which dropped @parent from kernfs_add_one().
      
      Signed-off-by: default avatarTejun Heo <tj@kernel.org>
      Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
      988cd7af
    • Tejun Heo's avatar
      kernfs: invoke kernfs_unmap_bin_file() directly from kernfs_deactivate() · ccf02aaf
      Tejun Heo authored
      
      kernfs_unmap_bin_file() is supposed to unmap all memory mappings of
      the target file before kernfs_remove() finishes; however, it currently
      is being called from kernfs_addrm_finish() and has the same race
      problem as the original implementation of deactivation when there are
      multiple removers - only the remover which snatches the node to its
      addrm_cxt->removed list is guaranteed to wait for its completion
      before returning.
      
      It can be easily fixed by moving kernfs_unmap_bin_file() invocation
      from kernfs_addrm_finish() to kernfs_deactivated().  The function may
      be called multiple times but that shouldn't do any harm.
      
      Signed-off-by: default avatarTejun Heo <tj@kernel.org>
      Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
      ccf02aaf
    • Tejun Heo's avatar
      kernfs: restructure removal path to fix possible premature return · 35beab06
      Tejun Heo authored
      
      The recursive nature of kernfs_remove() means that, even if
      kernfs_remove() is not allowed to be called multiple times on the same
      node, there may be race conditions between removal of parent and its
      descendants.  While we can claim that kernfs_remove() shouldn't be
      called on one of the descendants while the removal of an ancestor is
      in progress, such rule is unnecessarily restrictive and very difficult
      to enforce.  It's better to simply allow invoking kernfs_remove() as
      the caller sees fit as long as the caller ensures that the node is
      accessible.
      
      The current behavior in such situations is broken.  Whoever enters
      removal path first takes the node off the hierarchy and then
      deactivates.  Following removers either return as soon as it notices
      that it's not the first one or can't even find the target node as it
      has already been removed from the hierarchy.  In both cases, the
      following removers may finish prematurely while the nodes which should
      be removed and drained are still being processed by the first one.
      
      This patch restructures so that multiple removers, whether through
      recursion or direction invocation, always follow the following rules.
      
      * When there are multiple concurrent removers, only one puts the base
        ref.
      
      * Regardless of which one puts the base ref, all removers are blocked
        until the target node is fully deactivated and removed.
      
      To achieve the above, removal path now first marks all descendants
      including self REMOVED and then deactivates and unlinks leftmost
      descendant one-by-one.  kernfs_deactivate() is called directly from
      __kernfs_removal() and drops and regrabs kernfs_mutex for each
      descendant to drain active refs.  As this means that multiple removers
      can enter kernfs_deactivate() for the same node, the function is
      updated so that it can handle multiple deactivators of the same node -
      only one actually deactivates but all wait till drain completion.
      
      The restructured removal path guarantees that a removed node gets
      unlinked only after the node is deactivated and drained.  Combined
      with proper multiple deactivator handling, this guarantees that any
      invocation of kernfs_remove() returns only after the node itself and
      all its descendants are deactivated, drained and removed.
      
      v2: Draining separated into a separate loop (used to be in the same
          loop as unlink) and done from __kernfs_deactivate().  This is to
          allow exposing deactivation as a separate interface later.
      
          Root node removal was broken in v1 patch.  Fixed.
      
      v3: Revert most of v2 except for root node removal fix and
          simplification of KERNFS_REMOVED setting loop.
      
      v4: Refreshed on top of ("kernfs: make kernfs_deactivate() honor
          KERNFS_LOCKDEP flag").
      
      Signed-off-by: default avatarTejun Heo <tj@kernel.org>
      Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
      35beab06
    • Tejun Heo's avatar
      kernfs: replace kernfs_node->u.completion with kernfs_root->deactivate_waitq · abd54f02
      Tejun Heo authored
      
      kernfs_node->u.completion is used to notify deactivation completion
      from kernfs_put_active() to kernfs_deactivate().  We now allow
      multiple racing removals of the same node and the current removal
      scheme is no longer correct - kernfs_remove() invocation may return
      before the node is properly deactivated if it races against another
      removal.  The removal path will be restructured to address the issue.
      
      To help such restructure which requires supporting multiple waiters,
      this patch replaces kernfs_node->u.completion with
      kernfs_root->deactivate_waitq.  This makes deactivation event
      notifications share a per-root waitqueue_head; however, the wait path
      is quite cold and this will also allow shaving one pointer off
      kernfs_node.
      
      v2: Refreshed on top of ("kernfs: make kernfs_deactivate() honor
          KERNFS_LOCKDEP flag").
      
      Signed-off-by: default avatarTejun Heo <tj@kernel.org>
      Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
      abd54f02
    • Tejun Heo's avatar
      kernfs: make kernfs_deactivate() honor KERNFS_LOCKDEP flag · a6607930
      Tejun Heo authored
      
      kernfs_deactivate() forgot to check whether KERNFS_LOCKDEP is set
      before performing lockdep annotations and ends up feeding
      uninitialized lockdep_map to lockdep triggering warning like the
      following on USB stick hotunplug.
      
       usb 1-2: USB disconnect, device number 2
       INFO: trying to register non-static key.
       the code is fine but needs lockdep annotation.
       turning off the locking correctness validator.
       CPU: 1 PID: 62 Comm: khubd Not tainted 3.13.0-work+ #82
       Hardware name: empty empty/S3992, BIOS 080011  10/26/2007
        ffff880065ca7f60 ffff88013a4ffa08 ffffffff81cfb6bd 0000000000000002
        ffff88013a4ffac8 ffffffff810f8530 ffff88013a4fc710 0000000000000002
        ffff880100000000 ffffffff82a3db50 0000000000000001 ffff88013a4fc710
       Call Trace:
        [<ffffffff81cfb6bd>] dump_stack+0x4e/0x7a
        [<ffffffff810f8530>] __lock_acquire+0x1910/0x1e70
        [<ffffffff810f931a>] lock_acquire+0x9a/0x1d0
        [<ffffffff8127c75e>] kernfs_deactivate+0xee/0x130
        [<ffffffff8127d4c8>] kernfs_addrm_finish+0x38/0x60
        [<ffffffff8127d701>] kernfs_remove_by_name_ns+0x51/0xa0
        [<ffffffff8127b4f1>] remove_files.isra.1+0x41/0x80
        [<ffffffff8127b7e7>] sysfs_remove_group+0x47/0xa0
        [<ffffffff8127b873>] sysfs_remove_groups+0x33/0x50
        [<ffffffff8177d66d>] device_remove_attrs+0x4d/0x80
        [<ffffffff8177e25e>] device_del+0x12e/0x1d0
        [<ffffffff819722c2>] usb_disconnect+0x122/0x1a0
        [<ffffffff819749b5>] hub_thread+0x3c5/0x1290
        [<ffffffff810c6a6d>] kthread+0xed/0x110
        [<ffffffff81d0a56c>] ret_from_fork+0x7c/0xb0
      
      Fix it by making kernfs_deactivate() perform lockdep annotations only
      if KERNFS_LOCKDEP is set.
      
      Signed-off-by: default avatarTejun Heo <tj@kernel.org>
      Reported-by: default avatarFabio Estevam <festevam@gmail.com>
      Reported-by: default avatarAlan Stern <stern@rowland.harvard.edu>
      Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
      a6607930
  11. Feb 05, 2014
    • Tejun Heo's avatar
      kernfs: make kernfs_deactivate() honor KERNFS_LOCKDEP flag · da9846ae
      Tejun Heo authored
      
      kernfs_deactivate() forgot to check whether KERNFS_LOCKDEP is set
      before performing lockdep annotations and ends up feeding
      uninitialized lockdep_map to lockdep triggering warning like the
      following on USB stick hotunplug.
      
       usb 1-2: USB disconnect, device number 2
       INFO: trying to register non-static key.
       the code is fine but needs lockdep annotation.
       turning off the locking correctness validator.
       CPU: 1 PID: 62 Comm: khubd Not tainted 3.13.0-work+ #82
       Hardware name: empty empty/S3992, BIOS 080011  10/26/2007
        ffff880065ca7f60 ffff88013a4ffa08 ffffffff81cfb6bd 0000000000000002
        ffff88013a4ffac8 ffffffff810f8530 ffff88013a4fc710 0000000000000002
        ffff880100000000 ffffffff82a3db50 0000000000000001 ffff88013a4fc710
       Call Trace:
        [<ffffffff81cfb6bd>] dump_stack+0x4e/0x7a
        [<ffffffff810f8530>] __lock_acquire+0x1910/0x1e70
        [<ffffffff810f931a>] lock_acquire+0x9a/0x1d0
        [<ffffffff8127c75e>] kernfs_deactivate+0xee/0x130
        [<ffffffff8127d4c8>] kernfs_addrm_finish+0x38/0x60
        [<ffffffff8127d701>] kernfs_remove_by_name_ns+0x51/0xa0
        [<ffffffff8127b4f1>] remove_files.isra.1+0x41/0x80
        [<ffffffff8127b7e7>] sysfs_remove_group+0x47/0xa0
        [<ffffffff8127b873>] sysfs_remove_groups+0x33/0x50
        [<ffffffff8177d66d>] device_remove_attrs+0x4d/0x80
        [<ffffffff8177e25e>] device_del+0x12e/0x1d0
        [<ffffffff819722c2>] usb_disconnect+0x122/0x1a0
        [<ffffffff819749b5>] hub_thread+0x3c5/0x1290
        [<ffffffff810c6a6d>] kthread+0xed/0x110
        [<ffffffff81d0a56c>] ret_from_fork+0x7c/0xb0
      
      Fix it by making kernfs_deactivate() perform lockdep annotations only
      if KERNFS_LOCKDEP is set.
      
      Signed-off-by: default avatarTejun Heo <tj@kernel.org>
      Reported-by: default avatarFabio Estevam <festevam@gmail.com>
      Reported-by: default avatarAlan Stern <stern@rowland.harvard.edu>
      Reported-by: default avatarJiri Kosina <jkosina@suse.cz>
      Reported-by: default avatarDave Jones <davej@redhat.com>
      Tested-by: default avatarFabio Estevam <fabio.estevam@freescale.com>
      Tested-by: default avatarJiri Kosina <jkosina@suse.cz>
      Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
      da9846ae
  12. Jan 17, 2014
    • Tejun Heo's avatar
      kernfs: associate a new kernfs_node with its parent on creation · db4aad20
      Tejun Heo authored
      
      Once created, a kernfs_node is always destroyed by kernfs_put().
      Since ba7443bc ("sysfs, kernfs: implement
      kernfs_create/destroy_root()"), kernfs_put() depends on kernfs_root()
      to locate the ino_ida.  kernfs_root() in turn depends on
      kernfs_node->parent being set for !dir nodes.  This means that
      kernfs_put() of a !dir node requires its ->parent to be initialized.
      
      This leads to oops when a newly created !dir node is destroyed without
      going through kernfs_add_one() or after failing kernfs_add_one()
      before ->parent is set.  kernfs_root() invoked from kernfs_put() will
      try to dereference NULL parent.
      
      Fix it by moving parent association to kernfs_new_node() from
      kernfs_add_one().  kernfs_new_node() now takes @parent instead of
      @root and determines the root from the parent and also sets the new
      node's parent properly.  @parent parameter is removed from
      kernfs_add_one().  As there's no parent when creating the root node,
      __kernfs_new_node() which takes @root as before and doesn't set the
      parent is used in that case.
      
      This ensures that a kernfs_node in any stage in its life has its
      parent associated and thus can be put.
      
      Signed-off-by: default avatarTejun Heo <tj@kernel.org>
      Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
      db4aad20
  13. Jan 14, 2014
    • Tejun Heo's avatar
      kernfs: fix get_active failure handling in kernfs_seq_*() · bb305947
      Tejun Heo authored
      
      When kernfs_seq_start() fails to obtain an active reference, it
      returns ERR_PTR(-ENODEV).  kernfs_seq_stop() is then invoked with the
      error pointer value; however, it still proceeds to invoke
      kernfs_put_active() on the node leading to unbalanced put.
      
      If kernfs_seq_stop() is called even after active ref failure, it
      should skip invocation of @ops->seq_stop() and put_active.
      Unfortunately, this is a bit complicated because active ref failure
      isn't the only thing which may fail with ERR_PTR(-ENODEV).
      @ops->seq_start/next() may also fail with the error value and
      kernfs_seq_stop() doesn't have a way to tell apart those failures.
      
      Work it around by factoring out the active part of kernfs_seq_stop()
      into kernfs_seq_stop_active() and invoking it directly if
      @ops->seq_start/next() fail with ERR_PTR(-ENODEV) and updating
      kernfs_seq_stop() to skip kernfs_seq_stop_active() on
      ERR_PTR(-ENODEV).  This is a bit nasty but ensures that the active put
      is skipped iff get_active failed in kernfs_seq_start().
      
      tj: This was originally committed as d92d2e6b but got reverted by
          683bb276 along with other kernfs self removal patches.
          However, this one is an independent fix and shouldn't have been
          reverted together.  Reinstate the change.  Sorry about the mess.
      
      Signed-off-by: default avatarTejun Heo <tj@kernel.org>
      Cc: Sasha Levin <sasha.levin@oracle.com>
      Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
      bb305947
  14. Jan 13, 2014
Loading