/*
 * 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;
		size_t len;

		dst = psinfo->buf;
		hsize = sprintf(dst, "%s#%d Part%d\n", why, oopscount, part);
		size = psinfo->bufsize - hsize;
		dst += hsize;

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

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

		total += hsize + 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);
}
Beispiel #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);
}
Beispiel #3
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;
	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);
		is_locked = 1;
	}
	oopscount++;
	while (total < kmsg_bytes) {
		char *dst;
		unsigned long size;
		int hsize;
		int zipped_len = -1;
		size_t len;
		bool compressed = false;
		size_t total_len;

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

		hsize = sprintf(dst, "%s#%d Part%u\n", why, oopscount, part);
		size -= hsize;

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

		if (big_oops_buf && is_locked) {
			zipped_len = pstore_compress(dst, psinfo->buf,
						hsize + len, psinfo->bufsize);

			if (zipped_len > 0) {
				compressed = true;
				total_len = zipped_len;
			} else {
				total_len = copy_kmsg_to_buffer(hsize, len);
			}
		} else {
			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 (is_locked)
		spin_unlock_irqrestore(&psinfo->buf_lock, flags);
}