inode caching

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

 



NFS server: Linux 2.6.25
NFS client: Linux debian 2.6.25-2 (or 2.6.23.1)

If I do:

NFS client: fd1 = creat("foo"); write(fd1, "xx", 2); fsync(fd1);
NFS server: unlink("foo"); creat("foo");
NFS client: fd2 = open("foo"); fstat(fd1, &st1); fstat(fd2, &st2);
fstat(fd1, &st3);

The result is usually that the fstat(fd1) fails with ESTALE. But
sometimes the result is st1.st_ino == st2.st_ino == st3.st_ino and
st1.st_size == 2 but st2.st_size == 0. So I see two different files
using the same inode number. I'd really want to avoid seeing that
condition.

So what I'd want to know is:

a) Why does this happen only sometimes? I can't really figure out from
the code what invalidates the fd1 inode. Apparently the second open()
somehow, but since it uses the new "foo" file with a different struct
inode, where does the old struct inode get invalidated?

b) Can this be fixed? Or is it just luck that it works as well as it
does now?

Attached a test program. Usage:

NFS client: Mount with actimeo=2
NFS client: ./t
(Run the next two commands within 2 seconds)
NFS server: rm -f foo;touch foo
NFS client: hit enter 

Once in a while the result will be:
1a: ino=15646940 size=2
1b: ino=15646940 size=2
1c: ino=15646940 size=2
2: ino=15646940 size=0
1d: ino=15646940 size=2

#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/stat.h>

int main(void) {
	struct stat st;
	int fd, fd2;
	char buf[100];

	fd = open("foo", O_RDWR | O_CREAT, 0666);
	write(fd, "xx", 2); fsync(fd);
	if (fstat(fd, &st) < 0) perror("fstat()");
	printf("1a: ino=%ld size=%ld\n", (long)st.st_ino, st.st_size);

	fgets(buf, sizeof(buf), stdin);
	if (fstat(fd, &st) < 0) perror("fstat()");
	else printf("1b: ino=%ld size=%ld\n", (long)st.st_ino, st.st_size);

	fd2 = open("foo", O_RDWR);
	if (fstat(fd, &st) < 0) perror("fstat()");
	else printf("1c: ino=%ld size=%ld\n", (long)st.st_ino, st.st_size);
	if (fstat(fd2, &st) < 0) perror("fstat()");
	else printf("2: ino=%ld size=%ld\n", (long)st.st_ino, st.st_size);
	if (fstat(fd, &st) < 0) perror("fstat()");
	else printf("1d: ino=%ld size=%ld\n", (long)st.st_ino, st.st_size);
	return 0;
}

Attachment: signature.asc
Description: This is a digitally signed message part


[Index of Archives]     [Linux Filesystem Development]     [Linux USB Development]     [Linux Media Development]     [Video for Linux]     [Linux NILFS]     [Linux Audio Users]     [Yosemite Info]     [Linux SCSI]

  Powered by Linux