linux-hardened/drivers/base
Tejun Heo 1ae06819c7 kernfs, sysfs, driver-core: implement kernfs_remove_self() and its wrappers
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 and deactivates using
__kernfs_deactivate_self(), removes the self node, and restores active
ref to the dead node using __kernfs_reactivate_self() 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.

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: Updated to use __kernfs_{de|re}activate_self().

Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: Alan Stern <stern@rowland.harvard.edu>
Cc: kbuild test robot <fengguang.wu@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2014-01-10 14:01:05 -08:00
..
power Merge branches 'pm-cpuidle' and 'pm-cpufreq' 2013-12-06 02:17:59 +01:00
regmap Merge remote-tracking branches 'regmap/fix/doc' and 'regmap/fix/mmio' into regmap-linus 2013-11-26 13:16:56 +00:00
attribute_container.c drivers: avoid format string in dev_set_name 2013-07-03 16:07:41 -07:00
base.h driver core: bus_type: add drv_groups 2013-08-12 15:33:31 -07:00
bus.c driver-core: Fix use-after-free triggered by bus_unregister() 2014-01-08 15:36:18 -08:00
class.c sysfs: make attr namespace interface less convoluted 2013-09-26 14:50:01 -07:00
core.c kernfs, sysfs, driver-core: implement kernfs_remove_self() and its wrappers 2014-01-10 14:01:05 -08:00
cpu.c hotplug, powerpc, x86: Remove cpu_hotplug_driver_lock() 2013-09-30 19:55:51 +02:00
dd.c PM / runtime: Use pm_runtime_put_sync() in __device_release_driver() 2013-11-07 19:13:49 +01:00
devres.c devres: restore zeroing behavior of devres_alloc() 2013-10-25 05:46:27 +01:00
devtmpfs.c devtmpfs: Calling delete_path() only when necessary 2013-12-19 10:10:32 -08:00
dma-buf.c dma-buf: Expose buffer size to userspace (v2) 2013-09-10 11:36:45 +05:30
dma-coherent.c drivers: dma-coherent: Fix typo in dma_mmap_from_coherent documentation 2012-10-23 14:05:32 +02:00
dma-contiguous.c Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/trivial 2013-11-15 16:47:22 -08:00
dma-mapping.c [media] dma-mapping: fix dma_common_get_sgtable() conditional compilation 2012-11-27 09:42:31 -02:00
driver.c driver core: add #include <linux/sysfs.h> to core files. 2013-08-27 10:24:15 -07:00
firmware.c
firmware_class.c firmware_class: Fix the file size check 2014-01-08 20:29:19 -08:00
hypervisor.c drivers/base: Add export.h for EXPORT_SYMBOL/THIS_MODULE as required. 2011-10-31 19:31:38 -04:00
init.c driver-core: implement 'sysdev' functionality for regular devices and buses 2011-12-14 14:29:38 -08:00
isa.c dma-mapping: replace all DMA_24BIT_MASK macro with DMA_BIT_MASK(24) 2009-04-07 08:31:12 -07:00
Kconfig Merge remote-tracking branch 'dma-public/for-v3.12-cma-dma' into for-next 2013-07-15 11:13:54 +02:00
Makefile Merge remote-tracking branch 'origin/next' into kvm-ppc-next 2013-08-29 00:41:59 +02:00
map.c
memory.c driver core: Release device_hotplug_lock when store_mem_state returns EINVAL 2013-10-16 18:42:41 -07:00
module.c driver core: module.c: Use kasprintf 2010-05-21 09:37:29 -07:00
node.c thp: account anon transparent huge pages into NR_ANON_PAGES 2013-09-12 15:38:03 -07:00
pinctrl.c drivers: pinctrl sleep and idle states in the core 2013-06-16 11:56:52 +02:00
platform.c ACPI / driver core: Store an ACPI device pointer in struct acpi_dev_node 2013-11-14 23:14:43 +01:00
reservation.c reservation: cross-device reservation support, v4 2013-06-28 12:02:15 +10:00
soc.c mode_t whack-a-mole: ->is_visible() returns umode_t... 2012-05-29 23:28:42 -04:00
syscore.c PM: Reintroduce dropped call to check_wakeup_irqs 2011-07-11 10:51:49 +02:00
topology.c cpu topology: remove stale arch_provides_topology_pointers and define_siblings_show_map/list() 2013-07-29 13:12:45 -07:00
transport_class.c drivers/base: transport_class explicitly requires EXPORT_SYMBOL 2011-10-31 19:31:15 -04:00