Question regarding CIFS cache=loose behavior.

Jeffrey Layton jlayton at redhat.com
Wed Mar 26 06:21:19 MDT 2014


On Wed, 26 Mar 2014 21:04:15 +0900
Tetsuo Handa <penguin-kernel at I-love.SAKURA.ne.jp> wrote:

> Jeff Layton wrote:
> > > Yes, I suggested a customer using CIFS on RHEL6 to use cache=none
> > > or cache=strict , for that customer's system does not work as
> > > expected due to the latter behavior when using "tail -f" for
> > > checking for appended log.
> > 
> > Yeah, cache=strict should work much better for that sort of
> > use-case.
> > 
> I got another problem where none of cache=none cache=strict actimeo=0
> helps.
> 
> Since "tail -f" does "repeat calling sleep() and fstat() until the
> file size increases" -> "do read() until EOF" -> "call fstat()
> again", "tail -f" prints "file truncated" message and prints some
> portion of already printed lines even though the file size on the
> Samba server never decreased. I expect that the latest fstat()
> returns the up-to-date file size. This behavior is observed on
> 2.6.32-431.11.2.el6.x86_64 and 3.14-rc8.
> 
> Steps to reproduce:
> 
> ---------- Start of testprog.c ----------
> /**
>  * stdin and stdout must refer a regular file which is shared via
> CIFS.
>  * An example is shown below.
>  *
>  * # mount -t cifs -o
> cache=strict,actimeo=0 //127.0.0.1/path/to/export /path/to/mount
>  * $ cc -Wall -O3 -o a.out this_file.c
>  * $ ./a.out > /path/to/export/shared_file
> < /path/to/mount/shared_file */
> #include <stdio.h>
> #include <stdlib.h>
> #include <poll.h>
> #include <sys/stat.h>
> #include <unistd.h>
> 
> int main(int argc, char *argv[])
> {
> 	unsigned int delay = argc > 1 ? atoi(argv[1]) : 0;
> 	size_t write_pos = 0;
> 	size_t read_pos = 0;
> 	if (ftruncate(1, 0))
> 		return 1;
> 	while (1) {
> 		struct stat buf;
> 		char c;
> 		if (write(1, ".", 1) != 1)
> 			return 2;
> 		write_pos++;
> 		if (fstat(1, &buf))
> 			return 3;
> 		if (buf.st_size != write_pos)
> 			return 4;
> 		if (read(0, &c, 1) != 1)
> 			return 5;
> 		if (c != '.')
> 			return 6;
> 		read_pos++;
> 		if (delay)
> 			poll(NULL, 0, delay);
> 		if (fstat(0, &buf))
> 			return 7;
> 		if (buf.st_size < read_pos)
> 			fprintf(stderr, "read(%lu) - stat(%lu) =
> %lu\n", read_pos, buf.st_size, read_pos - buf.st_size);
> 	}
> }
> ---------- End of testprog.c ----------
> 
> Make a CIFS mount on localhost where the Samba server process is
> running. Compile testprog.c and run testprog, with stdin redirected
> to a regular file which is accessed via CIFS and stdout redirected to
> the same regular file which is accessed as a local filesystem. An
> example is shown below.
> 
>   # mount -t cifs -o cache=none,actimeo=0 //127.0.0.1/home /mnt
>   $ cc -Wall -O3 -o testprog testprog.c
>   $ ./testprog > ~/shared_file < /mnt/shared_file
> 
> According to what testprog.c does, it is expected that nothing is
> printed by testprog process because the bytes read via read() equals
> the bytes obtained via fstat(). However, testprog process prints that
> the bytes read via read() is larger than the bytes obtained via
> fstat().
> 
> The strace on the smbd process reports that CIFS is omitting lstat()
> request after pread() request if lstat() request was done very
> recently. Specifying delay as the command line argument for testprog
> process reduces the possibility of omitting lstat() request.

(cc'ing samba-technical)

...or that samba is omitting it and is sending cached info instead of
doing the lstat() call? I'm not sure if it does that, but I don't
think you should draw too many conclusions about the behavior of cifs.ko
from stracing smbd.

What may make more sense is to get network captures and analyze the
behavior from that perspective.

-- 
Jeff Layton <jlayton at redhat.com>


More information about the samba-technical mailing list