Lines Matching +full:no +full:- +full:dump +full:- +full:oops

1 // SPDX-License-Identifier: GPL-2.0
26 * struct psz_buffer - header of zone to flush to storage
28 * @sig: signature to indicate header (PSZ_SIG xor PSZONE-type value)
42 * struct psz_kmsg_header - kmsg dump-specific header to flush to storage
44 * @magic: magic num for kmsg dump header
45 * @time: kmsg dump trigger time
47 * @counter: kmsg dump counter
48 * @reason: the kmsg dump reason (e.g. oops, panic, etc)
51 * This is a sub-header for a kmsg dump, trailing after &psz_buffer.
64 * struct pstore_zone - single stored buffer
67 * @type: front-end type for this zone
68 * @name: front-end name for this zone
71 * @buffer_size: bytes in @buffer->data
90 * struct psz_context - all about running state of pstore/zone
92 * @kpszs: kmsg dump storage zones
98 * @kmsg_write_cnt: counter of total kmsg dump writes
103 * @oops_counter: counter of oops dumps
125 * It records the oops/panic times after crashes rather than boots.
146 * enum psz_flush_mode - flush mode for psz_zone_write()
162 return atomic_read(&zone->buffer->datalen); in buffer_datalen()
167 return atomic_read(&zone->buffer->start); in buffer_start()
178 if (!buf || !zone || !zone->buffer) in psz_zone_read_buffer()
179 return -EINVAL; in psz_zone_read_buffer()
180 if (off > zone->buffer_size) in psz_zone_read_buffer()
181 return -EINVAL; in psz_zone_read_buffer()
182 len = min_t(size_t, len, zone->buffer_size - off); in psz_zone_read_buffer()
183 memcpy(buf, zone->buffer->data + off, len); in psz_zone_read_buffer()
190 if (!buf || !zone || !zone->oldbuf) in psz_zone_read_oldbuf()
191 return -EINVAL; in psz_zone_read_oldbuf()
192 if (off > zone->buffer_size) in psz_zone_read_oldbuf()
193 return -EINVAL; in psz_zone_read_oldbuf()
194 len = min_t(size_t, len, zone->buffer_size - off); in psz_zone_read_oldbuf()
195 memcpy(buf, zone->oldbuf->data + off, len); in psz_zone_read_oldbuf()
208 if (off > zone->buffer_size) in psz_zone_write()
209 return -EINVAL; in psz_zone_write()
211 wlen = min_t(size_t, len, zone->buffer_size - off); in psz_zone_write()
213 memcpy(zone->buffer->data + off, buf, wlen); in psz_zone_write()
214 atomic_set(&zone->buffer->datalen, wlen + off); in psz_zone_write()
221 writeop = is_on_panic() ? info->panic_write : info->write; in psz_zone_write()
231 wcnt = writeop((const char *)zone->buffer->data + off, wlen, in psz_zone_write()
232 zone->off + sizeof(*zone->buffer) + off); in psz_zone_write()
238 wcnt = writeop((const char *)zone->buffer, wlen, zone->off); in psz_zone_write()
243 wlen = zone->buffer_size + sizeof(*zone->buffer); in psz_zone_write()
244 wcnt = writeop((const char *)zone->buffer, wlen, zone->off); in psz_zone_write()
252 /* no need to mark dirty if going to try next zone */ in psz_zone_write()
253 if (wcnt == -ENOMSG) in psz_zone_write()
254 return -ENOMSG; in psz_zone_write()
255 atomic_set(&zone->dirty, true); in psz_zone_write()
257 if (wcnt == -EBUSY && !is_on_panic()) in psz_zone_write()
259 return -EBUSY; in psz_zone_write()
267 return -EINVAL; in psz_flush_dirty_zone()
270 return -EBUSY; in psz_flush_dirty_zone()
272 if (!atomic_xchg(&zone->dirty, false)) in psz_flush_dirty_zone()
277 atomic_set(&zone->dirty, true); in psz_flush_dirty_zone()
287 return -EINVAL; in psz_flush_dirty_zones()
292 return -EINVAL; in psz_flush_dirty_zones()
302 const char *data = (const char *)old->buffer->data; in psz_move_zone()
307 atomic_set(&new->buffer->datalen, 0); in psz_move_zone()
308 atomic_set(&new->dirty, false); in psz_move_zone()
311 atomic_set(&old->buffer->datalen, 0); in psz_move_zone()
320 if (cxt->ppsz) in psz_flush_all_dirty_zones()
321 ret |= psz_flush_dirty_zone(cxt->ppsz); in psz_flush_all_dirty_zones()
322 if (cxt->cpsz) in psz_flush_all_dirty_zones()
323 ret |= psz_flush_dirty_zone(cxt->cpsz); in psz_flush_all_dirty_zones()
324 if (cxt->kpszs) in psz_flush_all_dirty_zones()
325 ret |= psz_flush_dirty_zones(cxt->kpszs, cxt->kmsg_max_cnt); in psz_flush_all_dirty_zones()
326 if (cxt->fpszs) in psz_flush_all_dirty_zones()
327 ret |= psz_flush_dirty_zones(cxt->fpszs, cxt->ftrace_max_cnt); in psz_flush_all_dirty_zones()
328 if (ret && cxt->pstore_zone_info) in psz_flush_all_dirty_zones()
334 struct pstore_zone_info *info = cxt->pstore_zone_info; in psz_kmsg_recover_data()
340 if (!info->read) in psz_kmsg_recover_data()
341 return -EINVAL; in psz_kmsg_recover_data()
343 for (i = 0; i < cxt->kmsg_max_cnt; i++) { in psz_kmsg_recover_data()
344 zone = cxt->kpszs[i]; in psz_kmsg_recover_data()
346 return -EINVAL; in psz_kmsg_recover_data()
347 if (atomic_read(&zone->dirty)) { in psz_kmsg_recover_data()
348 unsigned int wcnt = cxt->kmsg_write_cnt; in psz_kmsg_recover_data()
349 struct pstore_zone *new = cxt->kpszs[wcnt]; in psz_kmsg_recover_data()
358 cxt->kmsg_write_cnt = (wcnt + 1) % cxt->kmsg_max_cnt; in psz_kmsg_recover_data()
360 if (!zone->should_recover) in psz_kmsg_recover_data()
362 buf = zone->buffer; in psz_kmsg_recover_data()
363 rcnt = info->read((char *)buf, zone->buffer_size + sizeof(*buf), in psz_kmsg_recover_data()
364 zone->off); in psz_kmsg_recover_data()
365 if (rcnt != zone->buffer_size + sizeof(*buf)) in psz_kmsg_recover_data()
366 return rcnt < 0 ? rcnt : -EIO; in psz_kmsg_recover_data()
373 struct pstore_zone_info *info = cxt->pstore_zone_info; in psz_kmsg_recover_meta()
386 if (!info->read) in psz_kmsg_recover_meta()
387 return -EINVAL; in psz_kmsg_recover_meta()
391 for (i = 0; i < cxt->kmsg_max_cnt; i++) { in psz_kmsg_recover_meta()
392 zone = cxt->kpszs[i]; in psz_kmsg_recover_meta()
394 return -EINVAL; in psz_kmsg_recover_meta()
396 rcnt = info->read((char *)buf, len, zone->off); in psz_kmsg_recover_meta()
397 if (rcnt == -ENOMSG) { in psz_kmsg_recover_meta()
399 zone->name, i); in psz_kmsg_recover_meta()
402 pr_err("read %s with id %lu failed\n", zone->name, i); in psz_kmsg_recover_meta()
403 return rcnt < 0 ? rcnt : -EIO; in psz_kmsg_recover_meta()
406 if (buf->sig != zone->buffer->sig) { in psz_kmsg_recover_meta()
407 pr_debug("no valid data in kmsg dump zone %lu\n", i); in psz_kmsg_recover_meta()
411 if (zone->buffer_size < atomic_read(&buf->datalen)) { in psz_kmsg_recover_meta()
413 zone->name, i, zone->off, in psz_kmsg_recover_meta()
414 zone->buffer_size); in psz_kmsg_recover_meta()
418 hdr = (struct psz_kmsg_header *)buf->data; in psz_kmsg_recover_meta()
419 if (hdr->magic != PSTORE_KMSG_HEADER_MAGIC) { in psz_kmsg_recover_meta()
421 zone->name, i, zone->off, in psz_kmsg_recover_meta()
422 zone->buffer_size); in psz_kmsg_recover_meta()
430 if (hdr->time.tv_sec >= time.tv_sec) { in psz_kmsg_recover_meta()
431 time.tv_sec = hdr->time.tv_sec; in psz_kmsg_recover_meta()
432 cxt->kmsg_write_cnt = (i + 1) % cxt->kmsg_max_cnt; in psz_kmsg_recover_meta()
435 if (hdr->reason == KMSG_DUMP_OOPS) in psz_kmsg_recover_meta()
436 cxt->oops_counter = in psz_kmsg_recover_meta()
437 max(cxt->oops_counter, hdr->counter); in psz_kmsg_recover_meta()
438 else if (hdr->reason == KMSG_DUMP_PANIC) in psz_kmsg_recover_meta()
439 cxt->panic_counter = in psz_kmsg_recover_meta()
440 max(cxt->panic_counter, hdr->counter); in psz_kmsg_recover_meta()
442 if (!atomic_read(&buf->datalen)) { in psz_kmsg_recover_meta()
444 zone->name, i, zone->off, in psz_kmsg_recover_meta()
445 zone->buffer_size, in psz_kmsg_recover_meta()
446 atomic_read(&buf->datalen)); in psz_kmsg_recover_meta()
451 zone->should_recover = true; in psz_kmsg_recover_meta()
453 zone->name, i, zone->off, in psz_kmsg_recover_meta()
454 zone->buffer_size, atomic_read(&buf->datalen)); in psz_kmsg_recover_meta()
464 if (!cxt->kpszs) in psz_kmsg_recover()
483 struct pstore_zone_info *info = cxt->pstore_zone_info; in psz_recover_zone()
489 if (!zone || zone->oldbuf) in psz_recover_zone()
498 if (unlikely(!info->read)) in psz_recover_zone()
499 return -EINVAL; in psz_recover_zone()
502 rcnt = info->read((char *)&tmpbuf, len, zone->off); in psz_recover_zone()
504 pr_debug("read zone %s failed\n", zone->name); in psz_recover_zone()
505 return rcnt < 0 ? rcnt : -EIO; in psz_recover_zone()
508 if (tmpbuf.sig != zone->buffer->sig) { in psz_recover_zone()
509 pr_debug("no valid data in zone %s\n", zone->name); in psz_recover_zone()
513 if (zone->buffer_size < atomic_read(&tmpbuf.datalen) || in psz_recover_zone()
514 zone->buffer_size < atomic_read(&tmpbuf.start)) { in psz_recover_zone()
516 zone->name, zone->off, zone->buffer_size); in psz_recover_zone()
523 zone->name, zone->off, zone->buffer_size, in psz_recover_zone()
529 zone->name, zone->off, zone->buffer_size, in psz_recover_zone()
535 return -ENOMEM; in psz_recover_zone()
539 len = atomic_read(&oldbuf->datalen); in psz_recover_zone()
540 start = atomic_read(&oldbuf->start); in psz_recover_zone()
541 off = zone->off + sizeof(*oldbuf); in psz_recover_zone()
544 rcnt = info->read(buf, len - start, off + start); in psz_recover_zone()
545 if (rcnt != len - start) { in psz_recover_zone()
546 pr_err("read zone %s failed\n", zone->name); in psz_recover_zone()
547 ret = rcnt < 0 ? rcnt : -EIO; in psz_recover_zone()
552 rcnt = info->read(buf + len - start, start, off); in psz_recover_zone()
554 pr_err("read zone %s failed\n", zone->name); in psz_recover_zone()
555 ret = rcnt < 0 ? rcnt : -EIO; in psz_recover_zone()
559 zone->oldbuf = oldbuf; in psz_recover_zone()
589 pr_debug("recover %s[%u] failed\n", zone->name, i); in psz_recover_zones()
594 * psz_recovery() - recover data from storage
605 if (atomic_read(&cxt->recovered)) in psz_recovery()
612 ret = psz_recover_zone(cxt, cxt->ppsz); in psz_recovery()
616 ret = psz_recover_zone(cxt, cxt->cpsz); in psz_recovery()
620 ret = psz_recover_zones(cxt, cxt->fpszs, cxt->ftrace_max_cnt); in psz_recovery()
627 atomic_set(&cxt->recovered, 1); in psz_recovery()
634 struct psz_context *cxt = psi->data; in psz_pstore_open()
636 cxt->kmsg_read_cnt = 0; in psz_pstore_open()
637 cxt->pmsg_read_cnt = 0; in psz_pstore_open()
638 cxt->console_read_cnt = 0; in psz_pstore_open()
639 cxt->ftrace_read_cnt = 0; in psz_pstore_open()
645 if (zone && zone->oldbuf && atomic_read(&zone->oldbuf->datalen)) in psz_old_ok()
652 if (zone && zone->buffer && buffer_datalen(zone)) in psz_ok()
660 struct psz_buffer *buffer = zone->buffer; in psz_kmsg_erase()
662 (struct psz_kmsg_header *)buffer->data; in psz_kmsg_erase()
668 /* this zone is already updated, no need to erase */ in psz_kmsg_erase()
669 if (record->count != hdr->counter) in psz_kmsg_erase()
672 size = buffer_datalen(zone) + sizeof(*zone->buffer); in psz_kmsg_erase()
673 atomic_set(&zone->buffer->datalen, 0); in psz_kmsg_erase()
674 if (cxt->pstore_zone_info->erase) in psz_kmsg_erase()
675 return cxt->pstore_zone_info->erase(size, zone->off); in psz_kmsg_erase()
686 kfree(zone->oldbuf); in psz_record_erase()
687 zone->oldbuf = NULL; in psz_record_erase()
690 * are already invalid. It is no need to flush 0 (erase) to in psz_record_erase()
701 struct psz_context *cxt = record->psi->data; in psz_pstore_erase()
703 switch (record->type) { in psz_pstore_erase()
705 if (record->id >= cxt->kmsg_max_cnt) in psz_pstore_erase()
706 return -EINVAL; in psz_pstore_erase()
707 return psz_kmsg_erase(cxt, cxt->kpszs[record->id], record); in psz_pstore_erase()
709 return psz_record_erase(cxt, cxt->ppsz); in psz_pstore_erase()
711 return psz_record_erase(cxt, cxt->cpsz); in psz_pstore_erase()
713 if (record->id >= cxt->ftrace_max_cnt) in psz_pstore_erase()
714 return -EINVAL; in psz_pstore_erase()
715 return psz_record_erase(cxt, cxt->fpszs[record->id]); in psz_pstore_erase()
716 default: return -EINVAL; in psz_pstore_erase()
723 struct psz_context *cxt = record->psi->data; in psz_write_kmsg_hdr()
724 struct psz_buffer *buffer = zone->buffer; in psz_write_kmsg_hdr()
726 (struct psz_kmsg_header *)buffer->data; in psz_write_kmsg_hdr()
728 hdr->magic = PSTORE_KMSG_HEADER_MAGIC; in psz_write_kmsg_hdr()
729 hdr->compressed = record->compressed; in psz_write_kmsg_hdr()
730 hdr->time.tv_sec = record->time.tv_sec; in psz_write_kmsg_hdr()
731 hdr->time.tv_nsec = record->time.tv_nsec; in psz_write_kmsg_hdr()
732 hdr->reason = record->reason; in psz_write_kmsg_hdr()
733 if (hdr->reason == KMSG_DUMP_OOPS) in psz_write_kmsg_hdr()
734 hdr->counter = ++cxt->oops_counter; in psz_write_kmsg_hdr()
735 else if (hdr->reason == KMSG_DUMP_PANIC) in psz_write_kmsg_hdr()
736 hdr->counter = ++cxt->panic_counter; in psz_write_kmsg_hdr()
738 hdr->counter = 0; in psz_write_kmsg_hdr()
743 * start at cxt->kmsg_write_cnt.
752 for (i = 0; i < cxt->kmsg_max_cnt; i++) { in psz_kmsg_write_record()
756 zonenum = (cxt->kmsg_write_cnt + i) % cxt->kmsg_max_cnt; in psz_kmsg_write_record()
757 zone = cxt->kpszs[zonenum]; in psz_kmsg_write_record()
759 return -ENOSPC; in psz_kmsg_write_record()
762 len = zone->buffer_size + sizeof(*zone->buffer); in psz_kmsg_write_record()
763 zone->oldbuf = zone->buffer; in psz_kmsg_write_record()
764 zone->buffer = kzalloc(len, GFP_ATOMIC); in psz_kmsg_write_record()
765 if (!zone->buffer) { in psz_kmsg_write_record()
766 zone->buffer = zone->oldbuf; in psz_kmsg_write_record()
767 return -ENOMEM; in psz_kmsg_write_record()
769 zone->buffer->sig = zone->oldbuf->sig; in psz_kmsg_write_record()
771 pr_debug("write %s to zone id %d\n", zone->name, zonenum); in psz_kmsg_write_record()
774 size = min_t(size_t, record->size, zone->buffer_size - hlen); in psz_kmsg_write_record()
775 ret = psz_zone_write(zone, FLUSH_ALL, record->buf, size, hlen); in psz_kmsg_write_record()
776 if (likely(!ret || ret != -ENOMSG)) { in psz_kmsg_write_record()
777 cxt->kmsg_write_cnt = zonenum + 1; in psz_kmsg_write_record()
778 cxt->kmsg_write_cnt %= cxt->kmsg_max_cnt; in psz_kmsg_write_record()
779 /* no need to try next zone, free last zone buffer */ in psz_kmsg_write_record()
780 kfree(zone->oldbuf); in psz_kmsg_write_record()
781 zone->oldbuf = NULL; in psz_kmsg_write_record()
787 kfree(zone->buffer); in psz_kmsg_write_record()
788 zone->buffer = zone->oldbuf; in psz_kmsg_write_record()
789 zone->oldbuf = NULL; in psz_kmsg_write_record()
792 return -EBUSY; in psz_kmsg_write_record()
806 if (record->part != 1) in psz_kmsg_write()
807 return -ENOSPC; in psz_kmsg_write()
809 if (!cxt->kpszs) in psz_kmsg_write()
810 return -ENOSPC; in psz_kmsg_write()
832 return -ENOSPC; in psz_record_write()
834 if (atomic_read(&zone->buffer->datalen) >= zone->buffer_size) in psz_record_write()
837 cnt = record->size; in psz_record_write()
838 buf = record->buf; in psz_record_write()
839 if (unlikely(cnt > zone->buffer_size)) { in psz_record_write()
840 buf += cnt - zone->buffer_size; in psz_record_write()
841 cnt = zone->buffer_size; in psz_record_write()
845 rem = zone->buffer_size - start; in psz_record_write()
849 cnt -= rem; in psz_record_write()
854 atomic_set(&zone->buffer->start, cnt + start); in psz_record_write()
861 * beginning of zone, which make buffer->datalen wrongly. in psz_record_write()
866 atomic_set(&zone->buffer->datalen, zone->buffer_size); in psz_record_write()
874 struct psz_context *cxt = record->psi->data; in psz_pstore_write()
876 if (record->type == PSTORE_TYPE_DMESG && in psz_pstore_write()
877 record->reason == KMSG_DUMP_PANIC) in psz_pstore_write()
878 atomic_set(&cxt->on_panic, 1); in psz_pstore_write()
884 if (is_on_panic() && record->type != PSTORE_TYPE_DMESG) in psz_pstore_write()
885 return -EBUSY; in psz_pstore_write()
887 switch (record->type) { in psz_pstore_write()
891 return psz_record_write(cxt->cpsz, record); in psz_pstore_write()
893 return psz_record_write(cxt->ppsz, record); in psz_pstore_write()
897 if (!cxt->fpszs) in psz_pstore_write()
898 return -ENOSPC; in psz_pstore_write()
899 return psz_record_write(cxt->fpszs[zonenum], record); in psz_pstore_write()
902 return -EINVAL; in psz_pstore_write()
910 while (cxt->kmsg_read_cnt < cxt->kmsg_max_cnt) { in psz_read_next_zone()
911 zone = cxt->kpszs[cxt->kmsg_read_cnt++]; in psz_read_next_zone()
916 if (cxt->ftrace_read_cnt < cxt->ftrace_max_cnt) in psz_read_next_zone()
918 * No need psz_old_ok(). Let psz_ftrace_read() do so for in psz_read_next_zone()
922 return cxt->fpszs[cxt->ftrace_read_cnt++]; in psz_read_next_zone()
924 if (cxt->pmsg_read_cnt == 0) { in psz_read_next_zone()
925 cxt->pmsg_read_cnt++; in psz_read_next_zone()
926 zone = cxt->ppsz; in psz_read_next_zone()
931 if (cxt->console_read_cnt == 0) { in psz_read_next_zone()
932 cxt->console_read_cnt++; in psz_read_next_zone()
933 zone = cxt->cpsz; in psz_read_next_zone()
944 struct psz_buffer *buffer = zone->buffer; in psz_kmsg_read_hdr()
946 (struct psz_kmsg_header *)buffer->data; in psz_kmsg_read_hdr()
948 if (hdr->magic != PSTORE_KMSG_HEADER_MAGIC) in psz_kmsg_read_hdr()
949 return -EINVAL; in psz_kmsg_read_hdr()
950 record->compressed = hdr->compressed; in psz_kmsg_read_hdr()
951 record->time.tv_sec = hdr->time.tv_sec; in psz_kmsg_read_hdr()
952 record->time.tv_nsec = hdr->time.tv_nsec; in psz_kmsg_read_hdr()
953 record->reason = hdr->reason; in psz_kmsg_read_hdr()
954 record->count = hdr->counter; in psz_kmsg_read_hdr()
964 /* Clear and skip this kmsg dump record if it has no valid header */ in psz_kmsg_read()
966 atomic_set(&zone->buffer->datalen, 0); in psz_kmsg_read()
967 atomic_set(&zone->dirty, 0); in psz_kmsg_read()
968 return -ENOMSG; in psz_kmsg_read()
970 size -= sizeof(struct psz_kmsg_header); in psz_kmsg_read()
972 if (!record->compressed) { in psz_kmsg_read()
974 kmsg_dump_reason_str(record->reason), in psz_kmsg_read()
975 record->count); in psz_kmsg_read()
977 return -ENOMEM; in psz_kmsg_read()
979 record->buf = krealloc(buf, hlen + size, GFP_KERNEL); in psz_kmsg_read()
980 if (!record->buf) { in psz_kmsg_read()
982 return -ENOMEM; in psz_kmsg_read()
985 record->buf = kmalloc(size, GFP_KERNEL); in psz_kmsg_read()
986 if (!record->buf) in psz_kmsg_read()
987 return -ENOMEM; in psz_kmsg_read()
990 size = psz_zone_read_buffer(zone, record->buf + hlen, size, in psz_kmsg_read()
993 kfree(record->buf); in psz_kmsg_read()
994 return -ENOMSG; in psz_kmsg_read()
1009 return -ENOSPC; in psz_ftrace_read()
1014 buf = (struct psz_buffer *)zone->oldbuf; in psz_ftrace_read()
1016 return -ENOMSG; in psz_ftrace_read()
1018 ret = pstore_ftrace_combine_log(&record->buf, &record->size, in psz_ftrace_read()
1019 (char *)buf->data, atomic_read(&buf->datalen)); in psz_ftrace_read()
1024 cxt = record->psi->data; in psz_ftrace_read()
1025 if (cxt->ftrace_read_cnt < cxt->ftrace_max_cnt) in psz_ftrace_read()
1027 return -ENOMSG; in psz_ftrace_read()
1028 record->id = 0; in psz_ftrace_read()
1029 return record->size ? record->size : -ENOMSG; in psz_ftrace_read()
1039 return -ENOSPC; in psz_record_read()
1041 buf = (struct psz_buffer *)zone->oldbuf; in psz_record_read()
1043 return -ENOMSG; in psz_record_read()
1045 len = atomic_read(&buf->datalen); in psz_record_read()
1046 record->buf = kmalloc(len, GFP_KERNEL); in psz_record_read()
1047 if (!record->buf) in psz_record_read()
1048 return -ENOMEM; in psz_record_read()
1050 if (unlikely(psz_zone_read_oldbuf(zone, record->buf, len, 0))) { in psz_record_read()
1051 kfree(record->buf); in psz_record_read()
1052 return -ENOMSG; in psz_record_read()
1060 struct psz_context *cxt = record->psi->data; in psz_pstore_read()
1076 record->type = zone->type; in psz_pstore_read()
1077 switch (record->type) { in psz_pstore_read()
1080 record->id = cxt->kmsg_read_cnt - 1; in psz_pstore_read()
1094 if (ret == -ENOMSG) in psz_pstore_read()
1120 kfree(zone->buffer); in psz_free_zone()
1133 (*cnt)--; in psz_free_zones()
1142 if (cxt->kpszs) in psz_free_all_zones()
1143 psz_free_zones(&cxt->kpszs, &cxt->kmsg_max_cnt); in psz_free_all_zones()
1144 if (cxt->ppsz) in psz_free_all_zones()
1145 psz_free_zone(&cxt->ppsz); in psz_free_all_zones()
1146 if (cxt->cpsz) in psz_free_all_zones()
1147 psz_free_zone(&cxt->cpsz); in psz_free_all_zones()
1148 if (cxt->fpszs) in psz_free_all_zones()
1149 psz_free_zones(&cxt->fpszs, &cxt->ftrace_max_cnt); in psz_free_all_zones()
1162 if (*off + size > info->total_size) { in psz_init_zone()
1163 pr_err("no room for %s (0x%zx@0x%llx over 0x%lx)\n", in psz_init_zone()
1164 name, size, *off, info->total_size); in psz_init_zone()
1165 return ERR_PTR(-ENOMEM); in psz_init_zone()
1170 return ERR_PTR(-ENOMEM); in psz_init_zone()
1172 zone->buffer = kmalloc(size, GFP_KERNEL); in psz_init_zone()
1173 if (!zone->buffer) { in psz_init_zone()
1175 return ERR_PTR(-ENOMEM); in psz_init_zone()
1177 memset(zone->buffer, 0xFF, size); in psz_init_zone()
1178 zone->off = *off; in psz_init_zone()
1179 zone->name = name; in psz_init_zone()
1180 zone->type = type; in psz_init_zone()
1181 zone->buffer_size = size - sizeof(struct psz_buffer); in psz_init_zone()
1182 zone->buffer->sig = type ^ PSZ_SIG; in psz_init_zone()
1183 zone->oldbuf = NULL; in psz_init_zone()
1184 atomic_set(&zone->dirty, 0); in psz_init_zone()
1185 atomic_set(&zone->buffer->datalen, 0); in psz_init_zone()
1186 atomic_set(&zone->buffer->start, 0); in psz_init_zone()
1190 pr_debug("pszone %s: off 0x%llx, %zu header, %zu data\n", zone->name, in psz_init_zone()
1191 zone->off, sizeof(*zone->buffer), zone->buffer_size); in psz_init_zone()
1208 if (*off + total_size > info->total_size) { in psz_init_zones()
1209 pr_err("no room for zones %s (0x%zx@0x%llx over 0x%lx)\n", in psz_init_zones()
1210 name, total_size, *off, info->total_size); in psz_init_zones()
1211 return ERR_PTR(-ENOMEM); in psz_init_zones()
1218 return ERR_PTR(-ENOMEM); in psz_init_zones()
1237 struct pstore_zone_info *info = cxt->pstore_zone_info; in psz_alloc_zones()
1242 off_size += info->pmsg_size; in psz_alloc_zones()
1243 cxt->ppsz = psz_init_zone(PSTORE_TYPE_PMSG, &off, info->pmsg_size); in psz_alloc_zones()
1244 if (IS_ERR(cxt->ppsz)) { in psz_alloc_zones()
1245 err = PTR_ERR(cxt->ppsz); in psz_alloc_zones()
1246 cxt->ppsz = NULL; in psz_alloc_zones()
1250 off_size += info->console_size; in psz_alloc_zones()
1251 cxt->cpsz = psz_init_zone(PSTORE_TYPE_CONSOLE, &off, in psz_alloc_zones()
1252 info->console_size); in psz_alloc_zones()
1253 if (IS_ERR(cxt->cpsz)) { in psz_alloc_zones()
1254 err = PTR_ERR(cxt->cpsz); in psz_alloc_zones()
1255 cxt->cpsz = NULL; in psz_alloc_zones()
1259 off_size += info->ftrace_size; in psz_alloc_zones()
1260 cxt->fpszs = psz_init_zones(PSTORE_TYPE_FTRACE, &off, in psz_alloc_zones()
1261 info->ftrace_size, in psz_alloc_zones()
1262 info->ftrace_size / nr_cpu_ids, in psz_alloc_zones()
1263 &cxt->ftrace_max_cnt); in psz_alloc_zones()
1264 if (IS_ERR(cxt->fpszs)) { in psz_alloc_zones()
1265 err = PTR_ERR(cxt->fpszs); in psz_alloc_zones()
1266 cxt->fpszs = NULL; in psz_alloc_zones()
1270 cxt->kpszs = psz_init_zones(PSTORE_TYPE_DMESG, &off, in psz_alloc_zones()
1271 info->total_size - off_size, in psz_alloc_zones()
1272 info->kmsg_size, &cxt->kmsg_max_cnt); in psz_alloc_zones()
1273 if (IS_ERR(cxt->kpszs)) { in psz_alloc_zones()
1274 err = PTR_ERR(cxt->kpszs); in psz_alloc_zones()
1275 cxt->kpszs = NULL; in psz_alloc_zones()
1286 * register_pstore_zone() - register to pstore/zone
1288 * @info: back-end driver information. See &struct pstore_zone_info.
1290 * Only one back-end at one time.
1296 int err = -EINVAL; in register_pstore_zone()
1299 if (info->total_size < 4096) { in register_pstore_zone()
1301 return -EINVAL; in register_pstore_zone()
1303 if (info->total_size > SZ_128M) { in register_pstore_zone()
1305 info->total_size = SZ_128M; in register_pstore_zone()
1308 if (!info->kmsg_size && !info->pmsg_size && !info->console_size && in register_pstore_zone()
1309 !info->ftrace_size) { in register_pstore_zone()
1310 pr_warn("at least one record size must be non-zero\n"); in register_pstore_zone()
1311 return -EINVAL; in register_pstore_zone()
1314 if (!info->name || !info->name[0]) in register_pstore_zone()
1315 return -EINVAL; in register_pstore_zone()
1318 if (info->name > 0 && info->name < (size)) { \ in register_pstore_zone()
1320 return -EINVAL; \ in register_pstore_zone()
1322 if (info->name & (size - 1)) { \ in register_pstore_zone()
1325 return -EINVAL; \ in register_pstore_zone()
1339 * if no @read, pstore may mount failed. in register_pstore_zone()
1340 * if no @write, pstore do not support to remove record file. in register_pstore_zone()
1342 if (!info->read || !info->write) { in register_pstore_zone()
1343 pr_err("no valid general read/write interface\n"); in register_pstore_zone()
1344 return -EINVAL; in register_pstore_zone()
1347 mutex_lock(&cxt->pstore_zone_info_lock); in register_pstore_zone()
1348 if (cxt->pstore_zone_info) { in register_pstore_zone()
1350 cxt->pstore_zone_info->name, info->name); in register_pstore_zone()
1351 mutex_unlock(&cxt->pstore_zone_info_lock); in register_pstore_zone()
1352 return -EBUSY; in register_pstore_zone()
1354 cxt->pstore_zone_info = info; in register_pstore_zone()
1356 pr_debug("register %s with properties:\n", info->name); in register_pstore_zone()
1357 pr_debug("\ttotal size : %ld Bytes\n", info->total_size); in register_pstore_zone()
1358 pr_debug("\tkmsg size : %ld Bytes\n", info->kmsg_size); in register_pstore_zone()
1359 pr_debug("\tpmsg size : %ld Bytes\n", info->pmsg_size); in register_pstore_zone()
1360 pr_debug("\tconsole size : %ld Bytes\n", info->console_size); in register_pstore_zone()
1361 pr_debug("\tftrace size : %ld Bytes\n", info->ftrace_size); in register_pstore_zone()
1369 if (info->kmsg_size) { in register_pstore_zone()
1370 cxt->pstore.bufsize = cxt->kpszs[0]->buffer_size - in register_pstore_zone()
1372 cxt->pstore.buf = kzalloc(cxt->pstore.bufsize, GFP_KERNEL); in register_pstore_zone()
1373 if (!cxt->pstore.buf) { in register_pstore_zone()
1374 err = -ENOMEM; in register_pstore_zone()
1378 cxt->pstore.data = cxt; in register_pstore_zone()
1380 pr_info("registered %s as backend for", info->name); in register_pstore_zone()
1381 cxt->pstore.max_reason = info->max_reason; in register_pstore_zone()
1382 cxt->pstore.name = info->name; in register_pstore_zone()
1383 if (info->kmsg_size) { in register_pstore_zone()
1384 cxt->pstore.flags |= PSTORE_FLAGS_DMESG; in register_pstore_zone()
1386 kmsg_dump_reason_str(cxt->pstore.max_reason)); in register_pstore_zone()
1387 if (cxt->pstore_zone_info->panic_write) in register_pstore_zone()
1391 if (info->pmsg_size) { in register_pstore_zone()
1392 cxt->pstore.flags |= PSTORE_FLAGS_PMSG; in register_pstore_zone()
1395 if (info->console_size) { in register_pstore_zone()
1396 cxt->pstore.flags |= PSTORE_FLAGS_CONSOLE; in register_pstore_zone()
1399 if (info->ftrace_size) { in register_pstore_zone()
1400 cxt->pstore.flags |= PSTORE_FLAGS_FTRACE; in register_pstore_zone()
1405 err = pstore_register(&cxt->pstore); in register_pstore_zone()
1415 kfree(cxt->pstore.buf); in register_pstore_zone()
1416 cxt->pstore.buf = NULL; in register_pstore_zone()
1417 cxt->pstore.bufsize = 0; in register_pstore_zone()
1427 * unregister_pstore_zone() - unregister to pstore/zone
1429 * @info: back-end driver information. See struct pstore_zone_info.
1435 mutex_lock(&cxt->pstore_zone_info_lock); in unregister_pstore_zone()
1436 if (!cxt->pstore_zone_info) { in unregister_pstore_zone()
1437 mutex_unlock(&cxt->pstore_zone_info_lock); in unregister_pstore_zone()
1442 pstore_unregister(&cxt->pstore); in unregister_pstore_zone()
1449 kfree(cxt->pstore.buf); in unregister_pstore_zone()
1450 cxt->pstore.buf = NULL; in unregister_pstore_zone()
1451 cxt->pstore.bufsize = 0; in unregister_pstore_zone()
1452 cxt->pstore_zone_info = NULL; in unregister_pstore_zone()
1457 cxt->oops_counter = 0; in unregister_pstore_zone()
1458 cxt->panic_counter = 0; in unregister_pstore_zone()
1459 atomic_set(&cxt->recovered, 0); in unregister_pstore_zone()
1460 atomic_set(&cxt->on_panic, 0); in unregister_pstore_zone()
1462 mutex_unlock(&cxt->pstore_zone_info_lock); in unregister_pstore_zone()