Question regarding CIFS cache=loose behavior.
Jeffrey Layton
jlayton at redhat.com
Wed Mar 26 07:03:05 MDT 2014
On Wed, 26 Mar 2014 05:21:19 -0700
Jeffrey Layton <jlayton at redhat.com> wrote:
> 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.
>
...or maybe it *is* cifs.ko. From cifs_inode_needs_reval:
if (!time_in_range(jiffies, cifs_i->time,
cifs_i->time + cifs_sb->actimeo))
return true;
...I think though that if cifs_i->time == jiffies and actimeo=0, then
that condition will be false. As a quick check, it might be good to add
something like this before that if statement and then rerun your test:
if (!cifs_sb->actimeo)
return true;
That should get rid of that particular corner case.
--
Jeff Layton <jlayton at redhat.com>
More information about the samba-technical
mailing list