fs/pstore/platform.c

Source file repositories/reference/linux-study-clean/fs/pstore/platform.c

File Facts

System
Linux kernel
Corpus path
fs/pstore/platform.c
Extension
.c
Size
18931 bytes
Lines
767
Domain
Core OS
Bucket
VFS And Filesystem Core
Inferred role
Core OS: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

if (!raw_spin_trylock_irqsave(&psinfo->buf_lock, flags)) {
			pr_err("dump skipped in %s path because of concurrent dump\n",
					in_nmi() ? "NMI" : why);
			return;
		}
	} else {
		raw_spin_lock_irqsave(&psinfo->buf_lock, flags);
	}

	kmsg_dump_rewind(&iter);

	oopscount++;
	while (total < remaining) {
		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 = detail->reason;
		record.part = part;
		record.buf = psinfo->buf;

		dst = big_oops_buf ?: psinfo->buf;
		dst_size = max_compressed_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(&iter, 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 {
				/*
				 * Compression failed, so the buffer is most
				 * likely filled with binary data that does not
				 * compress as well as ASCII text. Copy as much
				 * of the uncompressed data as possible into
				 * the pstore record, and discard the rest.
				 */
				record.size = psinfo->bufsize;
				memcpy(psinfo->buf, dst, psinfo->bufsize);
			}
		} else {
			record.size = header_size + dump_size;
		}

		ret = psinfo->write(&record);
		if (ret == 0 && detail->reason == KMSG_DUMP_OOPS) {
			pstore_new_entry = 1;
			pstore_timer_kick();
		} else {
			/* Preserve only the first non-zero returned value. */
			if (!saved_ret)
				saved_ret = ret;
		}

		total += record.size;
		part++;
	}
	raw_spin_unlock_irqrestore(&psinfo->buf_lock, flags);

	if (saved_ret) {
		pr_err_once("backend (%s) writing error (%d)\n", psinfo->name,
			    saved_ret);
	}
}

static struct kmsg_dumper pstore_dumper = {
	.dump = pstore_dump,
};

/*
 * Register with kmsg_dump to save last part of console log on panic.

Annotation

Implementation Notes