/*
 * 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);
}
Example #2
0
/*
 * 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);
}
Example #3
0
/*
 * 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);
}
Example #4
0
/*
 * 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);
}
Example #5
0
/*
 * 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);
}
Example #6
0
/*
 * 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);
}
Example #7
0
/*
 * 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);
}
Example #8
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;

    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;
}
Example #9
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;
}