Re: Flush SMB Cache on Windows Vista?



Hello Jed,

I examined the source code and built both projects - there seems to be a problem. It's in AccessFile.c. Pathname (as passed to CreateFile) API is incorrect. For example, if the client is called like this:

myclient.exe c:\test 192.168.123.100

- then string "c:\test" is passed to server (via socket) and it creates file c:\test\test0.txt - so far it's fine. However, when client tries to open that file on server machine (via CreateFile API) - the same pathname is used - which is incorrect of course because you need UNC name here. For example:

\\192.168.123.100\c$\test\test0.txt

In my test environment file creation seems to work fine, but deletion returns error 123 - didn't get chance to look in this new issue.

Here's console output of both EXEs:

Client:


C:\temp\smb2_test_client>myclient.exe c:\temp\test 192.168.123.202
Using path: c:\temp\test
bind call worked
got server connection
The server failed to delete file c:\temp\test\test0.txt.
<<<<<<<<<<<<<<<<<

Server:


C:\temp\SMB2_test_server>myserver.exe
waiting for client connections...
accepted new connection from 192.168.123.104:14784
Received create file request. Creating File c:\temp\test\test0.txt
Received delete file request. Deleting File c:\temp\test\test0.txt
Error 123 when deleting c:\temp\test\test0.txt
got a disconnect request from 192.168.123.104:14784
<<<<<<<<<<<<<<<<<


Boris

"Jed" <jth_nospam_alias_2@xxxxxxxxxxxxxxxx> wrote in message news:6bf7df521ac078cb63f9e51998f7@xxxxxxxxxxxxxxxxxxxxxxx
Hello boris,

The notification is sent after user A closes the file. Although, due to your question, I put together a mock-up that simply created/opened the file (verifying success), and notified user B that the file was created (leaving the file open). The resulting behavior was no different than if I had closed the file.

I have put together a small mock-up that will reproduce the problem a reasonable percentage of the time. I was going to post a zip file containing two VS2005 projects, but they are too large to post. Instead, I'm attaching two source files to this message: server.c is a simple TCP "server" that will accept a TCP connection and create/delete a single file in response to a TCP command. AccessFile.cpp is a simple TCP client that will ask the "server" to create a file, then attempt to open it. If you're interested in building these, I can send the VS2005 projects used to build them (provided I can get the size down enough to post them). Let me know if you're interested...

Jed

Hello Jed,

A question. So when user A creates new file on file share, user B
receives
notification of that event and then attempts to open that file (which
fails
sometimes).
But at which point is the notification sent: right after user A
(successfully) calls CreatFile() or after user A closes that new file?
Have
you verified that the file already exists when notification is sent
(one way
of verifying would be trying to open that file or calling
FindFileFirst() on
the fileserver - so no SMB is involved)?
Boris

"Jed" <jth_nospam_alias_2@xxxxxxxxxxxxxxxx> wrote in message
news:6bf7df521a9268cb60910a256e1a@xxxxxxxxxxxxxxxxxxxxxxx

Hello boris,

That is an interesting theory. I am reasonably certain that I can
rule
that out as a possibility. My test environment is isolated to a
single
Vista client and the server. Actually, I've tested both with two
virtual
machines using host-only networking, as well as with two physical
boxes in
an isolated network. In both cases, the server shows no other
clients
connected and no open files.
More importantly, in both cases, wireshark doesn't even show any SMB
traffic for the CreateFile call when it fails. Here is a portion of
the
code that I have used to reproduce this behavior:
// The file has been created -- now see if this client can see it
hFile = CreateFile( (const char *)aucFullPath,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
NULL );
if ( hFile == INVALID_HANDLE_VALUE )
{
printf( "The file Does Not Exist.. ", iLoop );
dwStartTime = GetTickCount();

iRetryCount = 0;
do
{
Sleep( 50 );
iRetryCount++;
hFile = CreateFile( (const char *)aucFullPath,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
NULL );
} while ( hFile == INVALID_HANDLE_VALUE );
dwElapsedTime = (DWORD)( GetTickCount() - dwStartTime );
printf( "File Exists after %d milliseconds and %d retries.\n",
dwElapsedTime, iRetryCount );
}
When this fails, iRetryCount can be as high as 60-70. During that
time,
the network sniff will show absolutely no traffic going across the
wire
until the CreateFile call succeeds. (The gap in packet transmission
time
also corresponds to the value of dwElapsedTime.) If this were a CAL
licensing issue, I would expect traffic to go across the wire, and
the
server to deny the open request -- but it is clear from my
observation
that the client is denying the request without ever consulting the
file
server; which is why I'm reasonably certain that SMB caching is
causing
the issue. (Also, I can confirm that using
GetFileInformationByHandleEx
does bypass the cache --
it can see the file if I enumerate the directory contents; but even
when
GetFileInformationByHandleEx can "see" the file, CreateFile will fail
if
the cache information has not been updated.)
This is a real issue for us. Certainly we can't be the only ISV for
whom
this new protocol has had an adverse effect... I understand the
benefit
that caching can provide, but there are some situations in which
cached
data simply isn't acceptable. Surely there must be some API call
that
will force SMB to update its metadata cache prior to the scheduled
cache
refresh --
even if only for a specific share/directory?
Jed

Hello Jed,

Are you sure you aren't hitting this one:
http://support.microsoft.com/kb/937082 ? - it describes Vista used
as fileserver, but I imagine similar behavior would occur in Win2008
if there aren't enough CALs installed on the server.

Boris

"Jed" <jth_nospam_alias_2@xxxxxxxxxxxxxxxx> wrote in message
news:6bf7df521a79a8cb5fe5b5e35732@xxxxxxxxxxxxxxxxxxxxxxx

Hello boris,

Thanks for the suggestion, Boris. I do believe that would do the
job -- but that's a pretty large hammer. :) Unfortunately, I
don't think that would be a viable workaround for us.

Jed

"Jed" <jth_nospam_alias_2@xxxxxxxxxxxxxxxx> wrote in message
news:6bf7df521a71d8cb5f274f97aaf1@xxxxxxxxxxxxxxxxxxxxxxx

The short version of my question is: Is there an API call that
will
dump
the SMB cache on Windows Vista when SMB 2.0 is used for Windows
Networking?
There may be alternatives to dumping the cache that I haven't
considered,
so allow me to offer a bit of (simplified) background: We have a
multi-user software, where multiple users may be simultaneously
creating,
opening, and accessing files on a shared drive. We have found
then
when
our users upgrade their file servers to Server 2008, and they
access
the
share from Windows Vista, the following scenario may occur: A
file
is
created on a shared drive by User A. User B gets notification
that
the
file has been created, so user B attempts to open that file. In
most
cases, this works properly. But, sometimes (probably dependent
on
cache
refresh timing), User B's attempts to open the file fail with an
error 2.
I have replicated a replicated a simplified version of this test
case
in
our test environment and I have found that when User B receives
the
error
2 (file not found), no SMB2 traffic appears on the wire. That,
and
the
fact that this only occurs when Windows Vista and Server 2008 are
involved
tells me the caching in SMB2 is causing the client to return the
failure
based on cached directory information.
Up until this point, I have attempted several alternate ways of
attempting
to refresh the cache on demand: I've attempted to use the
following
methods to "force" the cache to update, or traffic to go across
the
wire:
- Call _access or GetFileAttributes (simply test for file
existence).
-
CreateFile (tested specifying dwCreationDisposition of both
CREATE_NEW and
OPEN_EXISTING). Using OPEN_EXISTING behaves the same as
GetFileAttributes. CREATE_NEW does work properly -- but creating
a
file
and then cleaning it up when the file is not present is not a
good
workaround.
- GetFileInformationByHandleEx also seems to bypass the cache and
can
provide up-to-date information on file existence -- but even when
file
existence has been confirmed by GetFileInformationByHandleEx, the
file
open still fails, so I doubt the cache is being updated.
Sorry for the lengthy post; but I wanted to detail what I've
already
tried. Does anyone have any other workarounds to try? Aside from
other
workarounds, it would be ideal for us to have an API that will
force
the
SMB cache to flush. Does any such API exist?
Jed
A workaround (an ugly one though) would be to reconnect to the
network
share
in question.
It could be done by a batch file:
net use \\servername\sharename /d
net use \\servername\sharename
It can also be done via Net Win32 APIs:
WNetCancelConnection2
http://msdn.microsoft.com/en-us/library/aa385427(VS.85).aspx
WNetAddConnection2
http://msdn.microsoft.com/en-us/library/aa385413(VS.85).aspx
Boris


.



Relevant Pages

  • Re: Flush SMB Cache on Windows Vista?
    ... (If you run the client with no arguments, the example provided by the usage statement indicates that. ... Pathname (as passed to CreateFile) ... client tries to open that file on server machine ... the cache information has not been updated.) ...
    (microsoft.public.win32.programmer.networks)
  • Re: Flush SMB Cache on Windows Vista?
    ... DeleteFilefails with error 123 because of this: ... I built both EXEs with UNICODE settings - but replaced all CreateFile() calls with CreateFileA: so it's able to use ascii filename strings. ... when client tries to open that file on server machine - the same pathname is used - which is incorrect of course because you need UNC name here. ... the cache information has not been updated.) ...
    (microsoft.public.win32.programmer.networks)
  • Re: How to create a pipe connection?
    ... Use the CreateNamedPipeAPI to create it on the server, ... You should read the Named Pipes section of the Platform SDK, ... the PSDK entries for CreateFile and all of the Named Pipe API functions. ...
    (comp.programming)
  • Re: A buffer mapped to a file?
    ... You could try a named pipe, if the program really just calls CreateFile and reads or write to the resulting handle, but as soon as a program tries to do something like query file size, set file pointer, or soforth, that will break. ... Basically I have a buffer of data and need to feed it into an API ... that are within the filesystem namespace and will the ReadFileAPI ...
    (microsoft.public.win32.programmer.kernel)
  • Re: How do I link to C Library functions in windows?
    ... Any Win32 API that takes or returns a string will have an A and a W ... What do you mean by "setup the stack"? ... If CreateFile returns ... push eax; which I should save to the stack ...
    (comp.lang.asm.x86)