Esempio n. 1
0
void
dumpsys(struct dumperinfo *di)
{
	struct sparc64_dump_hdr hdr;
	vm_size_t size, totsize, hdrsize;
	int error, i, nreg;

	/* Calculate dump size. */
	size = 0;
	nreg = sparc64_nmemreg;
	for (i = 0; i < sparc64_nmemreg; i++)
		size += sparc64_memreg[i].mr_size;
	/* Account for the header size. */
	hdrsize = roundup2(sizeof(hdr) + sizeof(struct sparc64_dump_reg) * nreg,
	    DEV_BSIZE);
	size += hdrsize;

	totsize = size + 2 * sizeof(kdh);
	if (totsize > di->mediasize) {
		printf("Insufficient space on device (need %ld, have %ld), "
		    "refusing to dump.\n", (long)totsize,
		    (long)di->mediasize);
		error = ENOSPC;
		goto fail;
	}

	/* Determine dump offset on device. */
	dumplo = di->mediaoffset + di->mediasize - totsize;

	mkdumpheader(&kdh, KERNELDUMPMAGIC, KERNELDUMP_SPARC64_VERSION, size,
	    di->blocksize);

	printf("Dumping %lu MB (%d chunks)\n", (u_long)(size >> 20), nreg);

	/* Dump leader */
	error = dump_write(di, &kdh, 0, dumplo, sizeof(kdh));
	if (error)
		goto fail;
	dumplo += sizeof(kdh);

	/* Dump the private header. */
	hdr.dh_hdr_size = hdrsize;
	hdr.dh_tsb_pa = tsb_kernel_phys;
	hdr.dh_tsb_size = tsb_kernel_size;
	hdr.dh_tsb_mask = tsb_kernel_mask;
	hdr.dh_nregions = nreg;

	if (buf_write(di, (char *)&hdr, sizeof(hdr)) != 0)
		goto fail;

	dumppos = hdrsize;
	/* Now, write out the region descriptors. */
	for (i = 0; i < sparc64_nmemreg; i++) {
		error = reg_write(di, sparc64_memreg[i].mr_start,
		    sparc64_memreg[i].mr_size);
		if (error != 0)
			goto fail;
	}
	buf_flush(di);

	/* Dump memory chunks. */
	for (i = 0; i < sparc64_nmemreg; i++) {
		error = blk_dump(di, sparc64_memreg[i].mr_start,
		    sparc64_memreg[i].mr_size);
		if (error != 0)
			goto fail;
	}

	/* Dump trailer */
	error = dump_write(di, &kdh, 0, dumplo, sizeof(kdh));
	if (error)
		goto fail;

	/* Signal completion, signoff and exit stage left. */
	dump_write(di, NULL, 0, 0, 0);
	printf("\nDump complete\n");
	return;

 fail:
	/* XXX It should look more like VMS :-) */
	printf("** DUMP FAILED (ERROR %d) **\n", error);
}
/*
 * Commit text dump to disk.
 */
void
textdump_dumpsys(struct dumperinfo *di)
{
	off_t dumplen, trailer_offset;

	if (di->blocksize != TEXTDUMP_BLOCKSIZE) {
		printf("Dump partition block size (%ju) not textdump "
		    "block size (%ju)", (uintmax_t)di->blocksize,
		    (uintmax_t)TEXTDUMP_BLOCKSIZE);
		return;
	}

	/*
	 * We don't know a priori how large the dump will be, but we do know
	 * that we need to reserve space for metadata and that we need two
	 * dump headers.  Also leave room for one ustar header and one block
	 * of data.
	 */
	if (di->mediasize < SIZEOF_METADATA + 2 * sizeof(kdh)) {
		printf("Insufficient space on dump partition.\n");
		return;
	}
	textdump_error = 0;

	/*
	 * Position the start of the dump so that we'll write the kernel dump
	 * trailer immediately before the end of the partition, and then work
	 * our way back.  We will rewrite this header later to reflect the
	 * true size if things go well.
	 */
	textdump_offset = di->mediasize - sizeof(kdh);
	textdump_saveoff(&trailer_offset);
	mkdumpheader(&kdh, TEXTDUMPMAGIC, KERNELDUMP_TEXT_VERSION, 0, TEXTDUMP_BLOCKSIZE);
	(void)textdump_writenextblock(di, (char *)&kdh);

	/*
	 * Write a series of files in ustar format.
	 */
	if (textdump_do_ddb)
		db_capture_dump(di);
#ifdef INCLUDE_CONFIG_FILE
	if (textdump_do_config)
		textdump_dump_config(di);
#endif
	if (textdump_do_msgbuf)
		textdump_dump_msgbuf(di);
	if (textdump_do_panic && panicstr != NULL)
		textdump_dump_panic(di);
	if (textdump_do_version)
		textdump_dump_version(di);

	/*
	 * Now that we know the true size, we can write out the header, then
	 * seek back to the end and rewrite the trailer with the correct
	 * size.
	 */
	dumplen = trailer_offset - (textdump_offset + TEXTDUMP_BLOCKSIZE);
	mkdumpheader(&kdh, TEXTDUMPMAGIC, KERNELDUMP_TEXT_VERSION, dumplen,
	    TEXTDUMP_BLOCKSIZE);
	(void)textdump_writenextblock(di, (char *)&kdh);
	textdump_restoreoff(trailer_offset);
	(void)textdump_writenextblock(di, (char *)&kdh);

	/*
	 * Terminate the dump, report any errors, and clear the pending flag.
	 */
	if (textdump_error == 0)
		(void)dump_write(di, NULL, 0, 0, 0);
	if (textdump_error == ENOSPC)
		printf("Insufficient space on dump partition\n");
	else if (textdump_error != 0)
		printf("Error %d writing dump\n", textdump_error);
	else
		printf("Textdump complete.\n");
	textdump_pending = 0;
}