/* * Read all the records from the persistent store. Create * files in our filesystem. Don't warn about -EEXIST errors * when we are re-scanning the backing store looking to add new * error records. */ void pstore_get_records(int quiet) { struct pstore_info *psi = psinfo; char *buf = NULL; ssize_t size; u64 id; int count; enum pstore_type_id type; struct timespec time; int failed = 0, rc; int made_annotate_file = 0; if (!psi) return; mutex_lock(&psi->read_mutex); if (psi->open && psi->open(psi)) goto out; while ((size = psi->read(&id, &type, &count, &time, &buf, psi)) > 0) { rc = pstore_mkfile(type, psi->name, id, count, buf, (size_t)size, time, psi); kfree(buf); buf = NULL; if (rc && (rc != -EEXIST || !quiet)) failed++; pr_info("Found record type %d, psi name %s\n", type, psi->name); if (type == PSTORE_TYPE_ANNOTATE) made_annotate_file = 1; } /* * If there isn't annotation file created (e.g in cold reboot * or power up), create it now, since we need app to make annotation * during bootup. */ if (!made_annotate_file) { rc = pstore_mkfile(PSTORE_TYPE_ANNOTATE, psi->name, 0, 0, NULL, 0, time, psi); if (rc) pr_err("annotate-%s can't be created\n", psi->name); else pr_info("Created annotate-%s\n", psi->name); } if (psi->close) psi->close(psi); out: mutex_unlock(&psi->read_mutex); if (failed) printk(KERN_WARNING "pstore: failed to load %d record(s) from '%s'\n", failed, psi->name); }
/* * Read all the records from the persistent store. Create * files in our filesystem. Don't warn about -EEXIST errors * when we are re-scanning the backing store looking to add new * error records. */ void pstore_get_records(int quiet) { struct pstore_info *psi = psinfo; char *buf = NULL; ssize_t size; u64 id; enum pstore_type_id type; struct timespec time; int failed = 0, rc; if (!psi) return; mutex_lock(&psi->read_mutex); rc = psi->open(psi); if (rc) goto out; while ((size = psi->read(&id, &type, &time, &buf, psi)) > 0) { rc = pstore_mkfile(type, psi->name, id, buf, (size_t)size, time, psi); kfree(buf); buf = NULL; if (rc && (rc != -EEXIST || !quiet)) failed++; } psi->close(psi); out: mutex_unlock(&psi->read_mutex); if (failed) printk(KERN_WARNING "pstore: failed to load %d record(s) from '%s'\n", failed, psi->name); }
/* * Read all the records from the persistent store. Create and * file files in our filesystem. */ void pstore_get_records(void) { struct pstore_info *psi = psinfo; ssize_t size; u64 id; enum pstore_type_id type; struct timespec time; int failed = 0, rc; if (!psi) return; mutex_lock(&psinfo->buf_mutex); rc = psi->open(psi); if (rc) goto out; while ((size = psi->read(&id, &type, &time, psi)) > 0) { if (pstore_mkfile(type, psi->name, id, psi->buf, (size_t)size, time, psi)) failed++; } psi->close(psi); out: mutex_unlock(&psinfo->buf_mutex); if (failed) printk(KERN_WARNING "pstore: failed to load %d record(s) from '%s'\n", failed, psi->name); }
/* * Read all the records from the persistent store. Create * files in our filesystem. Don't warn about -EEXIST errors * when we are re-scanning the backing store looking to add new * error records. */ void pstore_get_records(int quiet) { struct pstore_info *psi = psinfo; char *buf = NULL; ssize_t size; u64 id; int count; enum pstore_type_id type; struct timespec time; int failed = 0, rc; bool compressed; int unzipped_len = -1; if (!psi) return; mutex_lock(&psi->read_mutex); if (psi->open && psi->open(psi)) goto out; while ((size = psi->read(&id, &type, &count, &time, &buf, &compressed, psi)) > 0) { if (compressed && (type == PSTORE_TYPE_DMESG)) { if (big_oops_buf) unzipped_len = pstore_decompress(buf, big_oops_buf, size, big_oops_buf_sz); if (unzipped_len > 0) { kfree(buf); buf = big_oops_buf; size = unzipped_len; compressed = false; } else { pr_err("decompression failed;returned %d\n", unzipped_len); compressed = true; } } rc = pstore_mkfile(type, psi->name, id, count, buf, compressed, (size_t)size, time, psi); if (unzipped_len < 0) { /* Free buffer other than big oops */ kfree(buf); buf = NULL; } else unzipped_len = -1; if (rc && (rc != -EEXIST || !quiet)) failed++; } if (psi->close) psi->close(psi); out: mutex_unlock(&psi->read_mutex); if (failed) pr_warn("failed to load %d record(s) from '%s'\n", failed, psi->name); }
/* * Read all the records from one persistent store backend. Create * files in our filesystem. Don't warn about -EEXIST errors * when we are re-scanning the backing store looking to add new * error records. */ void pstore_get_backend_records(struct pstore_info *psi, struct dentry *root, int quiet) { int failed = 0; unsigned int stop_loop = 65536; if (!psi || !root) return; mutex_lock(&psi->read_mutex); if (psi->open && psi->open(psi)) goto out; /* * Backend callback read() allocates record.buf. decompress_record() * may reallocate record.buf. On success, pstore_mkfile() will keep * the record.buf, so free it only on failure. */ for (; stop_loop; stop_loop--) { struct pstore_record *record; int rc; record = kzalloc(sizeof(*record), GFP_KERNEL); if (!record) { pr_err("out of memory creating record\n"); break; } pstore_record_init(record, psi); record->size = psi->read(record); /* No more records left in backend? */ if (record->size <= 0) { kfree(record); break; } decompress_record(record); rc = pstore_mkfile(root, record); if (rc) { /* pstore_mkfile() did not take record, so free it. */ kfree(record->buf); kfree(record); if (rc != -EEXIST || !quiet) failed++; } } if (psi->close) psi->close(psi); out: mutex_unlock(&psi->read_mutex); if (failed) pr_warn("failed to create %d record(s) from '%s'\n", failed, psi->name); if (!stop_loop) pr_err("looping? Too many records seen from '%s'\n", psi->name); }
/* * callback from kmsg_dump. (s2,l2) has the most recently * written bytes, older bytes are in (s1,l1). Save as much * as we can from the end of the buffer. */ static void pstore_dump(struct kmsg_dumper *dumper, enum kmsg_dump_reason reason, const char *s1, unsigned long l1, const char *s2, unsigned long l2) { unsigned long s1_start, s2_start; unsigned long l1_cpy, l2_cpy; unsigned long size, total = 0; char *dst, *why; u64 id; int hsize; unsigned int part = 1; if (reason < ARRAY_SIZE(reason_str)) why = reason_str[reason]; else why = "Unknown"; mutex_lock(&psinfo->buf_mutex); oopscount++; while (total < kmsg_bytes) { dst = psinfo->buf; hsize = sprintf(dst, "%s#%d Part%d\n", why, oopscount, part); size = psinfo->bufsize - hsize; dst += hsize; l2_cpy = min(l2, size); l1_cpy = min(l1, size - l2_cpy); if (l1_cpy + l2_cpy == 0) break; s2_start = l2 - l2_cpy; s1_start = l1 - l1_cpy; memcpy(dst, s1 + s1_start, l1_cpy); memcpy(dst + l1_cpy, s2 + s2_start, l2_cpy); id = psinfo->write(PSTORE_TYPE_DMESG, part, hsize + l1_cpy + l2_cpy, psinfo); if (reason == KMSG_DUMP_OOPS && pstore_is_mounted()) pstore_mkfile(PSTORE_TYPE_DMESG, psinfo->name, id, psinfo->buf, hsize + l1_cpy + l2_cpy, CURRENT_TIME, psinfo); l1 -= l1_cpy; l2 -= l2_cpy; total += l1_cpy + l2_cpy; part++; } mutex_unlock(&psinfo->buf_mutex); }
/* * Read all the records from the persistent store. Create * files in our filesystem. Don't warn about -EEXIST errors * when we are re-scanning the backing store looking to add new * error records. */ void pstore_get_records(int quiet) { struct pstore_info *psi = psinfo; char *buf = NULL; ssize_t size; u64 id; int count; enum pstore_type_id type; int failed = 0, rc; bool compressed; int unzipped_len = -1; if (!psi) return; mutex_lock(&psi->read_mutex); if (psi->open && psi->open(psi)) goto out; while ((size = psi->read(&id, &type, &count, &buf, &compressed, psi)) > 0) { if (compressed && (type == PSTORE_TYPE_DMESG)) { pr_err("barebox does not have ramoops compression support\n"); continue; } rc = pstore_mkfile(type, psi->name, id, count, buf, compressed, (size_t)size, psi); if (unzipped_len < 0) { /* Free buffer other than big oops */ kfree(buf); buf = NULL; } else unzipped_len = -1; if (rc && (rc != -EEXIST || !quiet)) failed++; } if (psi->close) psi->close(psi); out: mutex_unlock(&psi->read_mutex); if (failed) pr_warn("failed to load %d record(s) from '%s'\n", failed, psi->name); }
/* * Call platform driver to write a record to the * persistent store. */ int pstore_write(enum pstore_type_id type, char *buf, size_t size) { u64 id; if (!psinfo) return -ENODEV; if (size > psinfo->bufsize) return -EFBIG; mutex_lock(&psinfo->buf_mutex); memcpy(psinfo->buf, buf, size); id = psinfo->write(type, 0, size, psinfo); if (pstore_is_mounted()) pstore_mkfile(PSTORE_TYPE_DMESG, psinfo->name, id, psinfo->buf, size, CURRENT_TIME, psinfo); mutex_unlock(&psinfo->buf_mutex); return 0; }
/* * Call platform driver to write a record to the * persistent store. */ int pstore_write(enum pstore_type_id type, char *buf, size_t size) { u64 id; int ret; unsigned long flags; if (!psinfo) return -ENODEV; if (size > psinfo->bufsize) return -EFBIG; spin_lock_irqsave(&psinfo->buf_lock, flags); memcpy(psinfo->buf, buf, size); ret = psinfo->write(type, &id, 0, size, psinfo); if (ret == 0 && pstore_is_mounted()) pstore_mkfile(PSTORE_TYPE_DMESG, psinfo->name, id, psinfo->buf, size, CURRENT_TIME, psinfo); spin_unlock_irqrestore(&psinfo->buf_lock, flags); return 0; }