Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drivers: base: add coredump driver ops

This adds the coredump driver operation. When the driver defines it
a coredump file is added in the sysfs folder of the device upon
driver binding. The file is removed when the driver is unbound.
User-space can trigger a coredump for this device by echo'ing to
the coredump file.

Signed-off-by: Arend van Spriel <aspriel@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Arend van Spriel and committed by
Greg Kroah-Hartman
3c47d19f 36d1d09a

+34 -8
+33 -7
drivers/base/dd.c
··· 288 288 kobject_uevent(&dev->kobj, KOBJ_BIND); 289 289 } 290 290 291 + static ssize_t coredump_store(struct device *dev, struct device_attribute *attr, 292 + const char *buf, size_t count) 293 + { 294 + device_lock(dev); 295 + if (dev->driver->coredump) 296 + dev->driver->coredump(dev); 297 + device_unlock(dev); 298 + 299 + return count; 300 + } 301 + static DEVICE_ATTR_WO(coredump); 302 + 291 303 static int driver_sysfs_add(struct device *dev) 292 304 { 293 305 int ret; ··· 309 297 BUS_NOTIFY_BIND_DRIVER, dev); 310 298 311 299 ret = sysfs_create_link(&dev->driver->p->kobj, &dev->kobj, 300 + kobject_name(&dev->kobj)); 301 + if (ret) 302 + goto fail; 303 + 304 + ret = sysfs_create_link(&dev->kobj, &dev->driver->p->kobj, 305 + "driver"); 306 + if (ret) 307 + goto rm_dev; 308 + 309 + if (!IS_ENABLED(CONFIG_DEV_COREDUMP) || !dev->driver->coredump || 310 + !device_create_file(dev, &dev_attr_coredump)) 311 + return 0; 312 + 313 + sysfs_remove_link(&dev->kobj, "driver"); 314 + 315 + rm_dev: 316 + sysfs_remove_link(&dev->driver->p->kobj, 312 317 kobject_name(&dev->kobj)); 313 - if (ret == 0) { 314 - ret = sysfs_create_link(&dev->kobj, &dev->driver->p->kobj, 315 - "driver"); 316 - if (ret) 317 - sysfs_remove_link(&dev->driver->p->kobj, 318 - kobject_name(&dev->kobj)); 319 - } 318 + 319 + fail: 320 320 return ret; 321 321 } 322 322 ··· 337 313 struct device_driver *drv = dev->driver; 338 314 339 315 if (drv) { 316 + if (drv->coredump) 317 + device_remove_file(dev, &dev_attr_coredump); 340 318 sysfs_remove_link(&drv->p->kobj, kobject_name(&dev->kobj)); 341 319 sysfs_remove_link(&dev->kobj, "driver"); 342 320 }
+1 -1
include/linux/device.h
··· 287 287 const struct attribute_group **groups; 288 288 289 289 const struct dev_pm_ops *pm; 290 + int (*coredump) (struct device *dev); 290 291 291 292 struct driver_private *p; 292 293 }; ··· 300 299 struct bus_type *bus); 301 300 extern int driver_probe_done(void); 302 301 extern void wait_for_device_probe(void); 303 - 304 302 305 303 /* sysfs interface for exporting driver attributes */ 306 304