1 // SPDX-License-Identifier: GPL-2.0
3 * Implements pstore backend driver that write to block (or non-block) storage
4 * devices, using the pstore/zone API.
7 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
9 #include <linux/kernel.h>
10 #include <linux/module.h>
11 #include "../../block/blk.h"
12 #include <linux/blkdev.h>
13 #include <linux/string.h>
15 #include <linux/of_address.h>
16 #include <linux/platform_device.h>
17 #include <linux/pstore_blk.h>
18 #include <linux/mount.h>
19 #include <linux/uio.h>
21 static long kmsg_size = CONFIG_PSTORE_BLK_KMSG_SIZE;
22 module_param(kmsg_size, long, 0400);
23 MODULE_PARM_DESC(kmsg_size, "kmsg dump record size in kbytes");
25 static int max_reason = CONFIG_PSTORE_BLK_MAX_REASON;
26 module_param(max_reason, int, 0400);
27 MODULE_PARM_DESC(max_reason,
28 "maximum reason for kmsg dump (default 2: Oops and Panic)");
30 #if IS_ENABLED(CONFIG_PSTORE_PMSG)
31 static long pmsg_size = CONFIG_PSTORE_BLK_PMSG_SIZE;
33 static long pmsg_size = -1;
35 module_param(pmsg_size, long, 0400);
36 MODULE_PARM_DESC(pmsg_size, "pmsg size in kbytes");
38 #if IS_ENABLED(CONFIG_PSTORE_CONSOLE)
39 static long console_size = CONFIG_PSTORE_BLK_CONSOLE_SIZE;
41 static long console_size = -1;
43 module_param(console_size, long, 0400);
44 MODULE_PARM_DESC(console_size, "console size in kbytes");
46 #if IS_ENABLED(CONFIG_PSTORE_FTRACE)
47 static long ftrace_size = CONFIG_PSTORE_BLK_FTRACE_SIZE;
49 static long ftrace_size = -1;
51 module_param(ftrace_size, long, 0400);
52 MODULE_PARM_DESC(ftrace_size, "ftrace size in kbytes");
55 * blkdev - the block device to use for pstore storage
57 * Usually, this will be a partition of a block device.
59 * blkdev accepts the following variants:
60 * 1) <hex_major><hex_minor> device number in hexadecimal representation,
61 * with no leading 0x, for example b302.
62 * 2) /dev/<disk_name> represents the device number of disk
63 * 3) /dev/<disk_name><decimal> represents the device number
64 * of partition - device number of disk plus the partition number
65 * 4) /dev/<disk_name>p<decimal> - same as the above, that form is
66 * used when disk name of partitioned disk ends on a digit.
67 * 5) PARTUUID=00112233-4455-6677-8899-AABBCCDDEEFF representing the
68 * unique id of a partition if the partition table provides it.
69 * The UUID may be either an EFI/GPT UUID, or refer to an MSDOS
70 * partition using the format SSSSSSSS-PP, where SSSSSSSS is a zero-
71 * filled hex representation of the 32-bit "NT disk signature", and PP
72 * is a zero-filled hex representation of the 1-based partition number.
73 * 6) PARTUUID=<UUID>/PARTNROFF=<int> to select a partition in relation to
74 * a partition with a known unique id.
75 * 7) <major>:<minor> major and minor number of the device separated by
78 static char blkdev[80] = CONFIG_PSTORE_BLK_BLKDEV;
79 module_param_string(blkdev, blkdev, 80, 0400);
80 MODULE_PARM_DESC(blkdev, "block device for pstore storage");
83 * All globals must only be accessed under the pstore_blk_lock
84 * during the register/unregister functions.
86 static DEFINE_MUTEX(pstore_blk_lock);
87 static struct block_device *psblk_bdev;
88 static struct pstore_zone_info *pstore_zone_info;
89 static pstore_blk_panic_write_op blkdev_panic_write;
98 * struct pstore_device_info - back-end pstore/blk driver structure.
100 * @total_size: The total size in bytes pstore/blk can use. It must be greater
101 * than 4096 and be multiple of 4096.
102 * @flags: Refer to macro starting with PSTORE_FLAGS defined in
103 * linux/pstore.h. It means what front-ends this device support.
104 * Zero means all backends for compatible.
105 * @read: The general read operation. Both of the function parameters
106 * @size and @offset are relative value to bock device (not the
108 * On success, the number of bytes should be returned, others
110 * @write: The same as @read, but the following error number:
111 * -EBUSY means try to write again later.
112 * -ENOMSG means to try next zone.
113 * @panic_write:The write operation only used for panic case. It's optional
114 * if you do not care panic log. The parameters are relative
116 * On success, the number of bytes should be returned, others
117 * excluding -ENOMSG mean error. -ENOMSG means to try next zone.
119 struct pstore_device_info {
120 unsigned long total_size;
122 pstore_zone_read_op read;
123 pstore_zone_write_op write;
124 pstore_zone_write_op panic_write;
127 static int psblk_register_do(struct pstore_device_info *dev)
131 if (!dev || !dev->total_size || !dev->read || !dev->write)
134 mutex_lock(&pstore_blk_lock);
136 /* someone already registered before */
137 if (pstore_zone_info) {
138 mutex_unlock(&pstore_blk_lock);
141 pstore_zone_info = kzalloc(sizeof(struct pstore_zone_info), GFP_KERNEL);
142 if (!pstore_zone_info) {
143 mutex_unlock(&pstore_blk_lock);
147 /* zero means not limit on which backends to attempt to store. */
149 dev->flags = UINT_MAX;
151 #define verify_size(name, alignsize, enabled) { \
152 long _##name_ = (enabled) ? (name) : 0; \
153 _##name_ = _##name_ <= 0 ? 0 : (_##name_ * 1024); \
154 if (_##name_ & ((alignsize) - 1)) { \
155 pr_info(#name " must align to %d\n", \
157 _##name_ = ALIGN(name, (alignsize)); \
159 name = _##name_ / 1024; \
160 pstore_zone_info->name = _##name_; \
163 verify_size(kmsg_size, 4096, dev->flags & PSTORE_FLAGS_DMESG);
164 verify_size(pmsg_size, 4096, dev->flags & PSTORE_FLAGS_PMSG);
165 verify_size(console_size, 4096, dev->flags & PSTORE_FLAGS_CONSOLE);
166 verify_size(ftrace_size, 4096, dev->flags & PSTORE_FLAGS_FTRACE);
169 pstore_zone_info->total_size = dev->total_size;
170 pstore_zone_info->max_reason = max_reason;
171 pstore_zone_info->read = dev->read;
172 pstore_zone_info->write = dev->write;
173 pstore_zone_info->panic_write = dev->panic_write;
174 pstore_zone_info->name = KBUILD_MODNAME;
175 pstore_zone_info->owner = THIS_MODULE;
177 ret = register_pstore_zone(pstore_zone_info);
179 kfree(pstore_zone_info);
180 pstore_zone_info = NULL;
182 mutex_unlock(&pstore_blk_lock);
186 static void psblk_unregister_do(struct pstore_device_info *dev)
188 mutex_lock(&pstore_blk_lock);
189 if (pstore_zone_info && pstore_zone_info->read == dev->read) {
190 unregister_pstore_zone(pstore_zone_info);
191 kfree(pstore_zone_info);
192 pstore_zone_info = NULL;
194 mutex_unlock(&pstore_blk_lock);
198 * psblk_get_bdev() - open block device
200 * @holder: Exclusive holder identifier
201 * @info: Information about bdev to fill in
203 * Return: pointer to block device on success and others on error.
205 * On success, the returned block_device has reference count of one.
207 static struct block_device *psblk_get_bdev(void *holder,
208 struct bdev_info *info)
210 struct block_device *bdev = ERR_PTR(-ENODEV);
211 fmode_t mode = FMODE_READ | FMODE_WRITE;
214 lockdep_assert_held(&pstore_blk_lock);
216 if (pstore_zone_info)
217 return ERR_PTR(-EBUSY);
220 return ERR_PTR(-ENODEV);
224 bdev = blkdev_get_by_path(blkdev, mode, holder);
228 devt = name_to_dev_t(blkdev);
230 return ERR_PTR(-ENODEV);
231 bdev = blkdev_get_by_dev(devt, mode, holder);
236 nr_sects = part_nr_sects_read(bdev->bd_part);
238 pr_err("not enough space for '%s'\n", blkdev);
239 blkdev_put(bdev, mode);
240 return ERR_PTR(-ENOSPC);
244 info->devt = bdev->bd_dev;
245 info->nr_sects = nr_sects;
246 info->start_sect = get_start_sect(bdev);
252 static void psblk_put_bdev(struct block_device *bdev, void *holder)
254 fmode_t mode = FMODE_READ | FMODE_WRITE;
256 lockdep_assert_held(&pstore_blk_lock);
263 blkdev_put(bdev, mode);
266 static ssize_t psblk_generic_blk_read(char *buf, size_t bytes, loff_t pos)
268 struct block_device *bdev = psblk_bdev;
271 struct iov_iter iter;
272 struct kvec iov = {.iov_base = buf, .iov_len = bytes};
277 memset(&file, 0, sizeof(struct file));
278 file.f_mapping = bdev->bd_inode->i_mapping;
279 file.f_flags = O_DSYNC | __O_SYNC | O_NOATIME;
280 file.f_inode = bdev->bd_inode;
281 file_ra_state_init(&file.f_ra, file.f_mapping);
283 init_sync_kiocb(&kiocb, &file);
285 iov_iter_kvec(&iter, READ, &iov, 1, bytes);
287 return generic_file_read_iter(&kiocb, &iter);
290 static ssize_t psblk_generic_blk_write(const char *buf, size_t bytes,
293 struct block_device *bdev = psblk_bdev;
294 struct iov_iter iter;
298 struct kvec iov = {.iov_base = (void *)buf, .iov_len = bytes};
303 /* Console/Ftrace backend may handle buffer until flush dirty zones */
304 if (in_interrupt() || irqs_disabled())
307 memset(&file, 0, sizeof(struct file));
308 file.f_mapping = bdev->bd_inode->i_mapping;
309 file.f_flags = O_DSYNC | __O_SYNC | O_NOATIME;
310 file.f_inode = bdev->bd_inode;
312 init_sync_kiocb(&kiocb, &file);
314 iov_iter_kvec(&iter, WRITE, &iov, 1, bytes);
316 inode_lock(bdev->bd_inode);
317 ret = generic_write_checks(&kiocb, &iter);
319 ret = generic_perform_write(&file, &iter, pos);
320 inode_unlock(bdev->bd_inode);
322 if (likely(ret > 0)) {
323 const struct file_operations f_op = {.fsync = blkdev_fsync};
327 ret = generic_write_sync(&kiocb, ret);
332 static ssize_t psblk_blk_panic_write(const char *buf, size_t size,
337 if (!blkdev_panic_write)
340 /* size and off must align to SECTOR_SIZE for block device */
341 ret = blkdev_panic_write(buf, off >> SECTOR_SHIFT,
342 size >> SECTOR_SHIFT);
346 return ret ? -EIO : size;
349 static int __register_pstore_blk(struct pstore_blk_info *info)
351 char bdev_name[BDEVNAME_SIZE];
352 struct block_device *bdev;
353 struct pstore_device_info dev;
354 struct bdev_info binfo;
355 void *holder = blkdev;
358 lockdep_assert_held(&pstore_blk_lock);
360 /* hold bdev exclusively */
361 memset(&binfo, 0, sizeof(binfo));
362 bdev = psblk_get_bdev(holder, &binfo);
364 pr_err("failed to open '%s'!\n", blkdev);
365 return PTR_ERR(bdev);
368 /* only allow driver matching the @blkdev */
369 if (!binfo.devt || MAJOR(binfo.devt) != info->major) {
370 pr_debug("invalid major %u (expect %u)\n",
371 info->major, MAJOR(binfo.devt));
376 /* psblk_bdev must be assigned before register to pstore/blk */
378 blkdev_panic_write = info->panic_write;
380 /* Copy back block device details. */
381 info->devt = binfo.devt;
382 info->nr_sects = binfo.nr_sects;
383 info->start_sect = binfo.start_sect;
385 memset(&dev, 0, sizeof(dev));
386 dev.total_size = info->nr_sects << SECTOR_SHIFT;
387 dev.flags = info->flags;
388 dev.read = psblk_generic_blk_read;
389 dev.write = psblk_generic_blk_write;
390 dev.panic_write = info->panic_write ? psblk_blk_panic_write : NULL;
392 ret = psblk_register_do(&dev);
396 bdevname(bdev, bdev_name);
397 pr_info("attached %s%s\n", bdev_name,
398 info->panic_write ? "" : " (no dedicated panic_write!)");
403 blkdev_panic_write = NULL;
404 psblk_put_bdev(bdev, holder);
409 * register_pstore_blk() - register block device to pstore/blk
411 * @info: details on the desired block device interface
415 * * Others - something error.
417 int register_pstore_blk(struct pstore_blk_info *info)
421 mutex_lock(&pstore_blk_lock);
422 ret = __register_pstore_blk(info);
423 mutex_unlock(&pstore_blk_lock);
427 EXPORT_SYMBOL_GPL(register_pstore_blk);
429 static void __unregister_pstore_blk(unsigned int major)
431 struct pstore_device_info dev = { .read = psblk_generic_blk_read };
432 void *holder = blkdev;
434 lockdep_assert_held(&pstore_blk_lock);
435 if (psblk_bdev && MAJOR(psblk_bdev->bd_dev) == major) {
436 psblk_unregister_do(&dev);
437 psblk_put_bdev(psblk_bdev, holder);
438 blkdev_panic_write = NULL;
444 * unregister_pstore_blk() - unregister block device from pstore/blk
446 * @major: the major device number of device
448 void unregister_pstore_blk(unsigned int major)
450 mutex_lock(&pstore_blk_lock);
451 __unregister_pstore_blk(major);
452 mutex_unlock(&pstore_blk_lock);
454 EXPORT_SYMBOL_GPL(unregister_pstore_blk);
456 static void __exit pstore_blk_exit(void)
458 mutex_lock(&pstore_blk_lock);
460 __unregister_pstore_blk(MAJOR(psblk_bdev->bd_dev));
461 mutex_unlock(&pstore_blk_lock);
463 module_exit(pstore_blk_exit);
465 MODULE_LICENSE("GPL");
466 MODULE_AUTHOR("WeiXiong Liao <liaoweixiong@allwinnertech.com>");
467 MODULE_AUTHOR("Kees Cook <keescook@chromium.org>");
468 MODULE_DESCRIPTION("pstore backend for block devices");