summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKoichiro Den <koichiro.den@canonical.com>2025-01-03 17:18:28 +0300
committerBartosz Golaszewski <bartosz.golaszewski@linaro.org>2025-01-03 19:15:04 +0300
commitc7c434c1dba955005f5161dae73f09c0a922cfa7 (patch)
tree7cb86e3d51dcebe68b7d3274f3664f6b47aac876
parent656cc2e892f128b03ea9ef19bd11d70f71d5472b (diff)
downloadlinux-c7c434c1dba955005f5161dae73f09c0a922cfa7.tar.xz
gpio: virtuser: lock up configfs that an instantiated device depends on
Once a virtuser device is instantiated and actively used, allowing rmdir for its configfs serves no purpose and can be confusing. Userspace interacts with the virtual consumer at arbitrary times, meaning it depends on its existence. Make the subsystem itself depend on the configfs entry for a virtuser device while it is in active use. Signed-off-by: Koichiro Den <koichiro.den@canonical.com> Link: https://lore.kernel.org/r/20250103141829.430662-4-koichiro.den@canonical.com Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
-rw-r--r--drivers/gpio/gpio-virtuser.c47
1 files changed, 40 insertions, 7 deletions
diff --git a/drivers/gpio/gpio-virtuser.c b/drivers/gpio/gpio-virtuser.c
index d6244f0d3bc7..e89f299f2140 100644
--- a/drivers/gpio/gpio-virtuser.c
+++ b/drivers/gpio/gpio-virtuser.c
@@ -1546,6 +1546,30 @@ gpio_virtuser_device_deactivate(struct gpio_virtuser_device *dev)
dev->pdev = NULL;
}
+static void
+gpio_virtuser_device_lockup_configfs(struct gpio_virtuser_device *dev, bool lock)
+{
+ struct configfs_subsystem *subsys = dev->group.cg_subsys;
+ struct gpio_virtuser_lookup_entry *entry;
+ struct gpio_virtuser_lookup *lookup;
+
+ /*
+ * The device only needs to depend on leaf lookup entries. This is
+ * sufficient to lock up all the configfs entries that the
+ * instantiated, alive device depends on.
+ */
+ list_for_each_entry(lookup, &dev->lookup_list, siblings) {
+ list_for_each_entry(entry, &lookup->entry_list, siblings) {
+ if (lock)
+ WARN_ON(configfs_depend_item_unlocked(
+ subsys, &entry->group.cg_item));
+ else
+ configfs_undepend_item_unlocked(
+ &entry->group.cg_item);
+ }
+ }
+}
+
static ssize_t
gpio_virtuser_device_config_live_store(struct config_item *item,
const char *page, size_t count)
@@ -1558,15 +1582,24 @@ gpio_virtuser_device_config_live_store(struct config_item *item,
if (ret)
return ret;
- guard(mutex)(&dev->lock);
+ if (live)
+ gpio_virtuser_device_lockup_configfs(dev, true);
- if (live == gpio_virtuser_device_is_live(dev))
- return -EPERM;
+ scoped_guard(mutex, &dev->lock) {
+ if (live == gpio_virtuser_device_is_live(dev))
+ ret = -EPERM;
+ else if (live)
+ ret = gpio_virtuser_device_activate(dev);
+ else
+ gpio_virtuser_device_deactivate(dev);
+ }
- if (live)
- ret = gpio_virtuser_device_activate(dev);
- else
- gpio_virtuser_device_deactivate(dev);
+ /*
+ * Undepend is required only if device disablement (live == 0)
+ * succeeds or if device enablement (live == 1) fails.
+ */
+ if (live == !!ret)
+ gpio_virtuser_device_lockup_configfs(dev, false);
return ret ?: count;
}