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 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"); 24 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)"); 29 30 #if IS_ENABLED(CONFIG_PSTORE_PMSG) 31 static long pmsg_size = CONFIG_PSTORE_BLK_PMSG_SIZE; 32 #else 33 static long pmsg_size = -1; 34 #endif 35 module_param(pmsg_size, long, 0400); 36 MODULE_PARM_DESC(pmsg_size, "pmsg size in kbytes"); 37 38 /* 39 * blkdev - the block device to use for pstore storage 40 * 41 * Usually, this will be a partition of a block device. 42 * 43 * blkdev accepts the following variants: 44 * 1) <hex_major><hex_minor> device number in hexadecimal representation, 45 * with no leading 0x, for example b302. 46 * 2) /dev/<disk_name> represents the device number of disk 47 * 3) /dev/<disk_name><decimal> represents the device number 48 * of partition - device number of disk plus the partition number 49 * 4) /dev/<disk_name>p<decimal> - same as the above, that form is 50 * used when disk name of partitioned disk ends on a digit. 51 * 5) PARTUUID=00112233-4455-6677-8899-AABBCCDDEEFF representing the 52 * unique id of a partition if the partition table provides it. 53 * The UUID may be either an EFI/GPT UUID, or refer to an MSDOS 54 * partition using the format SSSSSSSS-PP, where SSSSSSSS is a zero- 55 * filled hex representation of the 32-bit "NT disk signature", and PP 56 * is a zero-filled hex representation of the 1-based partition number. 57 * 6) PARTUUID=<UUID>/PARTNROFF=<int> to select a partition in relation to 58 * a partition with a known unique id. 59 * 7) <major>:<minor> major and minor number of the device separated by 60 * a colon. 61 */ 62 static char blkdev[80] = CONFIG_PSTORE_BLK_BLKDEV; 63 module_param_string(blkdev, blkdev, 80, 0400); 64 MODULE_PARM_DESC(blkdev, "block device for pstore storage"); 65 66 /* 67 * All globals must only be accessed under the pstore_blk_lock 68 * during the register/unregister functions. 69 */ 70 static DEFINE_MUTEX(pstore_blk_lock); 71 static struct block_device *psblk_bdev; 72 static struct pstore_zone_info *pstore_zone_info; 73 static pstore_blk_panic_write_op blkdev_panic_write; 74 75 struct bdev_info { 76 dev_t devt; 77 sector_t nr_sects; 78 sector_t start_sect; 79 }; 80 81 /** 82 * struct pstore_device_info - back-end pstore/blk driver structure. 83 * 84 * @total_size: The total size in bytes pstore/blk can use. It must be greater 85 * than 4096 and be multiple of 4096. 86 * @flags: Refer to macro starting with PSTORE_FLAGS defined in 87 * linux/pstore.h. It means what front-ends this device support. 88 * Zero means all backends for compatible. 89 * @read: The general read operation. Both of the function parameters 90 * @size and @offset are relative value to bock device (not the 91 * whole disk). 92 * On success, the number of bytes should be returned, others 93 * means error. 94 * @write: The same as @read. 95 * @panic_write:The write operation only used for panic case. It's optional 96 * if you do not care panic log. The parameters and return value 97 * are the same as @read. 98 */ 99 struct pstore_device_info { 100 unsigned long total_size; 101 unsigned int flags; 102 pstore_zone_read_op read; 103 pstore_zone_write_op write; 104 pstore_zone_write_op panic_write; 105 }; 106 107 static int psblk_register_do(struct pstore_device_info *dev) 108 { 109 int ret; 110 111 if (!dev || !dev->total_size || !dev->read || !dev->write) 112 return -EINVAL; 113 114 mutex_lock(&pstore_blk_lock); 115 116 /* someone already registered before */ 117 if (pstore_zone_info) { 118 mutex_unlock(&pstore_blk_lock); 119 return -EBUSY; 120 } 121 pstore_zone_info = kzalloc(sizeof(struct pstore_zone_info), GFP_KERNEL); 122 if (!pstore_zone_info) { 123 mutex_unlock(&pstore_blk_lock); 124 return -ENOMEM; 125 } 126 127 /* zero means not limit on which backends to attempt to store. */ 128 if (!dev->flags) 129 dev->flags = UINT_MAX; 130 131 #define verify_size(name, alignsize, enabled) { \ 132 long _##name_ = (enabled) ? (name) : 0; \ 133 _##name_ = _##name_ <= 0 ? 0 : (_##name_ * 1024); \ 134 if (_##name_ & ((alignsize) - 1)) { \ 135 pr_info(#name " must align to %d\n", \ 136 (alignsize)); \ 137 _##name_ = ALIGN(name, (alignsize)); \ 138 } \ 139 name = _##name_ / 1024; \ 140 pstore_zone_info->name = _##name_; \ 141 } 142 143 verify_size(kmsg_size, 4096, dev->flags & PSTORE_FLAGS_DMESG); 144 verify_size(pmsg_size, 4096, dev->flags & PSTORE_FLAGS_PMSG); 145 #undef verify_size 146 147 pstore_zone_info->total_size = dev->total_size; 148 pstore_zone_info->max_reason = max_reason; 149 pstore_zone_info->read = dev->read; 150 pstore_zone_info->write = dev->write; 151 pstore_zone_info->panic_write = dev->panic_write; 152 pstore_zone_info->name = KBUILD_MODNAME; 153 pstore_zone_info->owner = THIS_MODULE; 154 155 ret = register_pstore_zone(pstore_zone_info); 156 if (ret) { 157 kfree(pstore_zone_info); 158 pstore_zone_info = NULL; 159 } 160 mutex_unlock(&pstore_blk_lock); 161 return ret; 162 } 163 164 static void psblk_unregister_do(struct pstore_device_info *dev) 165 { 166 mutex_lock(&pstore_blk_lock); 167 if (pstore_zone_info && pstore_zone_info->read == dev->read) { 168 unregister_pstore_zone(pstore_zone_info); 169 kfree(pstore_zone_info); 170 pstore_zone_info = NULL; 171 } 172 mutex_unlock(&pstore_blk_lock); 173 } 174 175 /** 176 * psblk_get_bdev() - open block device 177 * 178 * @holder: Exclusive holder identifier 179 * @info: Information about bdev to fill in 180 * 181 * Return: pointer to block device on success and others on error. 182 * 183 * On success, the returned block_device has reference count of one. 184 */ 185 static struct block_device *psblk_get_bdev(void *holder, 186 struct bdev_info *info) 187 { 188 struct block_device *bdev = ERR_PTR(-ENODEV); 189 fmode_t mode = FMODE_READ | FMODE_WRITE; 190 sector_t nr_sects; 191 192 lockdep_assert_held(&pstore_blk_lock); 193 194 if (pstore_zone_info) 195 return ERR_PTR(-EBUSY); 196 197 if (!blkdev[0]) 198 return ERR_PTR(-ENODEV); 199 200 if (holder) 201 mode |= FMODE_EXCL; 202 bdev = blkdev_get_by_path(blkdev, mode, holder); 203 if (IS_ERR(bdev)) { 204 dev_t devt; 205 206 devt = name_to_dev_t(blkdev); 207 if (devt == 0) 208 return ERR_PTR(-ENODEV); 209 bdev = blkdev_get_by_dev(devt, mode, holder); 210 if (IS_ERR(bdev)) 211 return bdev; 212 } 213 214 nr_sects = part_nr_sects_read(bdev->bd_part); 215 if (!nr_sects) { 216 pr_err("not enough space for '%s'\n", blkdev); 217 blkdev_put(bdev, mode); 218 return ERR_PTR(-ENOSPC); 219 } 220 221 if (info) { 222 info->devt = bdev->bd_dev; 223 info->nr_sects = nr_sects; 224 info->start_sect = get_start_sect(bdev); 225 } 226 227 return bdev; 228 } 229 230 static void psblk_put_bdev(struct block_device *bdev, void *holder) 231 { 232 fmode_t mode = FMODE_READ | FMODE_WRITE; 233 234 lockdep_assert_held(&pstore_blk_lock); 235 236 if (!bdev) 237 return; 238 239 if (holder) 240 mode |= FMODE_EXCL; 241 blkdev_put(bdev, mode); 242 } 243 244 static ssize_t psblk_generic_blk_read(char *buf, size_t bytes, loff_t pos) 245 { 246 struct block_device *bdev = psblk_bdev; 247 struct file file; 248 struct kiocb kiocb; 249 struct iov_iter iter; 250 struct kvec iov = {.iov_base = buf, .iov_len = bytes}; 251 252 if (!bdev) 253 return -ENODEV; 254 255 memset(&file, 0, sizeof(struct file)); 256 file.f_mapping = bdev->bd_inode->i_mapping; 257 file.f_flags = O_DSYNC | __O_SYNC | O_NOATIME; 258 file.f_inode = bdev->bd_inode; 259 file_ra_state_init(&file.f_ra, file.f_mapping); 260 261 init_sync_kiocb(&kiocb, &file); 262 kiocb.ki_pos = pos; 263 iov_iter_kvec(&iter, READ, &iov, 1, bytes); 264 265 return generic_file_read_iter(&kiocb, &iter); 266 } 267 268 static ssize_t psblk_generic_blk_write(const char *buf, size_t bytes, 269 loff_t pos) 270 { 271 struct block_device *bdev = psblk_bdev; 272 struct iov_iter iter; 273 struct kiocb kiocb; 274 struct file file; 275 ssize_t ret; 276 struct kvec iov = {.iov_base = (void *)buf, .iov_len = bytes}; 277 278 if (!bdev) 279 return -ENODEV; 280 281 /* Console/Ftrace backend may handle buffer until flush dirty zones */ 282 if (in_interrupt() || irqs_disabled()) 283 return -EBUSY; 284 285 memset(&file, 0, sizeof(struct file)); 286 file.f_mapping = bdev->bd_inode->i_mapping; 287 file.f_flags = O_DSYNC | __O_SYNC | O_NOATIME; 288 file.f_inode = bdev->bd_inode; 289 290 init_sync_kiocb(&kiocb, &file); 291 kiocb.ki_pos = pos; 292 iov_iter_kvec(&iter, WRITE, &iov, 1, bytes); 293 294 inode_lock(bdev->bd_inode); 295 ret = generic_write_checks(&kiocb, &iter); 296 if (ret > 0) 297 ret = generic_perform_write(&file, &iter, pos); 298 inode_unlock(bdev->bd_inode); 299 300 if (likely(ret > 0)) { 301 const struct file_operations f_op = {.fsync = blkdev_fsync}; 302 303 file.f_op = &f_op; 304 kiocb.ki_pos += ret; 305 ret = generic_write_sync(&kiocb, ret); 306 } 307 return ret; 308 } 309 310 static ssize_t psblk_blk_panic_write(const char *buf, size_t size, 311 loff_t off) 312 { 313 int ret; 314 315 if (!blkdev_panic_write) 316 return -EOPNOTSUPP; 317 318 /* size and off must align to SECTOR_SIZE for block device */ 319 ret = blkdev_panic_write(buf, off >> SECTOR_SHIFT, 320 size >> SECTOR_SHIFT); 321 return ret ? -EIO : size; 322 } 323 324 static int __register_pstore_blk(struct pstore_blk_info *info) 325 { 326 char bdev_name[BDEVNAME_SIZE]; 327 struct block_device *bdev; 328 struct pstore_device_info dev; 329 struct bdev_info binfo; 330 void *holder = blkdev; 331 int ret = -ENODEV; 332 333 lockdep_assert_held(&pstore_blk_lock); 334 335 /* hold bdev exclusively */ 336 memset(&binfo, 0, sizeof(binfo)); 337 bdev = psblk_get_bdev(holder, &binfo); 338 if (IS_ERR(bdev)) { 339 pr_err("failed to open '%s'!\n", blkdev); 340 return PTR_ERR(bdev); 341 } 342 343 /* only allow driver matching the @blkdev */ 344 if (!binfo.devt || MAJOR(binfo.devt) != info->major) { 345 pr_debug("invalid major %u (expect %u)\n", 346 info->major, MAJOR(binfo.devt)); 347 ret = -ENODEV; 348 goto err_put_bdev; 349 } 350 351 /* psblk_bdev must be assigned before register to pstore/blk */ 352 psblk_bdev = bdev; 353 blkdev_panic_write = info->panic_write; 354 355 /* Copy back block device details. */ 356 info->devt = binfo.devt; 357 info->nr_sects = binfo.nr_sects; 358 info->start_sect = binfo.start_sect; 359 360 memset(&dev, 0, sizeof(dev)); 361 dev.total_size = info->nr_sects << SECTOR_SHIFT; 362 dev.flags = info->flags; 363 dev.read = psblk_generic_blk_read; 364 dev.write = psblk_generic_blk_write; 365 dev.panic_write = info->panic_write ? psblk_blk_panic_write : NULL; 366 367 ret = psblk_register_do(&dev); 368 if (ret) 369 goto err_put_bdev; 370 371 bdevname(bdev, bdev_name); 372 pr_info("attached %s%s\n", bdev_name, 373 info->panic_write ? "" : " (no dedicated panic_write!)"); 374 return 0; 375 376 err_put_bdev: 377 psblk_bdev = NULL; 378 blkdev_panic_write = NULL; 379 psblk_put_bdev(bdev, holder); 380 return ret; 381 } 382 383 /** 384 * register_pstore_blk() - register block device to pstore/blk 385 * 386 * @info: details on the desired block device interface 387 * 388 * Return: 389 * * 0 - OK 390 * * Others - something error. 391 */ 392 int register_pstore_blk(struct pstore_blk_info *info) 393 { 394 int ret; 395 396 mutex_lock(&pstore_blk_lock); 397 ret = __register_pstore_blk(info); 398 mutex_unlock(&pstore_blk_lock); 399 400 return ret; 401 } 402 EXPORT_SYMBOL_GPL(register_pstore_blk); 403 404 static void __unregister_pstore_blk(unsigned int major) 405 { 406 struct pstore_device_info dev = { .read = psblk_generic_blk_read }; 407 void *holder = blkdev; 408 409 lockdep_assert_held(&pstore_blk_lock); 410 if (psblk_bdev && MAJOR(psblk_bdev->bd_dev) == major) { 411 psblk_unregister_do(&dev); 412 psblk_put_bdev(psblk_bdev, holder); 413 blkdev_panic_write = NULL; 414 psblk_bdev = NULL; 415 } 416 } 417 418 /** 419 * unregister_pstore_blk() - unregister block device from pstore/blk 420 * 421 * @major: the major device number of device 422 */ 423 void unregister_pstore_blk(unsigned int major) 424 { 425 mutex_lock(&pstore_blk_lock); 426 __unregister_pstore_blk(major); 427 mutex_unlock(&pstore_blk_lock); 428 } 429 EXPORT_SYMBOL_GPL(unregister_pstore_blk); 430 431 static void __exit pstore_blk_exit(void) 432 { 433 mutex_lock(&pstore_blk_lock); 434 if (psblk_bdev) 435 __unregister_pstore_blk(MAJOR(psblk_bdev->bd_dev)); 436 mutex_unlock(&pstore_blk_lock); 437 } 438 module_exit(pstore_blk_exit); 439 440 MODULE_LICENSE("GPL"); 441 MODULE_AUTHOR("WeiXiong Liao <liaoweixiong@allwinnertech.com>"); 442 MODULE_AUTHOR("Kees Cook <keescook@chromium.org>"); 443 MODULE_DESCRIPTION("pstore backend for block devices"); 444