^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) * Provide a pstore intermediate backend, organized into kernel memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * allocated zones that are then mapped and flushed into a single
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * contiguous region on a storage backend of some kind (block, mtd, etc).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/mount.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/printk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/pstore_zone.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/kdev_t.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/namei.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/fcntl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/uio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/writeback.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include "internal.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * struct psz_head - header of zone to flush to storage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * @sig: signature to indicate header (PSZ_SIG xor PSZONE-type value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * @datalen: length of data in @data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * @start: offset into @data where the beginning of the stored bytes begin
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * @data: zone data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) struct psz_buffer {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define PSZ_SIG (0x43474244) /* DBGC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) uint32_t sig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) atomic_t datalen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) atomic_t start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) uint8_t data[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * struct psz_kmsg_header - kmsg dump-specific header to flush to storage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * @magic: magic num for kmsg dump header
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * @time: kmsg dump trigger time
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * @compressed: whether conpressed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * @counter: kmsg dump counter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * @reason: the kmsg dump reason (e.g. oops, panic, etc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * @data: pointer to log data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * This is a sub-header for a kmsg dump, trailing after &psz_buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) struct psz_kmsg_header {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define PSTORE_KMSG_HEADER_MAGIC 0x4dfc3ae5 /* Just a random number */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) uint32_t magic;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) struct timespec64 time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) bool compressed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) uint32_t counter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) enum kmsg_dump_reason reason;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) uint8_t data[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) * struct pstore_zone - single stored buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) * @off: zone offset of storage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) * @type: front-end type for this zone
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * @name: front-end name for this zone
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) * @buffer: pointer to data buffer managed by this zone
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) * @oldbuf: pointer to old data buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) * @buffer_size: bytes in @buffer->data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * @should_recover: whether this zone should recover from storage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * @dirty: whether the data in @buffer dirty
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * zone structure in memory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) struct pstore_zone {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) loff_t off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) enum pstore_type_id type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) struct psz_buffer *buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) struct psz_buffer *oldbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) size_t buffer_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) bool should_recover;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) atomic_t dirty;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) * struct psz_context - all about running state of pstore/zone
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) * @kpszs: kmsg dump storage zones
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) * @ppsz: pmsg storage zone
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) * @cpsz: console storage zone
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) * @fpszs: ftrace storage zones
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) * @kmsg_max_cnt: max count of @kpszs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) * @kmsg_read_cnt: counter of total read kmsg dumps
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) * @kmsg_write_cnt: counter of total kmsg dump writes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) * @pmsg_read_cnt: counter of total read pmsg zone
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) * @console_read_cnt: counter of total read console zone
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) * @ftrace_max_cnt: max count of @fpszs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) * @ftrace_read_cnt: counter of max read ftrace zone
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) * @oops_counter: counter of oops dumps
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) * @panic_counter: counter of panic dumps
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) * @recovered: whether finished recovering data from storage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) * @on_panic: whether panic is happening
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) * @pstore_zone_info_lock: lock to @pstore_zone_info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) * @pstore_zone_info: information from backend
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) * @pstore: structure for pstore
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) struct psz_context {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) struct pstore_zone **kpszs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) struct pstore_zone *ppsz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) struct pstore_zone *cpsz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) struct pstore_zone **fpszs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) unsigned int kmsg_max_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) unsigned int kmsg_read_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) unsigned int kmsg_write_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) unsigned int pmsg_read_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) unsigned int console_read_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) unsigned int ftrace_max_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) unsigned int ftrace_read_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) * These counters should be calculated during recovery.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) * It records the oops/panic times after crashes rather than boots.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) unsigned int oops_counter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) unsigned int panic_counter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) atomic_t recovered;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) atomic_t on_panic;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) * pstore_zone_info_lock protects this entire structure during calls
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) * to register_pstore_zone()/unregister_pstore_zone().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) struct mutex pstore_zone_info_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) struct pstore_zone_info *pstore_zone_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) struct pstore_info pstore;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) static struct psz_context pstore_zone_cxt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) static void psz_flush_all_dirty_zones(struct work_struct *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) static DECLARE_DELAYED_WORK(psz_cleaner, psz_flush_all_dirty_zones);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) * enum psz_flush_mode - flush mode for psz_zone_write()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) * @FLUSH_NONE: do not flush to storage but update data on memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) * @FLUSH_PART: just flush part of data including meta data to storage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) * @FLUSH_META: just flush meta data of zone to storage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) * @FLUSH_ALL: flush all of zone
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) enum psz_flush_mode {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) FLUSH_NONE = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) FLUSH_PART,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) FLUSH_META,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) FLUSH_ALL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) static inline int buffer_datalen(struct pstore_zone *zone)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) return atomic_read(&zone->buffer->datalen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) static inline int buffer_start(struct pstore_zone *zone)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) return atomic_read(&zone->buffer->start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) static inline bool is_on_panic(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) return atomic_read(&pstore_zone_cxt.on_panic);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) static ssize_t psz_zone_read_buffer(struct pstore_zone *zone, char *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) size_t len, unsigned long off)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) if (!buf || !zone || !zone->buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) if (off > zone->buffer_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) len = min_t(size_t, len, zone->buffer_size - off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) memcpy(buf, zone->buffer->data + off, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) static int psz_zone_read_oldbuf(struct pstore_zone *zone, char *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) size_t len, unsigned long off)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) if (!buf || !zone || !zone->oldbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) if (off > zone->buffer_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) len = min_t(size_t, len, zone->buffer_size - off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) memcpy(buf, zone->oldbuf->data + off, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) static int psz_zone_write(struct pstore_zone *zone,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) enum psz_flush_mode flush_mode, const char *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) size_t len, unsigned long off)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) struct pstore_zone_info *info = pstore_zone_cxt.pstore_zone_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) ssize_t wcnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) ssize_t (*writeop)(const char *buf, size_t bytes, loff_t pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) size_t wlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) if (off > zone->buffer_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) wlen = min_t(size_t, len, zone->buffer_size - off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) if (buf && wlen) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) memcpy(zone->buffer->data + off, buf, wlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) atomic_set(&zone->buffer->datalen, wlen + off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) /* avoid to damage old records */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) if (!is_on_panic() && !atomic_read(&pstore_zone_cxt.recovered))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) goto dirty;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) writeop = is_on_panic() ? info->panic_write : info->write;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) if (!writeop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) goto dirty;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) switch (flush_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) case FLUSH_NONE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) if (unlikely(buf && wlen))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) goto dirty;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) case FLUSH_PART:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) wcnt = writeop((const char *)zone->buffer->data + off, wlen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) zone->off + sizeof(*zone->buffer) + off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) if (wcnt != wlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) goto dirty;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) case FLUSH_META:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) wlen = sizeof(struct psz_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) wcnt = writeop((const char *)zone->buffer, wlen, zone->off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) if (wcnt != wlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) goto dirty;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) case FLUSH_ALL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) wlen = zone->buffer_size + sizeof(*zone->buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) wcnt = writeop((const char *)zone->buffer, wlen, zone->off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) if (wcnt != wlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) goto dirty;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) dirty:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) /* no need to mark dirty if going to try next zone */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) if (wcnt == -ENOMSG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) return -ENOMSG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) atomic_set(&zone->dirty, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) /* flush dirty zones nicely */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) if (wcnt == -EBUSY && !is_on_panic())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) schedule_delayed_work(&psz_cleaner, msecs_to_jiffies(500));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) static int psz_flush_dirty_zone(struct pstore_zone *zone)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) if (unlikely(!zone))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) if (unlikely(!atomic_read(&pstore_zone_cxt.recovered)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) if (!atomic_xchg(&zone->dirty, false))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) ret = psz_zone_write(zone, FLUSH_ALL, NULL, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) atomic_set(&zone->dirty, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) static int psz_flush_dirty_zones(struct pstore_zone **zones, unsigned int cnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) int i, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) struct pstore_zone *zone;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) if (!zones)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) for (i = 0; i < cnt; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) zone = zones[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) if (!zone)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) ret = psz_flush_dirty_zone(zone);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) static int psz_move_zone(struct pstore_zone *old, struct pstore_zone *new)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) const char *data = (const char *)old->buffer->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) ret = psz_zone_write(new, FLUSH_ALL, data, buffer_datalen(old), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) atomic_set(&new->buffer->datalen, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) atomic_set(&new->dirty, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) atomic_set(&old->buffer->datalen, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) static void psz_flush_all_dirty_zones(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) struct psz_context *cxt = &pstore_zone_cxt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) if (cxt->ppsz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) ret |= psz_flush_dirty_zone(cxt->ppsz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) if (cxt->cpsz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) ret |= psz_flush_dirty_zone(cxt->cpsz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) if (cxt->kpszs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) ret |= psz_flush_dirty_zones(cxt->kpszs, cxt->kmsg_max_cnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) if (cxt->fpszs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) ret |= psz_flush_dirty_zones(cxt->fpszs, cxt->ftrace_max_cnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) if (ret && cxt->pstore_zone_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) schedule_delayed_work(&psz_cleaner, msecs_to_jiffies(1000));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) static int psz_kmsg_recover_data(struct psz_context *cxt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) struct pstore_zone_info *info = cxt->pstore_zone_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) struct pstore_zone *zone = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) struct psz_buffer *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) unsigned long i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) ssize_t rcnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) if (!info->read)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) for (i = 0; i < cxt->kmsg_max_cnt; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) zone = cxt->kpszs[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) if (unlikely(!zone))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) if (atomic_read(&zone->dirty)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) unsigned int wcnt = cxt->kmsg_write_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) struct pstore_zone *new = cxt->kpszs[wcnt];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) ret = psz_move_zone(zone, new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) pr_err("move zone from %lu to %d failed\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) i, wcnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) cxt->kmsg_write_cnt = (wcnt + 1) % cxt->kmsg_max_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) if (!zone->should_recover)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) buf = zone->buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) rcnt = info->read((char *)buf, zone->buffer_size + sizeof(*buf),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) zone->off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) if (rcnt != zone->buffer_size + sizeof(*buf))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) return (int)rcnt < 0 ? (int)rcnt : -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) static int psz_kmsg_recover_meta(struct psz_context *cxt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) struct pstore_zone_info *info = cxt->pstore_zone_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) struct pstore_zone *zone;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) size_t rcnt, len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) struct psz_buffer *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) struct psz_kmsg_header *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) struct timespec64 time = { };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) unsigned long i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) * Recover may on panic, we can't allocate any memory by kmalloc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) * So, we use local array instead.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) char buffer_header[sizeof(*buf) + sizeof(*hdr)] = {0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) if (!info->read)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) len = sizeof(*buf) + sizeof(*hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) buf = (struct psz_buffer *)buffer_header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) for (i = 0; i < cxt->kmsg_max_cnt; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) zone = cxt->kpszs[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) if (unlikely(!zone))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) rcnt = info->read((char *)buf, len, zone->off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) if (rcnt == -ENOMSG) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) pr_debug("%s with id %lu may be broken, skip\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) zone->name, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) } else if (rcnt != len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) pr_err("read %s with id %lu failed\n", zone->name, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) return (int)rcnt < 0 ? (int)rcnt : -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) if (buf->sig != zone->buffer->sig) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) pr_debug("no valid data in kmsg dump zone %lu\n", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) if (zone->buffer_size < atomic_read(&buf->datalen)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) pr_info("found overtop zone: %s: id %lu, off %lld, size %zu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) zone->name, i, zone->off,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) zone->buffer_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) hdr = (struct psz_kmsg_header *)buf->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) if (hdr->magic != PSTORE_KMSG_HEADER_MAGIC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) pr_info("found invalid zone: %s: id %lu, off %lld, size %zu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) zone->name, i, zone->off,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) zone->buffer_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) * we get the newest zone, and the next one must be the oldest
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) * or unused zone, because we do write one by one like a circle.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) if (hdr->time.tv_sec >= time.tv_sec) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) time.tv_sec = hdr->time.tv_sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) cxt->kmsg_write_cnt = (i + 1) % cxt->kmsg_max_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) if (hdr->reason == KMSG_DUMP_OOPS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) cxt->oops_counter =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) max(cxt->oops_counter, hdr->counter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) else if (hdr->reason == KMSG_DUMP_PANIC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) cxt->panic_counter =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) max(cxt->panic_counter, hdr->counter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) if (!atomic_read(&buf->datalen)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) pr_debug("found erased zone: %s: id %lu, off %lld, size %zu, datalen %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) zone->name, i, zone->off,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) zone->buffer_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) atomic_read(&buf->datalen));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) if (!is_on_panic())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) zone->should_recover = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) pr_debug("found nice zone: %s: id %lu, off %lld, size %zu, datalen %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) zone->name, i, zone->off,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) zone->buffer_size, atomic_read(&buf->datalen));
^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) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) static int psz_kmsg_recover(struct psz_context *cxt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) if (!cxt->kpszs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) ret = psz_kmsg_recover_meta(cxt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) goto recover_fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) ret = psz_kmsg_recover_data(cxt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) goto recover_fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) recover_fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) pr_debug("psz_recover_kmsg failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) static int psz_recover_zone(struct psz_context *cxt, struct pstore_zone *zone)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) struct pstore_zone_info *info = cxt->pstore_zone_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) struct psz_buffer *oldbuf, tmpbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) char *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) ssize_t rcnt, len, start, off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) if (!zone || zone->oldbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) if (is_on_panic()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) /* save data as much as possible */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) psz_flush_dirty_zone(zone);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) if (unlikely(!info->read))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) len = sizeof(struct psz_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) rcnt = info->read((char *)&tmpbuf, len, zone->off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) if (rcnt != len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) pr_debug("read zone %s failed\n", zone->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) return (int)rcnt < 0 ? (int)rcnt : -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) if (tmpbuf.sig != zone->buffer->sig) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) pr_debug("no valid data in zone %s\n", zone->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) if (zone->buffer_size < atomic_read(&tmpbuf.datalen) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) zone->buffer_size < atomic_read(&tmpbuf.start)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) pr_info("found overtop zone: %s: off %lld, size %zu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) zone->name, zone->off, zone->buffer_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) /* just keep going */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) if (!atomic_read(&tmpbuf.datalen)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) pr_debug("found erased zone: %s: off %lld, size %zu, datalen %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) zone->name, zone->off, zone->buffer_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) atomic_read(&tmpbuf.datalen));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) pr_debug("found nice zone: %s: off %lld, size %zu, datalen %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) zone->name, zone->off, zone->buffer_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) atomic_read(&tmpbuf.datalen));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) len = atomic_read(&tmpbuf.datalen) + sizeof(*oldbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) oldbuf = kzalloc(len, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) if (!oldbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) memcpy(oldbuf, &tmpbuf, sizeof(*oldbuf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) buf = (char *)oldbuf + sizeof(*oldbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) len = atomic_read(&oldbuf->datalen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) start = atomic_read(&oldbuf->start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) off = zone->off + sizeof(*oldbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) /* get part of data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) rcnt = info->read(buf, len - start, off + start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) if (rcnt != len - start) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) pr_err("read zone %s failed\n", zone->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) ret = (int)rcnt < 0 ? (int)rcnt : -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) goto free_oldbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) /* get the rest of data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) rcnt = info->read(buf + len - start, start, off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) if (rcnt != start) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) pr_err("read zone %s failed\n", zone->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) ret = (int)rcnt < 0 ? (int)rcnt : -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) goto free_oldbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) zone->oldbuf = oldbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) psz_flush_dirty_zone(zone);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) free_oldbuf:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) kfree(oldbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) static int psz_recover_zones(struct psz_context *cxt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) struct pstore_zone **zones, unsigned int cnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) struct pstore_zone *zone;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) if (!zones)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) for (i = 0; i < cnt; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) zone = zones[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) if (unlikely(!zone))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) ret = psz_recover_zone(cxt, zone);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) goto recover_fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) recover_fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) pr_debug("recover %s[%u] failed\n", zone->name, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) * psz_recovery() - recover data from storage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) * @cxt: the context of pstore/zone
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) * recovery means reading data back from storage after rebooting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) * Return: 0 on success, others on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) static inline int psz_recovery(struct psz_context *cxt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) if (atomic_read(&cxt->recovered))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) ret = psz_kmsg_recover(cxt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) ret = psz_recover_zone(cxt, cxt->ppsz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) ret = psz_recover_zone(cxt, cxt->cpsz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) ret = psz_recover_zones(cxt, cxt->fpszs, cxt->ftrace_max_cnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) if (unlikely(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) pr_err("recover failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) pr_debug("recover end!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) atomic_set(&cxt->recovered, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) static int psz_pstore_open(struct pstore_info *psi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) struct psz_context *cxt = psi->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) cxt->kmsg_read_cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) cxt->pmsg_read_cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) cxt->console_read_cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) cxt->ftrace_read_cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) static inline bool psz_old_ok(struct pstore_zone *zone)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) if (zone && zone->oldbuf && atomic_read(&zone->oldbuf->datalen))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) static inline bool psz_ok(struct pstore_zone *zone)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) if (zone && zone->buffer && buffer_datalen(zone))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) static inline int psz_kmsg_erase(struct psz_context *cxt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) struct pstore_zone *zone, struct pstore_record *record)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) struct psz_buffer *buffer = zone->buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) struct psz_kmsg_header *hdr =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) (struct psz_kmsg_header *)buffer->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) size_t size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) if (unlikely(!psz_ok(zone)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) /* this zone is already updated, no need to erase */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) if (record->count != hdr->counter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) size = buffer_datalen(zone) + sizeof(*zone->buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) atomic_set(&zone->buffer->datalen, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) if (cxt->pstore_zone_info->erase)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) return cxt->pstore_zone_info->erase(size, zone->off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) return psz_zone_write(zone, FLUSH_META, NULL, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) static inline int psz_record_erase(struct psz_context *cxt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) struct pstore_zone *zone)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) if (unlikely(!psz_old_ok(zone)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) kfree(zone->oldbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) zone->oldbuf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) * if there are new data in zone buffer, that means the old data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) * are already invalid. It is no need to flush 0 (erase) to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) * block device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) if (!buffer_datalen(zone))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) return psz_zone_write(zone, FLUSH_META, NULL, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) psz_flush_dirty_zone(zone);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) static int psz_pstore_erase(struct pstore_record *record)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) struct psz_context *cxt = record->psi->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) switch (record->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) case PSTORE_TYPE_DMESG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) if (record->id >= cxt->kmsg_max_cnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) return psz_kmsg_erase(cxt, cxt->kpszs[record->id], record);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) case PSTORE_TYPE_PMSG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) return psz_record_erase(cxt, cxt->ppsz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) case PSTORE_TYPE_CONSOLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) return psz_record_erase(cxt, cxt->cpsz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) case PSTORE_TYPE_FTRACE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) if (record->id >= cxt->ftrace_max_cnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) return psz_record_erase(cxt, cxt->fpszs[record->id]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) default: return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) static void psz_write_kmsg_hdr(struct pstore_zone *zone,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) struct pstore_record *record)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) struct psz_context *cxt = record->psi->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) struct psz_buffer *buffer = zone->buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) struct psz_kmsg_header *hdr =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) (struct psz_kmsg_header *)buffer->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) hdr->magic = PSTORE_KMSG_HEADER_MAGIC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) hdr->compressed = record->compressed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) hdr->time.tv_sec = record->time.tv_sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) hdr->time.tv_nsec = record->time.tv_nsec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) hdr->reason = record->reason;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) if (hdr->reason == KMSG_DUMP_OOPS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) hdr->counter = ++cxt->oops_counter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) else if (hdr->reason == KMSG_DUMP_PANIC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) hdr->counter = ++cxt->panic_counter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) hdr->counter = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) * In case zone is broken, which may occur to MTD device, we try each zones,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) * start at cxt->kmsg_write_cnt.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) static inline int notrace psz_kmsg_write_record(struct psz_context *cxt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) struct pstore_record *record)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) size_t size, hlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) struct pstore_zone *zone;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) for (i = 0; i < cxt->kmsg_max_cnt; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) unsigned int zonenum, len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) zonenum = (cxt->kmsg_write_cnt + i) % cxt->kmsg_max_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) zone = cxt->kpszs[zonenum];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) if (unlikely(!zone))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) return -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) /* avoid destroying old data, allocate a new one */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) len = zone->buffer_size + sizeof(*zone->buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) zone->oldbuf = zone->buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) zone->buffer = kzalloc(len, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) if (!zone->buffer) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) zone->buffer = zone->oldbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) zone->buffer->sig = zone->oldbuf->sig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) pr_debug("write %s to zone id %d\n", zone->name, zonenum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) psz_write_kmsg_hdr(zone, record);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) hlen = sizeof(struct psz_kmsg_header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) size = min_t(size_t, record->size, zone->buffer_size - hlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) ret = psz_zone_write(zone, FLUSH_ALL, record->buf, size, hlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) if (likely(!ret || ret != -ENOMSG)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) cxt->kmsg_write_cnt = zonenum + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) cxt->kmsg_write_cnt %= cxt->kmsg_max_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) /* no need to try next zone, free last zone buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) kfree(zone->oldbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) zone->oldbuf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) pr_debug("zone %u may be broken, try next dmesg zone\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) zonenum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) kfree(zone->buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) zone->buffer = zone->oldbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) zone->oldbuf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) static int notrace psz_kmsg_write(struct psz_context *cxt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) struct pstore_record *record)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) * Explicitly only take the first part of any new crash.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) * If our buffer is larger than kmsg_bytes, this can never happen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) * and if our buffer is smaller than kmsg_bytes, we don't want the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) * report split across multiple records.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) if (record->part != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) return -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) if (!cxt->kpszs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) return -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) ret = psz_kmsg_write_record(cxt, record);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) if (!ret && is_on_panic()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) /* ensure all data are flushed to storage when panic */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) pr_debug("try to flush other dirty zones\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) psz_flush_all_dirty_zones(NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) /* always return 0 as we had handled it on buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) static int notrace psz_record_write(struct pstore_zone *zone,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) struct pstore_record *record)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) size_t start, rem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) bool is_full_data = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) char *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) int cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) if (!zone || !record)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) return -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) if (atomic_read(&zone->buffer->datalen) >= zone->buffer_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) is_full_data = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) cnt = record->size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) buf = record->buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) if (unlikely(cnt > zone->buffer_size)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) buf += cnt - zone->buffer_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) cnt = zone->buffer_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) start = buffer_start(zone);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) rem = zone->buffer_size - start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) if (unlikely(rem < cnt)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) psz_zone_write(zone, FLUSH_PART, buf, rem, start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) buf += rem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) cnt -= rem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) start = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) is_full_data = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) atomic_set(&zone->buffer->start, cnt + start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) psz_zone_write(zone, FLUSH_PART, buf, cnt, start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) * psz_zone_write will set datalen as start + cnt.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) * It work if actual data length lesser than buffer size.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) * If data length greater than buffer size, pmsg will rewrite to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) * beginning of zone, which make buffer->datalen wrongly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) * So we should reset datalen as buffer size once actual data length
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) * greater than buffer size.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) if (is_full_data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) atomic_set(&zone->buffer->datalen, zone->buffer_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) psz_zone_write(zone, FLUSH_META, NULL, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) static int notrace psz_pstore_write(struct pstore_record *record)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) struct psz_context *cxt = record->psi->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) if (record->type == PSTORE_TYPE_DMESG &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) record->reason == KMSG_DUMP_PANIC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) atomic_set(&cxt->on_panic, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) * if on panic, do not write except panic records
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) * Fix case that panic_write prints log which wakes up console backend.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) if (is_on_panic() && record->type != PSTORE_TYPE_DMESG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) switch (record->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) case PSTORE_TYPE_DMESG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) return psz_kmsg_write(cxt, record);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) case PSTORE_TYPE_CONSOLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) return psz_record_write(cxt->cpsz, record);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) case PSTORE_TYPE_PMSG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) return psz_record_write(cxt->ppsz, record);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) case PSTORE_TYPE_FTRACE: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) int zonenum = smp_processor_id();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) if (!cxt->fpszs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) return -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) return psz_record_write(cxt->fpszs[zonenum], record);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) static struct pstore_zone *psz_read_next_zone(struct psz_context *cxt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) struct pstore_zone *zone = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) while (cxt->kmsg_read_cnt < cxt->kmsg_max_cnt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) zone = cxt->kpszs[cxt->kmsg_read_cnt++];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) if (psz_ok(zone))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) return zone;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) if (cxt->ftrace_read_cnt < cxt->ftrace_max_cnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) * No need psz_old_ok(). Let psz_ftrace_read() do so for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) * combination. psz_ftrace_read() should traverse over
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) * all zones in case of some zone without data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) return cxt->fpszs[cxt->ftrace_read_cnt++];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) if (cxt->pmsg_read_cnt == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) cxt->pmsg_read_cnt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) zone = cxt->ppsz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) if (psz_old_ok(zone))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) return zone;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) if (cxt->console_read_cnt == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) cxt->console_read_cnt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) zone = cxt->cpsz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) if (psz_old_ok(zone))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) return zone;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) static int psz_kmsg_read_hdr(struct pstore_zone *zone,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) struct pstore_record *record)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) struct psz_buffer *buffer = zone->buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) struct psz_kmsg_header *hdr =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) (struct psz_kmsg_header *)buffer->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) if (hdr->magic != PSTORE_KMSG_HEADER_MAGIC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) record->compressed = hdr->compressed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) record->time.tv_sec = hdr->time.tv_sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) record->time.tv_nsec = hdr->time.tv_nsec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) record->reason = hdr->reason;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) record->count = hdr->counter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) static ssize_t psz_kmsg_read(struct pstore_zone *zone,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) struct pstore_record *record)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) ssize_t size, hlen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) size = buffer_datalen(zone);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) /* Clear and skip this kmsg dump record if it has no valid header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) if (psz_kmsg_read_hdr(zone, record)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) atomic_set(&zone->buffer->datalen, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) atomic_set(&zone->dirty, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) return -ENOMSG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) size -= sizeof(struct psz_kmsg_header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) if (!record->compressed) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) char *buf = kasprintf(GFP_KERNEL, "%s: Total %d times\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) kmsg_dump_reason_str(record->reason),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) record->count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) hlen = strlen(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) record->buf = krealloc(buf, hlen + size, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) if (!record->buf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) kfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) record->buf = kmalloc(size, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) if (!record->buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) size = psz_zone_read_buffer(zone, record->buf + hlen, size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) sizeof(struct psz_kmsg_header));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) if (unlikely(size < 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) kfree(record->buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) return -ENOMSG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) return size + hlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) /* try to combine all ftrace zones */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) static ssize_t psz_ftrace_read(struct pstore_zone *zone,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) struct pstore_record *record)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) struct psz_context *cxt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) struct psz_buffer *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) if (!zone || !record)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) return -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) if (!psz_old_ok(zone))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) buf = (struct psz_buffer *)zone->oldbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) if (!buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) return -ENOMSG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) ret = pstore_ftrace_combine_log(&record->buf, &record->size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) (char *)buf->data, atomic_read(&buf->datalen));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) if (unlikely(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) cxt = record->psi->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) if (cxt->ftrace_read_cnt < cxt->ftrace_max_cnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) /* then, read next ftrace zone */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) return -ENOMSG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) record->id = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) return record->size ? record->size : -ENOMSG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) static ssize_t psz_record_read(struct pstore_zone *zone,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) struct pstore_record *record)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) size_t len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) struct psz_buffer *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) if (!zone || !record)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) return -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) buf = (struct psz_buffer *)zone->oldbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) if (!buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) return -ENOMSG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) len = atomic_read(&buf->datalen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) record->buf = kmalloc(len, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) if (!record->buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) if (unlikely(psz_zone_read_oldbuf(zone, record->buf, len, 0))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) kfree(record->buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) return -ENOMSG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) static ssize_t psz_pstore_read(struct pstore_record *record)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) struct psz_context *cxt = record->psi->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) ssize_t (*readop)(struct pstore_zone *zone,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) struct pstore_record *record);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) struct pstore_zone *zone;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) ssize_t ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) /* before read, we must recover from storage */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) ret = psz_recovery(cxt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) next_zone:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) zone = psz_read_next_zone(cxt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) if (!zone)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) record->type = zone->type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) switch (record->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) case PSTORE_TYPE_DMESG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) readop = psz_kmsg_read;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) record->id = cxt->kmsg_read_cnt - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) case PSTORE_TYPE_FTRACE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) readop = psz_ftrace_read;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) case PSTORE_TYPE_CONSOLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) case PSTORE_TYPE_PMSG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) readop = psz_record_read;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) goto next_zone;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) ret = readop(zone, record);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) if (ret == -ENOMSG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) goto next_zone;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) static struct psz_context pstore_zone_cxt = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) .pstore_zone_info_lock =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) __MUTEX_INITIALIZER(pstore_zone_cxt.pstore_zone_info_lock),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) .recovered = ATOMIC_INIT(0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) .on_panic = ATOMIC_INIT(0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) .pstore = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) .open = psz_pstore_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) .read = psz_pstore_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) .write = psz_pstore_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) .erase = psz_pstore_erase,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) static void psz_free_zone(struct pstore_zone **pszone)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) struct pstore_zone *zone = *pszone;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) if (!zone)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) kfree(zone->buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) kfree(zone);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) *pszone = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) static void psz_free_zones(struct pstore_zone ***pszones, unsigned int *cnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) struct pstore_zone **zones = *pszones;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) if (!zones)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) while (*cnt > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) (*cnt)--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) psz_free_zone(&(zones[*cnt]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) kfree(zones);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) *pszones = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) static void psz_free_all_zones(struct psz_context *cxt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) if (cxt->kpszs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) psz_free_zones(&cxt->kpszs, &cxt->kmsg_max_cnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) if (cxt->ppsz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) psz_free_zone(&cxt->ppsz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) if (cxt->cpsz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) psz_free_zone(&cxt->cpsz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) if (cxt->fpszs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) psz_free_zones(&cxt->fpszs, &cxt->ftrace_max_cnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) static struct pstore_zone *psz_init_zone(enum pstore_type_id type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) loff_t *off, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) struct pstore_zone_info *info = pstore_zone_cxt.pstore_zone_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) struct pstore_zone *zone;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) const char *name = pstore_type_to_name(type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) if (!size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) if (*off + size > info->total_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) pr_err("no room for %s (0x%zx@0x%llx over 0x%lx)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) name, size, *off, info->total_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) zone = kzalloc(sizeof(struct pstore_zone), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) if (!zone)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) zone->buffer = kmalloc(size, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) if (!zone->buffer) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) kfree(zone);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) memset(zone->buffer, 0xFF, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) zone->off = *off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) zone->name = name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) zone->type = type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) zone->buffer_size = size - sizeof(struct psz_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) zone->buffer->sig = type ^ PSZ_SIG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) zone->oldbuf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) atomic_set(&zone->dirty, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) atomic_set(&zone->buffer->datalen, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) atomic_set(&zone->buffer->start, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) *off += size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) pr_debug("pszone %s: off 0x%llx, %zu header, %zu data\n", zone->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) zone->off, sizeof(*zone->buffer), zone->buffer_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) return zone;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) static struct pstore_zone **psz_init_zones(enum pstore_type_id type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) loff_t *off, size_t total_size, ssize_t record_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) unsigned int *cnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) struct pstore_zone_info *info = pstore_zone_cxt.pstore_zone_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) struct pstore_zone **zones, *zone;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) const char *name = pstore_type_to_name(type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) int c, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) *cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) if (!total_size || !record_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) if (*off + total_size > info->total_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) pr_err("no room for zones %s (0x%zx@0x%llx over 0x%lx)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) name, total_size, *off, info->total_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) c = total_size / record_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) zones = kcalloc(c, sizeof(*zones), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) if (!zones) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) pr_err("allocate for zones %s failed\n", name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) memset(zones, 0, c * sizeof(*zones));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) for (i = 0; i < c; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) zone = psz_init_zone(type, off, record_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) if (!zone || IS_ERR(zone)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) pr_err("initialize zones %s failed\n", name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) psz_free_zones(&zones, &i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) return (void *)zone;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) zones[i] = zone;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) *cnt = c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) return zones;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) static int psz_alloc_zones(struct psz_context *cxt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) struct pstore_zone_info *info = cxt->pstore_zone_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) loff_t off = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) size_t off_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) off_size += info->pmsg_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) cxt->ppsz = psz_init_zone(PSTORE_TYPE_PMSG, &off, info->pmsg_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) if (IS_ERR(cxt->ppsz)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) err = PTR_ERR(cxt->ppsz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) cxt->ppsz = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) goto free_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) off_size += info->console_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) cxt->cpsz = psz_init_zone(PSTORE_TYPE_CONSOLE, &off,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) info->console_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) if (IS_ERR(cxt->cpsz)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) err = PTR_ERR(cxt->cpsz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) cxt->cpsz = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) goto free_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) off_size += info->ftrace_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) cxt->fpszs = psz_init_zones(PSTORE_TYPE_FTRACE, &off,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) info->ftrace_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) info->ftrace_size / nr_cpu_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) &cxt->ftrace_max_cnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) if (IS_ERR(cxt->fpszs)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) err = PTR_ERR(cxt->fpszs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) cxt->fpszs = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) goto free_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) cxt->kpszs = psz_init_zones(PSTORE_TYPE_DMESG, &off,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) info->total_size - off_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) info->kmsg_size, &cxt->kmsg_max_cnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) if (IS_ERR(cxt->kpszs)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) err = PTR_ERR(cxt->kpszs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) cxt->kpszs = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) goto free_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) free_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) psz_free_all_zones(cxt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) * register_pstore_zone() - register to pstore/zone
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) * @info: back-end driver information. See &struct pstore_zone_info.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) * Only one back-end at one time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) * Return: 0 on success, others on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) int register_pstore_zone(struct pstore_zone_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) int err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) struct psz_context *cxt = &pstore_zone_cxt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) if (info->total_size < 4096) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) pr_warn("total_size must be >= 4096\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) if (!info->kmsg_size && !info->pmsg_size && !info->console_size &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) !info->ftrace_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) pr_warn("at least one record size must be non-zero\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) if (!info->name || !info->name[0])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) #define check_size(name, size) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) if (info->name > 0 && info->name < (size)) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) pr_err(#name " must be over %d\n", (size)); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) return -EINVAL; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) if (info->name & (size - 1)) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) pr_err(#name " must be a multiple of %d\n", \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) (size)); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) return -EINVAL; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) check_size(total_size, 4096);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) check_size(kmsg_size, SECTOR_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) check_size(pmsg_size, SECTOR_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) check_size(console_size, SECTOR_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) check_size(ftrace_size, SECTOR_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) #undef check_size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) * the @read and @write must be applied.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) * if no @read, pstore may mount failed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) * if no @write, pstore do not support to remove record file.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) if (!info->read || !info->write) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) pr_err("no valid general read/write interface\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) mutex_lock(&cxt->pstore_zone_info_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) if (cxt->pstore_zone_info) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) pr_warn("'%s' already loaded: ignoring '%s'\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) cxt->pstore_zone_info->name, info->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) mutex_unlock(&cxt->pstore_zone_info_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) cxt->pstore_zone_info = info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) pr_debug("register %s with properties:\n", info->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) pr_debug("\ttotal size : %ld Bytes\n", info->total_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) pr_debug("\tkmsg size : %ld Bytes\n", info->kmsg_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) pr_debug("\tpmsg size : %ld Bytes\n", info->pmsg_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) pr_debug("\tconsole size : %ld Bytes\n", info->console_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) pr_debug("\tftrace size : %ld Bytes\n", info->ftrace_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) err = psz_alloc_zones(cxt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) pr_err("alloc zones failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) goto fail_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) if (info->kmsg_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) cxt->pstore.bufsize = cxt->kpszs[0]->buffer_size -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) sizeof(struct psz_kmsg_header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) cxt->pstore.buf = kzalloc(cxt->pstore.bufsize, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) if (!cxt->pstore.buf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) goto fail_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) cxt->pstore.data = cxt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) pr_info("registered %s as backend for", info->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) cxt->pstore.max_reason = info->max_reason;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) cxt->pstore.name = info->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) if (info->kmsg_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) cxt->pstore.flags |= PSTORE_FLAGS_DMESG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) pr_cont(" kmsg(%s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) kmsg_dump_reason_str(cxt->pstore.max_reason));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) if (cxt->pstore_zone_info->panic_write)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) pr_cont(",panic_write");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) pr_cont(")");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) if (info->pmsg_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) cxt->pstore.flags |= PSTORE_FLAGS_PMSG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) pr_cont(" pmsg");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) if (info->console_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) cxt->pstore.flags |= PSTORE_FLAGS_CONSOLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) pr_cont(" console");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) if (info->ftrace_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) cxt->pstore.flags |= PSTORE_FLAGS_FTRACE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) pr_cont(" ftrace");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) pr_cont("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) err = pstore_register(&cxt->pstore);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) pr_err("registering with pstore failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) goto fail_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) mutex_unlock(&pstore_zone_cxt.pstore_zone_info_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) fail_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) kfree(cxt->pstore.buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) cxt->pstore.buf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) cxt->pstore.bufsize = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) psz_free_all_zones(cxt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) fail_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) pstore_zone_cxt.pstore_zone_info = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) mutex_unlock(&pstore_zone_cxt.pstore_zone_info_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) EXPORT_SYMBOL_GPL(register_pstore_zone);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) * unregister_pstore_zone() - unregister to pstore/zone
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) * @info: back-end driver information. See struct pstore_zone_info.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) void unregister_pstore_zone(struct pstore_zone_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) struct psz_context *cxt = &pstore_zone_cxt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) mutex_lock(&cxt->pstore_zone_info_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) if (!cxt->pstore_zone_info) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) mutex_unlock(&cxt->pstore_zone_info_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) /* Stop incoming writes from pstore. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) pstore_unregister(&cxt->pstore);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) /* Flush any pending writes. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) psz_flush_all_dirty_zones(NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) flush_delayed_work(&psz_cleaner);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) /* Clean up allocations. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) kfree(cxt->pstore.buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) cxt->pstore.buf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) cxt->pstore.bufsize = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) cxt->pstore_zone_info = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) psz_free_all_zones(cxt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) /* Clear counters and zone state. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) cxt->oops_counter = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) cxt->panic_counter = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) atomic_set(&cxt->recovered, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) atomic_set(&cxt->on_panic, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) mutex_unlock(&cxt->pstore_zone_info_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) EXPORT_SYMBOL_GPL(unregister_pstore_zone);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) MODULE_AUTHOR("WeiXiong Liao <liaoweixiong@allwinnertech.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) MODULE_AUTHOR("Kees Cook <keescook@chromium.org>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) MODULE_DESCRIPTION("Storage Manager for pstore/blk");