0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/module.h>
0009 #include <linux/device.h>
0010 #include <linux/devcoredump.h>
0011 #include <linux/list.h>
0012 #include <linux/slab.h>
0013 #include <linux/fs.h>
0014 #include <linux/workqueue.h>
0015
0016 static struct class devcd_class;
0017
0018
0019 static bool devcd_disabled;
0020
0021
0022 #define DEVCD_TIMEOUT (HZ * 60 * 5)
0023
0024 struct devcd_entry {
0025 struct device devcd_dev;
0026 void *data;
0027 size_t datalen;
0028 struct module *owner;
0029 ssize_t (*read)(char *buffer, loff_t offset, size_t count,
0030 void *data, size_t datalen);
0031 void (*free)(void *data);
0032 struct delayed_work del_wk;
0033 struct device *failing_dev;
0034 };
0035
0036 static struct devcd_entry *dev_to_devcd(struct device *dev)
0037 {
0038 return container_of(dev, struct devcd_entry, devcd_dev);
0039 }
0040
0041 static void devcd_dev_release(struct device *dev)
0042 {
0043 struct devcd_entry *devcd = dev_to_devcd(dev);
0044
0045 devcd->free(devcd->data);
0046 module_put(devcd->owner);
0047
0048
0049
0050
0051
0052 if (devcd->failing_dev->kobj.sd)
0053 sysfs_delete_link(&devcd->failing_dev->kobj, &dev->kobj,
0054 "devcoredump");
0055
0056 put_device(devcd->failing_dev);
0057 kfree(devcd);
0058 }
0059
0060 static void devcd_del(struct work_struct *wk)
0061 {
0062 struct devcd_entry *devcd;
0063
0064 devcd = container_of(wk, struct devcd_entry, del_wk.work);
0065
0066 device_del(&devcd->devcd_dev);
0067 put_device(&devcd->devcd_dev);
0068 }
0069
0070 static ssize_t devcd_data_read(struct file *filp, struct kobject *kobj,
0071 struct bin_attribute *bin_attr,
0072 char *buffer, loff_t offset, size_t count)
0073 {
0074 struct device *dev = kobj_to_dev(kobj);
0075 struct devcd_entry *devcd = dev_to_devcd(dev);
0076
0077 return devcd->read(buffer, offset, count, devcd->data, devcd->datalen);
0078 }
0079
0080 static ssize_t devcd_data_write(struct file *filp, struct kobject *kobj,
0081 struct bin_attribute *bin_attr,
0082 char *buffer, loff_t offset, size_t count)
0083 {
0084 struct device *dev = kobj_to_dev(kobj);
0085 struct devcd_entry *devcd = dev_to_devcd(dev);
0086
0087 mod_delayed_work(system_wq, &devcd->del_wk, 0);
0088
0089 return count;
0090 }
0091
0092 static struct bin_attribute devcd_attr_data = {
0093 .attr = { .name = "data", .mode = S_IRUSR | S_IWUSR, },
0094 .size = 0,
0095 .read = devcd_data_read,
0096 .write = devcd_data_write,
0097 };
0098
0099 static struct bin_attribute *devcd_dev_bin_attrs[] = {
0100 &devcd_attr_data, NULL,
0101 };
0102
0103 static const struct attribute_group devcd_dev_group = {
0104 .bin_attrs = devcd_dev_bin_attrs,
0105 };
0106
0107 static const struct attribute_group *devcd_dev_groups[] = {
0108 &devcd_dev_group, NULL,
0109 };
0110
0111 static int devcd_free(struct device *dev, void *data)
0112 {
0113 struct devcd_entry *devcd = dev_to_devcd(dev);
0114
0115 flush_delayed_work(&devcd->del_wk);
0116 return 0;
0117 }
0118
0119 static ssize_t disabled_show(struct class *class, struct class_attribute *attr,
0120 char *buf)
0121 {
0122 return sysfs_emit(buf, "%d\n", devcd_disabled);
0123 }
0124
0125 static ssize_t disabled_store(struct class *class, struct class_attribute *attr,
0126 const char *buf, size_t count)
0127 {
0128 long tmp = simple_strtol(buf, NULL, 10);
0129
0130
0131
0132
0133
0134
0135 if (tmp != 1)
0136 return -EINVAL;
0137
0138 devcd_disabled = true;
0139
0140 class_for_each_device(&devcd_class, NULL, NULL, devcd_free);
0141
0142 return count;
0143 }
0144 static CLASS_ATTR_RW(disabled);
0145
0146 static struct attribute *devcd_class_attrs[] = {
0147 &class_attr_disabled.attr,
0148 NULL,
0149 };
0150 ATTRIBUTE_GROUPS(devcd_class);
0151
0152 static struct class devcd_class = {
0153 .name = "devcoredump",
0154 .owner = THIS_MODULE,
0155 .dev_release = devcd_dev_release,
0156 .dev_groups = devcd_dev_groups,
0157 .class_groups = devcd_class_groups,
0158 };
0159
0160 static ssize_t devcd_readv(char *buffer, loff_t offset, size_t count,
0161 void *data, size_t datalen)
0162 {
0163 return memory_read_from_buffer(buffer, count, &offset, data, datalen);
0164 }
0165
0166 static void devcd_freev(void *data)
0167 {
0168 vfree(data);
0169 }
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181 void dev_coredumpv(struct device *dev, void *data, size_t datalen,
0182 gfp_t gfp)
0183 {
0184 dev_coredumpm(dev, NULL, data, datalen, gfp, devcd_readv, devcd_freev);
0185 }
0186 EXPORT_SYMBOL_GPL(dev_coredumpv);
0187
0188 static int devcd_match_failing(struct device *dev, const void *failing)
0189 {
0190 struct devcd_entry *devcd = dev_to_devcd(dev);
0191
0192 return devcd->failing_dev == failing;
0193 }
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203 static void devcd_free_sgtable(void *data)
0204 {
0205 _devcd_free_sgtable(data);
0206 }
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218 static ssize_t devcd_read_from_sgtable(char *buffer, loff_t offset,
0219 size_t buf_len, void *data,
0220 size_t data_len)
0221 {
0222 struct scatterlist *table = data;
0223
0224 if (offset > data_len)
0225 return -EINVAL;
0226
0227 if (offset + buf_len > data_len)
0228 buf_len = data_len - offset;
0229 return sg_pcopy_to_buffer(table, sg_nents(table), buffer, buf_len,
0230 offset);
0231 }
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247
0248 void dev_coredumpm(struct device *dev, struct module *owner,
0249 void *data, size_t datalen, gfp_t gfp,
0250 ssize_t (*read)(char *buffer, loff_t offset, size_t count,
0251 void *data, size_t datalen),
0252 void (*free)(void *data))
0253 {
0254 static atomic_t devcd_count = ATOMIC_INIT(0);
0255 struct devcd_entry *devcd;
0256 struct device *existing;
0257
0258 if (devcd_disabled)
0259 goto free;
0260
0261 existing = class_find_device(&devcd_class, NULL, dev,
0262 devcd_match_failing);
0263 if (existing) {
0264 put_device(existing);
0265 goto free;
0266 }
0267
0268 if (!try_module_get(owner))
0269 goto free;
0270
0271 devcd = kzalloc(sizeof(*devcd), gfp);
0272 if (!devcd)
0273 goto put_module;
0274
0275 devcd->owner = owner;
0276 devcd->data = data;
0277 devcd->datalen = datalen;
0278 devcd->read = read;
0279 devcd->free = free;
0280 devcd->failing_dev = get_device(dev);
0281
0282 device_initialize(&devcd->devcd_dev);
0283
0284 dev_set_name(&devcd->devcd_dev, "devcd%d",
0285 atomic_inc_return(&devcd_count));
0286 devcd->devcd_dev.class = &devcd_class;
0287
0288 if (device_add(&devcd->devcd_dev))
0289 goto put_device;
0290
0291
0292
0293
0294
0295
0296 if (sysfs_create_link(&devcd->devcd_dev.kobj, &dev->kobj,
0297 "failing_device") ||
0298 sysfs_create_link(&dev->kobj, &devcd->devcd_dev.kobj,
0299 "devcoredump"))
0300 dev_warn(dev, "devcoredump create_link failed\n");
0301
0302 INIT_DELAYED_WORK(&devcd->del_wk, devcd_del);
0303 schedule_delayed_work(&devcd->del_wk, DEVCD_TIMEOUT);
0304
0305 return;
0306 put_device:
0307 put_device(&devcd->devcd_dev);
0308 put_module:
0309 module_put(owner);
0310 free:
0311 free(data);
0312 }
0313 EXPORT_SYMBOL_GPL(dev_coredumpm);
0314
0315
0316
0317
0318
0319
0320
0321
0322
0323
0324
0325
0326
0327
0328 void dev_coredumpsg(struct device *dev, struct scatterlist *table,
0329 size_t datalen, gfp_t gfp)
0330 {
0331 dev_coredumpm(dev, NULL, table, datalen, gfp, devcd_read_from_sgtable,
0332 devcd_free_sgtable);
0333 }
0334 EXPORT_SYMBOL_GPL(dev_coredumpsg);
0335
0336 static int __init devcoredump_init(void)
0337 {
0338 return class_register(&devcd_class);
0339 }
0340 __initcall(devcoredump_init);
0341
0342 static void __exit devcoredump_exit(void)
0343 {
0344 class_for_each_device(&devcd_class, NULL, NULL, devcd_free);
0345 class_unregister(&devcd_class);
0346 }
0347 __exitcall(devcoredump_exit);