[linux-cifs-client] lseek(x, x, SEEK_END) and the infinite dentry cache

Maximiliano Curia maxy at rivero.com.ar
Tue Dec 27 17:06:00 GMT 2005


Hi!

I'm debugging some data-loss problems that I've been having, with old clipper 
applications running inside dosemu.  I work in a mixed-client environment with 
some Windows and some Linux clients.  All the servers run Linux.

Trying to find the root of the problem I've written some C code that 
reproduces the bad behaviour.

One of the problems I've found is with lseek.  For example, doing this:

	end = lseek (fd, 0, SEEK_END);

over a file that changes externally (another client is adding records to it) 
returns the same value as long as you don't do something else with the
cifs connection.

I've written an small test program [1] that checks the return value of lseek 
and waits for it to change. To test it you have to make a change to a file 
(tlseek.tst) remotely.

In order to fix the problem, I've added a simple cifs_llseek in cifsfs.c for  
kernel tree 2.6.14 (based on the nfs code for the same purpose):

static loff_t cifs_llseek(struct file *file, loff_t offset, int origin)
{
	/* origin == SEEK_END => we must revalidate the cached file length */
	if (origin == 2) {
		int retval = cifs_revalidate(file->f_dentry);
		if (retval < 0)
			return (loff_t)retval;
	}
	return remote_llseek(file, offset, origin);
}

And registered the cifs_llseek in cifs_file_ops.

This does fix the lseek problem inside the C program [2], but it does not fix 
it for programs running under dosemu.  When doing an strace of those [3], the 
call to lseek still returns the same value every time, even if the file has 
changed.

If I strace the file-server, each lseek triggers an fstat64 call, that 
correctly returns the new file size.  However, for some weird reason the 
lseek function does not take this value.

I can't yet figure out what the difference might be.  The output of strace is 
quite similar, but the results are pretty different.

[1] http://gnuservers.com.ar/~maxy/linux/tlseek.c
[2] http://gnuservers.com.ar/~maxy/linux/tlseek.strace 
[3] http://gnuservers.com.ar/~maxy/linux/dosemu.strace (filtered version, 
that only includes the important data and some of the lseek calls, this was 
actually running for a very long time, and there was never a change in the 
lseek return value, no matter how large the file got)

-- 
Saludos,
 /\/\ /\ >< `/


More information about the linux-cifs-client mailing list