Lines Matching +full:max +full:- +full:reason

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
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.
59 enum kmsg_dump_reason reason; member
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
96 * @kmsg_max_cnt: max count of @kpszs
101 * @ftrace_max_cnt: max count of @fpszs
102 * @ftrace_read_cnt: counter of max read ftrace zone
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()
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()
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()
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()
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()
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()
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()
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 record->buf = krealloc(buf, hlen + size, GFP_KERNEL); in psz_kmsg_read()
978 if (!record->buf) { in psz_kmsg_read()
980 return -ENOMEM; in psz_kmsg_read()
983 record->buf = kmalloc(size, GFP_KERNEL); in psz_kmsg_read()
984 if (!record->buf) in psz_kmsg_read()
985 return -ENOMEM; in psz_kmsg_read()
988 size = psz_zone_read_buffer(zone, record->buf + hlen, size, in psz_kmsg_read()
991 kfree(record->buf); in psz_kmsg_read()
992 return -ENOMSG; in psz_kmsg_read()
1007 return -ENOSPC; in psz_ftrace_read()
1012 buf = (struct psz_buffer *)zone->oldbuf; in psz_ftrace_read()
1014 return -ENOMSG; in psz_ftrace_read()
1016 ret = pstore_ftrace_combine_log(&record->buf, &record->size, in psz_ftrace_read()
1017 (char *)buf->data, atomic_read(&buf->datalen)); in psz_ftrace_read()
1022 cxt = record->psi->data; in psz_ftrace_read()
1023 if (cxt->ftrace_read_cnt < cxt->ftrace_max_cnt) in psz_ftrace_read()
1025 return -ENOMSG; in psz_ftrace_read()
1026 record->id = 0; in psz_ftrace_read()
1027 return record->size ? record->size : -ENOMSG; in psz_ftrace_read()
1037 return -ENOSPC; in psz_record_read()
1039 buf = (struct psz_buffer *)zone->oldbuf; in psz_record_read()
1041 return -ENOMSG; in psz_record_read()
1043 len = atomic_read(&buf->datalen); in psz_record_read()
1044 record->buf = kmalloc(len, GFP_KERNEL); in psz_record_read()
1045 if (!record->buf) in psz_record_read()
1046 return -ENOMEM; in psz_record_read()
1048 if (unlikely(psz_zone_read_oldbuf(zone, record->buf, len, 0))) { in psz_record_read()
1049 kfree(record->buf); in psz_record_read()
1050 return -ENOMSG; in psz_record_read()
1058 struct psz_context *cxt = record->psi->data; in psz_pstore_read()
1074 record->type = zone->type; in psz_pstore_read()
1075 switch (record->type) { in psz_pstore_read()
1078 record->id = cxt->kmsg_read_cnt - 1; in psz_pstore_read()
1092 if (ret == -ENOMSG) in psz_pstore_read()
1118 kfree(zone->buffer); in psz_free_zone()
1131 (*cnt)--; in psz_free_zones()
1140 if (cxt->kpszs) in psz_free_all_zones()
1141 psz_free_zones(&cxt->kpszs, &cxt->kmsg_max_cnt); in psz_free_all_zones()
1142 if (cxt->ppsz) in psz_free_all_zones()
1143 psz_free_zone(&cxt->ppsz); in psz_free_all_zones()
1144 if (cxt->cpsz) in psz_free_all_zones()
1145 psz_free_zone(&cxt->cpsz); in psz_free_all_zones()
1146 if (cxt->fpszs) in psz_free_all_zones()
1147 psz_free_zones(&cxt->fpszs, &cxt->ftrace_max_cnt); in psz_free_all_zones()
1160 if (*off + size > info->total_size) { in psz_init_zone()
1162 name, size, *off, info->total_size); in psz_init_zone()
1163 return ERR_PTR(-ENOMEM); in psz_init_zone()
1168 return ERR_PTR(-ENOMEM); in psz_init_zone()
1170 zone->buffer = kmalloc(size, GFP_KERNEL); in psz_init_zone()
1171 if (!zone->buffer) { in psz_init_zone()
1173 return ERR_PTR(-ENOMEM); in psz_init_zone()
1175 memset(zone->buffer, 0xFF, size); in psz_init_zone()
1176 zone->off = *off; in psz_init_zone()
1177 zone->name = name; in psz_init_zone()
1178 zone->type = type; in psz_init_zone()
1179 zone->buffer_size = size - sizeof(struct psz_buffer); in psz_init_zone()
1180 zone->buffer->sig = type ^ PSZ_SIG; in psz_init_zone()
1181 zone->oldbuf = NULL; in psz_init_zone()
1182 atomic_set(&zone->dirty, 0); in psz_init_zone()
1183 atomic_set(&zone->buffer->datalen, 0); in psz_init_zone()
1184 atomic_set(&zone->buffer->start, 0); in psz_init_zone()
1188 pr_debug("pszone %s: off 0x%llx, %zu header, %zu data\n", zone->name, in psz_init_zone()
1189 zone->off, sizeof(*zone->buffer), zone->buffer_size); in psz_init_zone()
1206 if (*off + total_size > info->total_size) { in psz_init_zones()
1208 name, total_size, *off, info->total_size); in psz_init_zones()
1209 return ERR_PTR(-ENOMEM); in psz_init_zones()
1216 return ERR_PTR(-ENOMEM); in psz_init_zones()
1236 struct pstore_zone_info *info = cxt->pstore_zone_info; in psz_alloc_zones()
1241 off_size += info->pmsg_size; in psz_alloc_zones()
1242 cxt->ppsz = psz_init_zone(PSTORE_TYPE_PMSG, &off, info->pmsg_size); in psz_alloc_zones()
1243 if (IS_ERR(cxt->ppsz)) { in psz_alloc_zones()
1244 err = PTR_ERR(cxt->ppsz); in psz_alloc_zones()
1245 cxt->ppsz = NULL; in psz_alloc_zones()
1249 off_size += info->console_size; in psz_alloc_zones()
1250 cxt->cpsz = psz_init_zone(PSTORE_TYPE_CONSOLE, &off, in psz_alloc_zones()
1251 info->console_size); in psz_alloc_zones()
1252 if (IS_ERR(cxt->cpsz)) { in psz_alloc_zones()
1253 err = PTR_ERR(cxt->cpsz); in psz_alloc_zones()
1254 cxt->cpsz = NULL; in psz_alloc_zones()
1258 off_size += info->ftrace_size; in psz_alloc_zones()
1259 cxt->fpszs = psz_init_zones(PSTORE_TYPE_FTRACE, &off, in psz_alloc_zones()
1260 info->ftrace_size, in psz_alloc_zones()
1261 info->ftrace_size / nr_cpu_ids, in psz_alloc_zones()
1262 &cxt->ftrace_max_cnt); in psz_alloc_zones()
1263 if (IS_ERR(cxt->fpszs)) { in psz_alloc_zones()
1264 err = PTR_ERR(cxt->fpszs); in psz_alloc_zones()
1265 cxt->fpszs = NULL; in psz_alloc_zones()
1269 cxt->kpszs = psz_init_zones(PSTORE_TYPE_DMESG, &off, in psz_alloc_zones()
1270 info->total_size - off_size, in psz_alloc_zones()
1271 info->kmsg_size, &cxt->kmsg_max_cnt); in psz_alloc_zones()
1272 if (IS_ERR(cxt->kpszs)) { in psz_alloc_zones()
1273 err = PTR_ERR(cxt->kpszs); in psz_alloc_zones()
1274 cxt->kpszs = NULL; in psz_alloc_zones()
1285 * register_pstore_zone() - register to pstore/zone
1287 * @info: back-end driver information. See &struct pstore_zone_info.
1289 * Only one back-end at one time.
1295 int err = -EINVAL; in register_pstore_zone()
1298 if (info->total_size < 4096) { in register_pstore_zone()
1300 return -EINVAL; in register_pstore_zone()
1302 if (info->total_size > SZ_128M) { in register_pstore_zone()
1304 info->total_size = SZ_128M; in register_pstore_zone()
1307 if (!info->kmsg_size && !info->pmsg_size && !info->console_size && in register_pstore_zone()
1308 !info->ftrace_size) { in register_pstore_zone()
1309 pr_warn("at least one record size must be non-zero\n"); in register_pstore_zone()
1310 return -EINVAL; in register_pstore_zone()
1313 if (!info->name || !info->name[0]) in register_pstore_zone()
1314 return -EINVAL; in register_pstore_zone()
1317 if (info->name > 0 && info->name < (size)) { \ in register_pstore_zone()
1319 return -EINVAL; \ in register_pstore_zone()
1321 if (info->name & (size - 1)) { \ in register_pstore_zone()
1324 return -EINVAL; \ in register_pstore_zone()
1341 if (!info->read || !info->write) { in register_pstore_zone()
1343 return -EINVAL; in register_pstore_zone()
1346 mutex_lock(&cxt->pstore_zone_info_lock); in register_pstore_zone()
1347 if (cxt->pstore_zone_info) { in register_pstore_zone()
1349 cxt->pstore_zone_info->name, info->name); in register_pstore_zone()
1350 mutex_unlock(&cxt->pstore_zone_info_lock); in register_pstore_zone()
1351 return -EBUSY; in register_pstore_zone()
1353 cxt->pstore_zone_info = info; in register_pstore_zone()
1355 pr_debug("register %s with properties:\n", info->name); in register_pstore_zone()
1356 pr_debug("\ttotal size : %ld Bytes\n", info->total_size); in register_pstore_zone()
1357 pr_debug("\tkmsg size : %ld Bytes\n", info->kmsg_size); in register_pstore_zone()
1358 pr_debug("\tpmsg size : %ld Bytes\n", info->pmsg_size); in register_pstore_zone()
1359 pr_debug("\tconsole size : %ld Bytes\n", info->console_size); in register_pstore_zone()
1360 pr_debug("\tftrace size : %ld Bytes\n", info->ftrace_size); in register_pstore_zone()
1368 if (info->kmsg_size) { in register_pstore_zone()
1369 cxt->pstore.bufsize = cxt->kpszs[0]->buffer_size - in register_pstore_zone()
1371 cxt->pstore.buf = kzalloc(cxt->pstore.bufsize, GFP_KERNEL); in register_pstore_zone()
1372 if (!cxt->pstore.buf) { in register_pstore_zone()
1373 err = -ENOMEM; in register_pstore_zone()
1377 cxt->pstore.data = cxt; in register_pstore_zone()
1379 pr_info("registered %s as backend for", info->name); in register_pstore_zone()
1380 cxt->pstore.max_reason = info->max_reason; in register_pstore_zone()
1381 cxt->pstore.name = info->name; in register_pstore_zone()
1382 if (info->kmsg_size) { in register_pstore_zone()
1383 cxt->pstore.flags |= PSTORE_FLAGS_DMESG; in register_pstore_zone()
1385 kmsg_dump_reason_str(cxt->pstore.max_reason)); in register_pstore_zone()
1386 if (cxt->pstore_zone_info->panic_write) in register_pstore_zone()
1390 if (info->pmsg_size) { in register_pstore_zone()
1391 cxt->pstore.flags |= PSTORE_FLAGS_PMSG; in register_pstore_zone()
1394 if (info->console_size) { in register_pstore_zone()
1395 cxt->pstore.flags |= PSTORE_FLAGS_CONSOLE; in register_pstore_zone()
1398 if (info->ftrace_size) { in register_pstore_zone()
1399 cxt->pstore.flags |= PSTORE_FLAGS_FTRACE; in register_pstore_zone()
1404 err = pstore_register(&cxt->pstore); in register_pstore_zone()
1414 kfree(cxt->pstore.buf); in register_pstore_zone()
1415 cxt->pstore.buf = NULL; in register_pstore_zone()
1416 cxt->pstore.bufsize = 0; in register_pstore_zone()
1426 * unregister_pstore_zone() - unregister to pstore/zone
1428 * @info: back-end driver information. See struct pstore_zone_info.
1434 mutex_lock(&cxt->pstore_zone_info_lock); in unregister_pstore_zone()
1435 if (!cxt->pstore_zone_info) { in unregister_pstore_zone()
1436 mutex_unlock(&cxt->pstore_zone_info_lock); in unregister_pstore_zone()
1441 pstore_unregister(&cxt->pstore); in unregister_pstore_zone()
1448 kfree(cxt->pstore.buf); in unregister_pstore_zone()
1449 cxt->pstore.buf = NULL; in unregister_pstore_zone()
1450 cxt->pstore.bufsize = 0; in unregister_pstore_zone()
1451 cxt->pstore_zone_info = NULL; in unregister_pstore_zone()
1456 cxt->oops_counter = 0; in unregister_pstore_zone()
1457 cxt->panic_counter = 0; in unregister_pstore_zone()
1458 atomic_set(&cxt->recovered, 0); in unregister_pstore_zone()
1459 atomic_set(&cxt->on_panic, 0); in unregister_pstore_zone()
1461 mutex_unlock(&cxt->pstore_zone_info_lock); in unregister_pstore_zone()