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