Re: Page cache ignored on second read

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Mark Hills <mark@xxxxxxxxxxx> wrote:

> But now that I can reasonably use fscache with NFS, I noticed that the 
> page cache doesn't seem to be used?
> 
> * When cachefilesd is running, reads do not come from the page cache

Hmmm.

> * The page cache fills up with something, but the local cache filesystem
>   continues to be read

The cache files themselves also get read into the pagecache.  Ideally I'd have
them do direct I/O, but that's not easy with Linux.

> In the first cases, I'm not sure if the page cache memory contains NFS 
> pages, or local disk pages. Is there an easy way to check?

You can watch /proc/fs/fscache/stats to see what fscache is being asked to do,
though I'm not sure how much that helps you.

These two lines:

	Retrvls: n=48497 ok=20622 wt=11867 nod=27871 nbf=0 int=0 oom=0
	Retrvls: ops=48497 owt=12134 abt=0

indicate the number of retrieval operations taking place (n), the number that
were satisfied from disk (ok) and the number for which the disk contained no
data (nod).

Also these two lines:

	Stores : n=70254 ok=70254 agn=0 nbf=0 oom=0
	Stores : ops=27311 run=97136 pgs=69825 rxd=70208 olm=0

which indicate the number of page storage requests given to fscache (n) and
completed (ok).  The number of internal storage operations (ops) is also shown
(an op may write more than one page, so n!=ops is okay).

A retrieval should only occur when the netfs doesn't have the data to hand,
but will take two pages to complete with CacheFiles.  The backing page is
immediately discardable once the data it contains has been copied to the netfs
page - but it does mean that your pagecache may be only half as efficient as
it could be for those files.

I wonder if there's a way to tell the VM to discard the backing pages I've
finished with...

Attached is the program I use for watching files like this (I prefer it to
watch + cat).  Just compile and give it the name of the file you want to
watch.

Another way to find out, though it's a bit drastic, is to unmount the net or
backing fs and see how much space becomes available.

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@xxxxxxxxxx)
 *
 * 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 = 0, r;
	char *ip, *istop;
	int l, llen;

	do {
		r = pread(fd, input + isize, input_size - isize, isize);
		if (r == -1)
			error("read");
		isize += r;

	} while (r > 0 && isize < input_size);

	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;
			}
		}
	}
}
--
Linux-cachefs mailing list
Linux-cachefs@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/linux-cachefs

[Index of Archives]     [LARTC]     [Bugtraq]     [Yosemite Forum]
  Powered by Linux