]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
gpio: sim: lock up configfs that an instantiated device depends on
authorKoichiro Den <koichiro.den@canonical.com>
Fri, 3 Jan 2025 14:18:29 +0000 (23:18 +0900)
committerBartosz Golaszewski <bartosz.golaszewski@linaro.org>
Fri, 3 Jan 2025 16:15:04 +0000 (17:15 +0100)
Once a sim device is instantiated and actively used, allowing rmdir for
its configfs serves no purpose and can be confusing. Effectively,
arbitrary users start depending on its existence.

Make the subsystem itself depend on the configfs entry for a sim device
while it is in active use.

Signed-off-by: Koichiro Den <koichiro.den@canonical.com>
Link: https://lore.kernel.org/r/20250103141829.430662-5-koichiro.den@canonical.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
drivers/gpio/gpio-sim.c

index f387dad81f2960b5ec3c1b5fd04081ee501cc75b..686ae3d11ba3629c18d91222bdb01cace5d1a940 100644 (file)
@@ -1027,6 +1027,30 @@ static void gpio_sim_device_deactivate(struct gpio_sim_device *dev)
        dev->pdev = NULL;
 }
 
+static void
+gpio_sim_device_lockup_configfs(struct gpio_sim_device *dev, bool lock)
+{
+       struct configfs_subsystem *subsys = dev->group.cg_subsys;
+       struct gpio_sim_bank *bank;
+       struct gpio_sim_line *line;
+
+       /*
+        * The device only needs to depend on leaf line entries. This is
+        * sufficient to lock up all the configfs entries that the
+        * instantiated, alive device depends on.
+        */
+       list_for_each_entry(bank, &dev->bank_list, siblings) {
+               list_for_each_entry(line, &bank->line_list, siblings) {
+                       if (lock)
+                               WARN_ON(configfs_depend_item_unlocked(
+                                               subsys, &line->group.cg_item));
+                       else
+                               configfs_undepend_item_unlocked(
+                                               &line->group.cg_item);
+               }
+       }
+}
+
 static ssize_t
 gpio_sim_device_config_live_store(struct config_item *item,
                                  const char *page, size_t count)
@@ -1039,14 +1063,24 @@ gpio_sim_device_config_live_store(struct config_item *item,
        if (ret)
                return ret;
 
-       guard(mutex)(&dev->lock);
+       if (live)
+               gpio_sim_device_lockup_configfs(dev, true);
 
-       if (live == gpio_sim_device_is_live(dev))
-               ret = -EPERM;
-       else if (live)
-               ret = gpio_sim_device_activate(dev);
-       else
-               gpio_sim_device_deactivate(dev);
+       scoped_guard(mutex, &dev->lock) {
+               if (live == gpio_sim_device_is_live(dev))
+                       ret = -EPERM;
+               else if (live)
+                       ret = gpio_sim_device_activate(dev);
+               else
+                       gpio_sim_device_deactivate(dev);
+       }
+
+       /*
+        * Undepend is required only if device disablement (live == 0)
+        * succeeds or if device enablement (live == 1) fails.
+        */
+       if (live == !!ret)
+               gpio_sim_device_lockup_configfs(dev, false);
 
        return ret ?: count;
 }