Skip to content

Commit

Permalink
Allow cbuf to be saved to disk from Registry
Browse files Browse the repository at this point in the history
Adding a tunable to allow cbuf to be saved to disk,
which might make it easier for non-developers to
share debug information.

Signed-off-by: Jorgen Lundman <[email protected]>
  • Loading branch information
lundman committed Sep 6, 2024
1 parent 6fe046e commit d493b96
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 0 deletions.
80 changes: 80 additions & 0 deletions module/os/windows/debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include <stdarg.h>
#include <stdio.h>
#include <Trace.h>
#include <sys/mod_os.h>

#define max_line_length 1024

Expand All @@ -48,11 +49,90 @@ char *cbuf = NULL;
static unsigned long long cbuf_size = 0x100000; // 1MB
static unsigned long long startOff = 0;


#define CBUF_SAVE_LEN 100
#define CBUF_FILENAME L"\\??\\C:\\Program Files\\OpenZFS On Windows\\cbuf.txt"
uchar_t zfs_cbuf_save[CBUF_SAVE_LEN] = "Set this to 1 to save cbuf";

int
param_cbuf_save(ZFS_MODULE_PARAM_ARGS)
{
static uchar_t buf[CBUF_SAVE_LEN];

*type = ZT_TYPE_STRING;

if (set == B_FALSE) {
*ptr = (void *)zfs_cbuf_save;
*len = strlen(zfs_cbuf_save);
return (0);
}

// Skip any string not starting with "1"
if (!ptr ||
!*ptr ||
((char *)*ptr)[0] != '1') {
// Keep the text if starts with *
if (((char *)*ptr)[0] != '*')
snprintf(zfs_cbuf_save, sizeof (zfs_cbuf_save),
"Set this to 1 to save cbuf");
return (0);
}

// strlcpy(buf, *ptr, sizeof (buf));
dprintf("Saving cbuf to %S\n", CBUF_FILENAME);
((char *)*ptr)[0] = '*'; // Take out the '1'

UNICODE_STRING fileNameUnicode;
OBJECT_ATTRIBUTES objectAttributes;
HANDLE fileHandle;
IO_STATUS_BLOCK ioStatusBlock;
NTSTATUS status;

RtlInitUnicodeString(&fileNameUnicode, CBUF_FILENAME);

InitializeObjectAttributes(&objectAttributes, &fileNameUnicode,
OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL);

status = ZwCreateFile(&fileHandle, GENERIC_WRITE, &objectAttributes,
&ioStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL,
0, FILE_OVERWRITE_IF, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);

if (NT_SUCCESS(status)) {
// To be nice, let's start at the offset, and do two saves.
// first, startOffset to end of buffer. Special case, if
// buffer has never wrapped, skip all initial "\n"
unsigned long long pos;
pos = startOff + sizeof (endBuf);
while (cbuf[pos] == '\n' && pos < cbuf_size)
pos++;

len = cbuf_size - pos;
if (len > 0)
status = ZwWriteFile(fileHandle, NULL, NULL, NULL,
&ioStatusBlock, cbuf + pos, (ULONG)len, NULL, NULL);
// then, start of file, to startOff
len = startOff;
if (len > 0)
status = ZwWriteFile(fileHandle, NULL, NULL, NULL,
&ioStatusBlock, cbuf, (ULONG)len, NULL, NULL);

ZwClose(fileHandle);
snprintf(zfs_cbuf_save, sizeof (zfs_cbuf_save),
"* Saved %S", CBUF_FILENAME);
} else {
snprintf(zfs_cbuf_save, sizeof (zfs_cbuf_save),
"* Unable to open %S", CBUF_FILENAME);
}

return (0);
}

int
initDbgCircularBuffer(void)
{
cbuf = ExAllocatePoolWithTag(NonPagedPoolNx, cbuf_size, '!GBD');
ASSERT(cbuf);
memset(cbuf, '\n', cbuf_size);
KeInitializeSpinLock(&cbuf_spin);
return (0);
}
Expand Down
9 changes: 9 additions & 0 deletions module/os/windows/zfs/zfs_debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -295,3 +295,12 @@ zfs_dbgmsg_print(int id, const char *tag)
(void) printBuffer("%s\n", zdm->zdm_msg);
mutex_exit(&zfs_dbgmsgs_lock);
}

// Sadly, the linker_set.h and mod_os.h work for
// clang, but not MSVC, so can not be defined in
// debug.c for now. One day we'll figure out the
// use of __pragma(data_seg(push, ".")) to make it work.
extern uchar_t *zfs_cbuf_save;
extern int param_cbuf_save(ZFS_MODULE_PARAM_ARGS);
ZFS_MODULE_PARAM_CALL(, zfs_, cbuf_save, param_cbuf_save,
param_get_charp, ZMOD_RW, "OpenZFS debug buffer");

0 comments on commit d493b96

Please sign in to comment.