Esempio n. 1
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)
{
    unsigned long	total = 0;
    const char	*why;
    u64		id;
    unsigned int	part = 1;
    unsigned long	flags = 0;
    int		is_locked = 0;
    int		ret;

    why = get_reason_str(reason);

    if (pstore_cannot_block_path(reason)) {
        is_locked = spin_trylock_irqsave(&psinfo->buf_lock, flags);
        if (!is_locked) {
            pr_err("pstore dump routine blocked in %s path, may corrupt error record\n"
                   , in_nmi() ? "NMI" : why);
        }
    } else
        spin_lock_irqsave(&psinfo->buf_lock, flags);
    oopscount++;
    while (total < kmsg_bytes) {
        char *dst;
        unsigned long size;
        int hsize;
        int zipped_len = -1;
        size_t len;
        bool compressed;
        size_t total_len;

        if (big_oops_buf && is_locked) {
            dst = big_oops_buf;
            hsize = sprintf(dst, "%s#%d Part%u\n", why,
                            oopscount, part);
            size = big_oops_buf_sz - hsize;

            if (!kmsg_dump_get_buffer(dumper, true, dst + hsize,
                                      size, &len))
                break;

            zipped_len = pstore_compress(dst, psinfo->buf,
                                         hsize + len, psinfo->bufsize);

            if (zipped_len > 0) {
                compressed = true;
                total_len = zipped_len;
            } else {
                compressed = false;
                total_len = copy_kmsg_to_buffer(hsize, len);
            }
        } else {
            dst = psinfo->buf;
            hsize = sprintf(dst, "%s#%d Part%u\n", why, oopscount,
                            part);
            size = psinfo->bufsize - hsize;
            dst += hsize;

            if (!kmsg_dump_get_buffer(dumper, true, dst,
                                      size, &len))
                break;

            compressed = false;
            total_len = hsize + len;
        }

        ret = psinfo->write(PSTORE_TYPE_DMESG, reason, &id, part,
                            oopscount, compressed, total_len, psinfo);
        if (ret == 0 && reason == KMSG_DUMP_OOPS && pstore_is_mounted())
            pstore_new_entry = 1;

        total += total_len;
        part++;
    }
    if (pstore_cannot_block_path(reason)) {
        if (is_locked)
            spin_unlock_irqrestore(&psinfo->buf_lock, flags);
    } else
        spin_unlock_irqrestore(&psinfo->buf_lock, flags);
}
Esempio n. 2
0
/*
 * callback from kmsg_dump. Save as much as we can (up to kmsg_bytes) from the
 * end of the buffer.
 */
static void pstore_dump(struct kmsg_dumper *dumper,
			enum kmsg_dump_reason reason)
{
	unsigned long	total = 0;
	const char	*why;
	unsigned int	part = 1;
	int		ret;

	why = get_reason_str(reason);

	if (down_trylock(&psinfo->buf_lock)) {
		/* Failed to acquire lock: give up if we cannot wait. */
		if (pstore_cannot_wait(reason)) {
			pr_err("dump skipped in %s path: may corrupt error record\n",
				in_nmi() ? "NMI" : why);
			return;
		}
		if (down_interruptible(&psinfo->buf_lock)) {
			pr_err("could not grab semaphore?!\n");
			return;
		}
	}

	oopscount++;
	while (total < kmsg_bytes) {
		char *dst;
		size_t dst_size;
		int header_size;
		int zipped_len = -1;
		size_t dump_size;
		struct pstore_record record;

		pstore_record_init(&record, psinfo);
		record.type = PSTORE_TYPE_DMESG;
		record.count = oopscount;
		record.reason = reason;
		record.part = part;
		record.buf = psinfo->buf;

		if (big_oops_buf) {
			dst = big_oops_buf;
			dst_size = big_oops_buf_sz;
		} else {
			dst = psinfo->buf;
			dst_size = psinfo->bufsize;
		}

		/* Write dump header. */
		header_size = snprintf(dst, dst_size, "%s#%d Part%u\n", why,
				 oopscount, part);
		dst_size -= header_size;

		/* Write dump contents. */
		if (!kmsg_dump_get_buffer(dumper, true, dst + header_size,
					  dst_size, &dump_size))
			break;

		if (big_oops_buf) {
			zipped_len = pstore_compress(dst, psinfo->buf,
						header_size + dump_size,
						psinfo->bufsize);

			if (zipped_len > 0) {
				record.compressed = true;
				record.size = zipped_len;
			} else {
				record.size = copy_kmsg_to_buffer(header_size,
								  dump_size);
			}
		} else {
			record.size = header_size + dump_size;
		}

		ret = psinfo->write(&record);
		if (ret == 0 && reason == KMSG_DUMP_OOPS && pstore_is_mounted())
			pstore_new_entry = 1;

		total += record.size;
		part++;
	}

	up(&psinfo->buf_lock);
}