1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Implements pstore backend driver that write to block (or non-block) storage 4 * devices, using the pstore/zone API. 5 */ 6 7#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 8 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> 14#include <linux/of.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> 20 21static long kmsg_size = CONFIG_PSTORE_BLK_KMSG_SIZE; 22module_param(kmsg_size, long, 0400); 23MODULE_PARM_DESC(kmsg_size, "kmsg dump record size in kbytes"); 24 25static int max_reason = CONFIG_PSTORE_BLK_MAX_REASON; 26module_param(max_reason, int, 0400); 27MODULE_PARM_DESC(max_reason, 28 "maximum reason for kmsg dump (default 2: Oops and Panic)"); 29 30#if IS_ENABLED(CONFIG_PSTORE_PMSG) 31static long pmsg_size = CONFIG_PSTORE_BLK_PMSG_SIZE; 32#else 33static long pmsg_size = -1; 34#endif 35module_param(pmsg_size, long, 0400); 36MODULE_PARM_DESC(pmsg_size, "pmsg size in kbytes"); 37 38#if IS_ENABLED(CONFIG_PSTORE_CONSOLE) 39static long console_size = CONFIG_PSTORE_BLK_CONSOLE_SIZE; 40#else 41static long console_size = -1; 42#endif 43module_param(console_size, long, 0400); 44MODULE_PARM_DESC(console_size, "console size in kbytes"); 45 46#if IS_ENABLED(CONFIG_PSTORE_FTRACE) 47static long ftrace_size = CONFIG_PSTORE_BLK_FTRACE_SIZE; 48#else 49static long ftrace_size = -1; 50#endif 51module_param(ftrace_size, long, 0400); 52MODULE_PARM_DESC(ftrace_size, "ftrace size in kbytes"); 53 54#if IS_ENABLED(CONFIG_PSTORE_BLACKBOX) 55static long blackbox_size = CONFIG_PSTORE_BLK_BLACKBOX_SIZE; 56bool pstore_ready; 57#else 58static long blackbox_size = -1; 59#endif 60module_param(blackbox_size, long, 0400); 61MODULE_PARM_DESC(blackbox_size, "blackbox size in kbytes"); 62 63static bool best_effort; 64module_param(best_effort, bool, 0400); 65MODULE_PARM_DESC(best_effort, "use best effort to write (i.e. do not require storage driver pstore support, default: off)"); 66 67/* 68 * blkdev - the block device to use for pstore storage 69 * 70 * Usually, this will be a partition of a block device. 71 * 72 * blkdev accepts the following variants: 73 * 1) <hex_major><hex_minor> device number in hexadecimal representation, 74 * with no leading 0x, for example b302. 75 * 2) /dev/<disk_name> represents the device number of disk 76 * 3) /dev/<disk_name><decimal> represents the device number 77 * of partition - device number of disk plus the partition number 78 * 4) /dev/<disk_name>p<decimal> - same as the above, that form is 79 * used when disk name of partitioned disk ends on a digit. 80 * 5) PARTUUID=00112233-4455-6677-8899-AABBCCDDEEFF representing the 81 * unique id of a partition if the partition table provides it. 82 * The UUID may be either an EFI/GPT UUID, or refer to an MSDOS 83 * partition using the format SSSSSSSS-PP, where SSSSSSSS is a zero- 84 * filled hex representation of the 32-bit "NT disk signature", and PP 85 * is a zero-filled hex representation of the 1-based partition number. 86 * 6) PARTUUID=<UUID>/PARTNROFF=<int> to select a partition in relation to 87 * a partition with a known unique id. 88 * 7) <major>:<minor> major and minor number of the device separated by 89 * a colon. 90 */ 91static char blkdev[80] = CONFIG_PSTORE_BLK_BLKDEV; 92module_param_string(blkdev, blkdev, 80, 0400); 93MODULE_PARM_DESC(blkdev, "block device for pstore storage"); 94 95/* 96 * All globals must only be accessed under the pstore_blk_lock 97 * during the register/unregister functions. 98 */ 99static DEFINE_MUTEX(pstore_blk_lock); 100static struct block_device *psblk_bdev; 101static struct pstore_zone_info *pstore_zone_info; 102static pstore_blk_panic_write_op blkdev_panic_write; 103 104struct bdev_info { 105 dev_t devt; 106 sector_t nr_sects; 107 sector_t start_sect; 108}; 109 110#define check_size(name, alignsize) ({ \ 111 long _##name_ = (name); \ 112 _##name_ = _##name_ <= 0 ? 0 : (_##name_ * 1024); \ 113 if (_##name_ & ((alignsize) - 1)) { \ 114 pr_info(#name " must align to %d\n", \ 115 (alignsize)); \ 116 _##name_ = ALIGN(name, (alignsize)); \ 117 } \ 118 _##name_; \ 119}) 120 121static int __register_pstore_device(struct pstore_device_info *dev) 122{ 123 int ret; 124 125 lockdep_assert_held(&pstore_blk_lock); 126 127 if (!dev || !dev->total_size || !dev->read || !dev->write) 128 return -EINVAL; 129 130 /* someone already registered before */ 131 if (pstore_zone_info) 132 return -EBUSY; 133 134 pstore_zone_info = kzalloc(sizeof(struct pstore_zone_info), GFP_KERNEL); 135 if (!pstore_zone_info) 136 return -ENOMEM; 137 138 /* zero means not limit on which backends to attempt to store. */ 139 if (!dev->flags) 140 dev->flags = UINT_MAX; 141 142#define verify_size(name, alignsize, enabled) { \ 143 long _##name_; \ 144 if (enabled) \ 145 _##name_ = check_size(name, alignsize); \ 146 else \ 147 _##name_ = 0; \ 148 name = _##name_ / 1024; \ 149 pstore_zone_info->name = _##name_; \ 150 } 151 152 verify_size(kmsg_size, 4096, dev->flags & PSTORE_FLAGS_DMESG); 153 verify_size(pmsg_size, 4096, dev->flags & PSTORE_FLAGS_PMSG); 154 verify_size(console_size, 4096, dev->flags & PSTORE_FLAGS_CONSOLE); 155 verify_size(ftrace_size, 4096, dev->flags & PSTORE_FLAGS_FTRACE); 156 verify_size(blackbox_size, 4096, dev->flags & PSTORE_FLAGS_BLACKBOX); 157#undef verify_size 158 159 pstore_zone_info->total_size = dev->total_size; 160 pstore_zone_info->max_reason = max_reason; 161 pstore_zone_info->read = dev->read; 162 pstore_zone_info->write = dev->write; 163 pstore_zone_info->erase = dev->erase; 164 pstore_zone_info->panic_write = dev->panic_write; 165 pstore_zone_info->name = KBUILD_MODNAME; 166 pstore_zone_info->owner = THIS_MODULE; 167 168 ret = register_pstore_zone(pstore_zone_info); 169 if (ret) { 170 kfree(pstore_zone_info); 171 pstore_zone_info = NULL; 172 } 173 return ret; 174} 175/** 176 * register_pstore_device() - register non-block device to pstore/blk 177 * 178 * @dev: non-block device information 179 * 180 * Return: 181 * * 0 - OK 182 * * Others - something error. 183 */ 184int register_pstore_device(struct pstore_device_info *dev) 185{ 186 int ret; 187 188 mutex_lock(&pstore_blk_lock); 189 ret = __register_pstore_device(dev); 190 mutex_unlock(&pstore_blk_lock); 191 192 return ret; 193} 194EXPORT_SYMBOL_GPL(register_pstore_device); 195 196static void __unregister_pstore_device(struct pstore_device_info *dev) 197{ 198 lockdep_assert_held(&pstore_blk_lock); 199 if (pstore_zone_info && pstore_zone_info->read == dev->read) { 200 unregister_pstore_zone(pstore_zone_info); 201 kfree(pstore_zone_info); 202 pstore_zone_info = NULL; 203 } 204} 205 206/** 207 * unregister_pstore_device() - unregister non-block device from pstore/blk 208 * 209 * @dev: non-block device information 210 */ 211void unregister_pstore_device(struct pstore_device_info *dev) 212{ 213 mutex_lock(&pstore_blk_lock); 214 __unregister_pstore_device(dev); 215 mutex_unlock(&pstore_blk_lock); 216} 217EXPORT_SYMBOL_GPL(unregister_pstore_device); 218 219/** 220 * psblk_get_bdev() - open block device 221 * 222 * @holder: Exclusive holder identifier 223 * @info: Information about bdev to fill in 224 * 225 * Return: pointer to block device on success and others on error. 226 * 227 * On success, the returned block_device has reference count of one. 228 */ 229static struct block_device *psblk_get_bdev(void *holder, 230 struct bdev_info *info) 231{ 232 struct block_device *bdev = ERR_PTR(-ENODEV); 233 fmode_t mode = FMODE_READ | FMODE_WRITE; 234 sector_t nr_sects; 235 236 lockdep_assert_held(&pstore_blk_lock); 237 238 if (pstore_zone_info) 239 return ERR_PTR(-EBUSY); 240 241 if (!blkdev[0]) 242 return ERR_PTR(-ENODEV); 243 244 if (holder) 245 mode |= FMODE_EXCL; 246 bdev = blkdev_get_by_path(blkdev, mode, holder); 247 if (IS_ERR(bdev)) { 248 dev_t devt; 249 250 devt = name_to_dev_t(blkdev); 251 if (devt == 0) 252 return ERR_PTR(-ENODEV); 253 bdev = blkdev_get_by_dev(devt, mode, holder); 254 if (IS_ERR(bdev)) 255 return bdev; 256 } 257 258 nr_sects = part_nr_sects_read(bdev->bd_part); 259 if (!nr_sects) { 260 pr_err("not enough space for '%s'\n", blkdev); 261 blkdev_put(bdev, mode); 262 return ERR_PTR(-ENOSPC); 263 } 264 265 if (info) { 266 info->devt = bdev->bd_dev; 267 info->nr_sects = nr_sects; 268 info->start_sect = get_start_sect(bdev); 269 } 270 271 return bdev; 272} 273 274static void psblk_put_bdev(struct block_device *bdev, void *holder) 275{ 276 fmode_t mode = FMODE_READ | FMODE_WRITE; 277 278 lockdep_assert_held(&pstore_blk_lock); 279 280 if (!bdev) 281 return; 282 283 if (holder) 284 mode |= FMODE_EXCL; 285 blkdev_put(bdev, mode); 286} 287 288static ssize_t psblk_generic_blk_read(char *buf, size_t bytes, loff_t pos) 289{ 290 struct block_device *bdev = psblk_bdev; 291 struct file file; 292 struct kiocb kiocb; 293 struct iov_iter iter; 294 struct kvec iov = {.iov_base = buf, .iov_len = bytes}; 295 296 if (!bdev) 297 return -ENODEV; 298 299 memset(&file, 0, sizeof(struct file)); 300 file.f_mapping = bdev->bd_inode->i_mapping; 301 file.f_flags = O_DSYNC | __O_SYNC | O_NOATIME; 302 file.f_inode = bdev->bd_inode; 303 file_ra_state_init(&file.f_ra, file.f_mapping); 304 305 init_sync_kiocb(&kiocb, &file); 306 kiocb.ki_pos = pos; 307 iov_iter_kvec(&iter, READ, &iov, 1, bytes); 308 309 return generic_file_read_iter(&kiocb, &iter); 310} 311 312static ssize_t psblk_generic_blk_write(const char *buf, size_t bytes, 313 loff_t pos) 314{ 315 struct block_device *bdev = psblk_bdev; 316 struct iov_iter iter; 317 struct kiocb kiocb; 318 struct file file; 319 ssize_t ret; 320 struct kvec iov = {.iov_base = (void *)buf, .iov_len = bytes}; 321 322 if (!bdev) 323 return -ENODEV; 324 325 /* Console/Ftrace backend may handle buffer until flush dirty zones */ 326 if (in_interrupt() || irqs_disabled()) 327 return -EBUSY; 328 329 memset(&file, 0, sizeof(struct file)); 330 file.f_mapping = bdev->bd_inode->i_mapping; 331 file.f_flags = O_DSYNC | __O_SYNC | O_NOATIME; 332 file.f_inode = bdev->bd_inode; 333 334 init_sync_kiocb(&kiocb, &file); 335 kiocb.ki_pos = pos; 336 iov_iter_kvec(&iter, WRITE, &iov, 1, bytes); 337 338 inode_lock(bdev->bd_inode); 339 ret = generic_write_checks(&kiocb, &iter); 340 if (ret > 0) 341 ret = generic_perform_write(&file, &iter, pos); 342 inode_unlock(bdev->bd_inode); 343 344 if (likely(ret > 0)) { 345 const struct file_operations f_op = {.fsync = blkdev_fsync}; 346 347 file.f_op = &f_op; 348 kiocb.ki_pos += ret; 349 ret = generic_write_sync(&kiocb, ret); 350 } 351 return ret; 352} 353 354static ssize_t psblk_blk_panic_write(const char *buf, size_t size, 355 loff_t off) 356{ 357 int ret; 358 359 if (!blkdev_panic_write) 360 return -EOPNOTSUPP; 361 362 /* size and off must align to SECTOR_SIZE for block device */ 363 ret = blkdev_panic_write(buf, off >> SECTOR_SHIFT, 364 size >> SECTOR_SHIFT); 365 /* try next zone */ 366 if (ret == -ENOMSG) 367 return ret; 368 return ret ? -EIO : size; 369} 370 371static int __register_pstore_blk(struct pstore_blk_info *info) 372{ 373 char bdev_name[BDEVNAME_SIZE]; 374 struct block_device *bdev; 375 struct pstore_device_info dev; 376 struct bdev_info binfo; 377 void *holder = blkdev; 378 int ret = -ENODEV; 379 380 lockdep_assert_held(&pstore_blk_lock); 381 382 /* hold bdev exclusively */ 383 memset(&binfo, 0, sizeof(binfo)); 384 bdev = psblk_get_bdev(holder, &binfo); 385 if (IS_ERR(bdev)) { 386 pr_err("failed to open '%s'!\n", blkdev); 387 return PTR_ERR(bdev); 388 } 389 390 /* only allow driver matching the @blkdev */ 391 if (!binfo.devt || (!best_effort && 392 MAJOR(binfo.devt) != info->major)) { 393 pr_debug("invalid major %u (expect %u)\n", 394 info->major, MAJOR(binfo.devt)); 395 ret = -ENODEV; 396 goto err_put_bdev; 397 } 398 399 /* psblk_bdev must be assigned before register to pstore/blk */ 400 psblk_bdev = bdev; 401 blkdev_panic_write = info->panic_write; 402 403 /* Copy back block device details. */ 404 info->devt = binfo.devt; 405 info->nr_sects = binfo.nr_sects; 406 info->start_sect = binfo.start_sect; 407 408 memset(&dev, 0, sizeof(dev)); 409 dev.total_size = info->nr_sects << SECTOR_SHIFT; 410 dev.flags = info->flags; 411 dev.read = psblk_generic_blk_read; 412 dev.write = psblk_generic_blk_write; 413 dev.erase = NULL; 414 dev.panic_write = info->panic_write ? psblk_blk_panic_write : NULL; 415 416 ret = __register_pstore_device(&dev); 417 if (ret) 418 goto err_put_bdev; 419 420 bdevname(bdev, bdev_name); 421 pr_info("attached %s%s\n", bdev_name, 422 info->panic_write ? "" : " (no dedicated panic_write!)"); 423 return 0; 424 425err_put_bdev: 426 psblk_bdev = NULL; 427 blkdev_panic_write = NULL; 428 psblk_put_bdev(bdev, holder); 429 return ret; 430} 431 432/** 433 * register_pstore_blk() - register block device to pstore/blk 434 * 435 * @info: details on the desired block device interface 436 * 437 * Return: 438 * * 0 - OK 439 * * Others - something error. 440 */ 441int register_pstore_blk(struct pstore_blk_info *info) 442{ 443 int ret; 444 445 mutex_lock(&pstore_blk_lock); 446 ret = __register_pstore_blk(info); 447 mutex_unlock(&pstore_blk_lock); 448 449 return ret; 450} 451EXPORT_SYMBOL_GPL(register_pstore_blk); 452 453static void __unregister_pstore_blk(unsigned int major) 454{ 455 struct pstore_device_info dev = { .read = psblk_generic_blk_read }; 456 void *holder = blkdev; 457 458 lockdep_assert_held(&pstore_blk_lock); 459 if (psblk_bdev && MAJOR(psblk_bdev->bd_dev) == major) { 460 __unregister_pstore_device(&dev); 461 psblk_put_bdev(psblk_bdev, holder); 462 blkdev_panic_write = NULL; 463 psblk_bdev = NULL; 464 } 465} 466 467/** 468 * unregister_pstore_blk() - unregister block device from pstore/blk 469 * 470 * @major: the major device number of device 471 */ 472void unregister_pstore_blk(unsigned int major) 473{ 474 mutex_lock(&pstore_blk_lock); 475 __unregister_pstore_blk(major); 476 mutex_unlock(&pstore_blk_lock); 477} 478EXPORT_SYMBOL_GPL(unregister_pstore_blk); 479 480/* get information of pstore/blk */ 481int pstore_blk_get_config(struct pstore_blk_config *info) 482{ 483 strncpy(info->device, blkdev, 80); 484 info->max_reason = max_reason; 485 info->kmsg_size = check_size(kmsg_size, 4096); 486 info->pmsg_size = check_size(pmsg_size, 4096); 487 info->ftrace_size = check_size(ftrace_size, 4096); 488 info->console_size = check_size(console_size, 4096); 489 info->blackbox_size = check_size(blackbox_size, 4096); 490 491 return 0; 492} 493EXPORT_SYMBOL_GPL(pstore_blk_get_config); 494 495static int __init pstore_blk_init(void) 496{ 497 struct pstore_blk_info info = { }; 498 int ret = 0; 499 500 mutex_lock(&pstore_blk_lock); 501 if (!pstore_zone_info && best_effort && blkdev[0]) 502 ret = __register_pstore_blk(&info); 503 mutex_unlock(&pstore_blk_lock); 504 505#if IS_ENABLED(CONFIG_PSTORE_BLACKBOX) 506 if (best_effort && blkdev[0]) 507 pstore_ready = true; 508#endif 509 510 return ret; 511} 512late_initcall(pstore_blk_init); 513 514static void __exit pstore_blk_exit(void) 515{ 516 mutex_lock(&pstore_blk_lock); 517 if (psblk_bdev) 518 __unregister_pstore_blk(MAJOR(psblk_bdev->bd_dev)); 519 else { 520 struct pstore_device_info dev = { }; 521 522 if (pstore_zone_info) 523 dev.read = pstore_zone_info->read; 524 __unregister_pstore_device(&dev); 525 } 526 mutex_unlock(&pstore_blk_lock); 527} 528module_exit(pstore_blk_exit); 529 530MODULE_LICENSE("GPL"); 531MODULE_AUTHOR("WeiXiong Liao <liaoweixiong@allwinnertech.com>"); 532MODULE_AUTHOR("Kees Cook <keescook@chromium.org>"); 533MODULE_DESCRIPTION("pstore backend for block devices"); 534