hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/drivers/base/attribute_container.c
....@@ -236,6 +236,109 @@
236236 mutex_unlock(&attribute_container_mutex);
237237 }
238238
239
+static int
240
+do_attribute_container_device_trigger_safe(struct device *dev,
241
+ struct attribute_container *cont,
242
+ int (*fn)(struct attribute_container *,
243
+ struct device *, struct device *),
244
+ int (*undo)(struct attribute_container *,
245
+ struct device *, struct device *))
246
+{
247
+ int ret;
248
+ struct internal_container *ic, *failed;
249
+ struct klist_iter iter;
250
+
251
+ if (attribute_container_no_classdevs(cont))
252
+ return fn(cont, dev, NULL);
253
+
254
+ klist_for_each_entry(ic, &cont->containers, node, &iter) {
255
+ if (dev == ic->classdev.parent) {
256
+ ret = fn(cont, dev, &ic->classdev);
257
+ if (ret) {
258
+ failed = ic;
259
+ klist_iter_exit(&iter);
260
+ goto fail;
261
+ }
262
+ }
263
+ }
264
+ return 0;
265
+
266
+fail:
267
+ if (!undo)
268
+ return ret;
269
+
270
+ /* Attempt to undo the work partially done. */
271
+ klist_for_each_entry(ic, &cont->containers, node, &iter) {
272
+ if (ic == failed) {
273
+ klist_iter_exit(&iter);
274
+ break;
275
+ }
276
+ if (dev == ic->classdev.parent)
277
+ undo(cont, dev, &ic->classdev);
278
+ }
279
+ return ret;
280
+}
281
+
282
+/**
283
+ * attribute_container_device_trigger_safe - execute a trigger for each
284
+ * matching classdev or fail all of them.
285
+ *
286
+ * @dev: The generic device to run the trigger for
287
+ * @fn the function to execute for each classdev.
288
+ * @undo A function to undo the work previously done in case of error
289
+ *
290
+ * This function is a safe version of
291
+ * attribute_container_device_trigger. It stops on the first error and
292
+ * undo the partial work that has been done, on previous classdev. It
293
+ * is guaranteed that either they all succeeded, or none of them
294
+ * succeeded.
295
+ */
296
+int
297
+attribute_container_device_trigger_safe(struct device *dev,
298
+ int (*fn)(struct attribute_container *,
299
+ struct device *,
300
+ struct device *),
301
+ int (*undo)(struct attribute_container *,
302
+ struct device *,
303
+ struct device *))
304
+{
305
+ struct attribute_container *cont, *failed = NULL;
306
+ int ret = 0;
307
+
308
+ mutex_lock(&attribute_container_mutex);
309
+
310
+ list_for_each_entry(cont, &attribute_container_list, node) {
311
+
312
+ if (!cont->match(cont, dev))
313
+ continue;
314
+
315
+ ret = do_attribute_container_device_trigger_safe(dev, cont,
316
+ fn, undo);
317
+ if (ret) {
318
+ failed = cont;
319
+ break;
320
+ }
321
+ }
322
+
323
+ if (ret && !WARN_ON(!undo)) {
324
+ list_for_each_entry(cont, &attribute_container_list, node) {
325
+
326
+ if (failed == cont)
327
+ break;
328
+
329
+ if (!cont->match(cont, dev))
330
+ continue;
331
+
332
+ do_attribute_container_device_trigger_safe(dev, cont,
333
+ undo, NULL);
334
+ }
335
+ }
336
+
337
+ mutex_unlock(&attribute_container_mutex);
338
+ return ret;
339
+
340
+}
341
+
239342 /**
240343 * attribute_container_device_trigger - execute a trigger for each matching classdev
241344 *