[Linux-cachefs] Yet another trace from a crash

David Howells dhowells at redhat.com
Tue May 11 16:46:26 UTC 2010


Can you manage to get a printout of /proc/fs/fscache/stats just before the
crash?

You might be able to do this by ssh'ing in and running:

	filewatch /proc/fs/fscache/stats

Where filewatch is the attached program.  This has an advantage over watch+cat
in that it doesn't have to keep forking and execing.

David
---
/* watch a file and display the output on a TTY, appropriately formatted
 *
 * Copyright (C) 2009 Red Hat, Inc. All Rights Reserved.
 * Written by David Howells (dhowells at redhat.com)
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public Licence
 * as published by the Free Software Foundation; either version
 * 2 of the Licence, or (at your option) any later version.
 */


#define _XOPEN_SOURCE 500
#include <ncurses.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <errno.h>
#include <string.h>

static char *input;
static int fd;
static int lines, cols;
static size_t input_size;

static void cleanup(void)
{
	endwin();
}

static void sigint(int sig)
{
	endwin();
	signal(SIGINT, SIG_DFL);
	raise(SIGINT);
}

static __attribute__((noreturn))
void error(const char *str)
{
	int err = errno;

	endwin();
	fprintf(stderr, "%s: %s\n", str, strerror(err));
	exit(1);
}

/*
 * read from the file into the buffer and then display into the curses buffer,
 * truncating overlong lines
 */
static void display_file(void)
{
	ssize_t isize;
	char *ip, *istop;
	int l, llen;

	isize = pread(fd, input, input_size, 0);
	if (isize == -1)
		error("read");

	ip = input;
	for (l = 0; l < lines; l++) {
		if (isize <= 0)
			break;

		istop = memchr(ip, '\n', isize);
		llen = istop - ip;
		if (llen > cols)
			llen = cols;
		if (llen > 0)
			mvaddnstr(l, 0, ip, llen);
		if (llen < cols)
			clrtoeol();
		istop++;
		isize -= istop - ip;
		ip = istop;
	}

	if (l < lines)
		clrtobot();
}

/*
 *
 */
int main(int argc, char **argv)
{
	int ch, paused = 0;

	if (argc != 2)
		exit(2);

	if (!isatty(1)) {
		fprintf(stderr, "stdout not a TTY\n");
		exit(3);
	}

	fd = open(argv[1], O_RDONLY, 0);
	if (fd == -1) {
		perror("open");
		exit(1);
	}

	signal(SIGINT, sigint);
	atexit(cleanup);

	initscr();
	cbreak();
	noecho();

	for (;;) {
		if (!input) {
			lines = LINES;
			cols = COLS;
			input_size = lines * (cols + 1) * 4;
			input = calloc(1, input_size + 1);
			if (!input)
				error("calloc");
		}

		if (!paused) {
			display_file();
			move(lines - 1, cols - 1);
			refresh();
		}

		if (halfdelay(1) == OK) {
			ch = getch();
			if (ch == 'q')
				exit(0);
			if (ch == ' ') {
				paused = !paused;
				if (paused) {
					mvaddch(0, cols - 8, '[');
					standout();
					addnstr("PAUSED", 6);
					standend();
					addch(']');
				}
			}
			if (ch == KEY_RESIZE) {
				free(input);
				input = NULL;
			}
		}
	}
}




More information about the Linux-cachefs mailing list