Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Flush SMB Cache on Windows Vista?

5,009 views
Skip to first unread message

Jed

unread,
Feb 17, 2009, 4:58:21 PM2/17/09
to
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


boris

unread,
Feb 18, 2009, 1:35:47 AM2/18/09
to
"Jed" <jth_nospa...@community.nospam> wrote in message
news:6bf7df521a71d8...@msnews.microsoft.com...
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

Jed

unread,
Feb 18, 2009, 3:41:17 PM2/18/09
to
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

boris

unread,
Feb 18, 2009, 4:25:35 PM2/18/09
to
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_nospa...@community.nospam> wrote in message

news:6bf7df521a79a8...@msnews.microsoft.com...

Jed

unread,
Feb 19, 2009, 12:07:43 PM2/19/09
to
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

boris

unread,
Feb 19, 2009, 7:45:02 PM2/19/09
to
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_nospa...@community.nospam> wrote in message

news:6bf7df521a9268...@msnews.microsoft.com...

boris

unread,
Feb 24, 2009, 9:20:24 AM2/24/09
to
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_nospa...@community.nospam> wrote in message

news:6bf7df521ac078...@msnews.microsoft.com...
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

boris

unread,
Feb 24, 2009, 9:35:43 AM2/24/09
to
Actually,

DeleteFile() fails with error 123 because of this:

I built both EXEs with (default) UNICODE settings - but replaced all
CreateFile() calls with CreateFileA(): so it's able to use ascii filename
strings. But just forgot to replace DeleteFile() with DeleteFileA().

Boris

"boris" <some...@nowhere.net> wrote in message
news:49a4022b$0$1640$742e...@news.sonic.net...

Jed

unread,
Feb 24, 2009, 11:57:16 AM2/24/09
to
Hello boris,

Thank you for taking a look at the source..

Actually, the test was meant to use a UNC path. (If you run the client with
no arguments, the example provided by the usage statement indicates that.
I should have been more explicit in the instructions.) If you run the test
using "AccessFile \\server\c$\test 192.168.123.202", I think it should work
better for you. You'll find that it will work properly some percentage of
the time, but a small percentage of the time, you'll see output similar to
this:

"File \\server\test\test0.txt does not exist.. File Exists after X milliseconds
and Y retries."
(Typically, X will be less than about 5000, and Y will be less than 100.)

Jed

boris

unread,
Feb 24, 2009, 8:08:13 PM2/24/09
to
Hello Jed,

Oops - sorry for confusion.

I ran the tests twice.
1st scenario. client: Hyper-v vm with Win2008 Ent. x64 R2 Beta; server: vm
with Win2008 Standard x86;
2nd scenario. client: Win2008 Ent. x64 system (not vm); server: vm with
Win2008 Standard x86 (same as in 1st scenario);
Verified that SMB2 was used: by running WireShark on the server vm.

In both cases the tests ran to completion successfully (1000 iterations). No
error messages were displayed in client console window.

>>>>>>>>>>>>>PASTE client console output>>>>>>>>>>>>>>>>>>>

C:\temp\smb2_test>myclient.exe \\192.168.123.202\c$\temp\test
192.168.123.202
Using path: \\192.168.123.202\c$\temp\test


bind call worked
got server connection

C:\temp\smb2_test>

<<<<<<<<<<<<<PASTE<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

>>>>>>>>>>>>>PASTE serverconsole output>>>>>>>>>>>>>>>>>>>
...


Received create file request. Creating File

\\192.168.123.202\c$\temp\test\test
995.txt


Received delete file request. Deleting File

\\192.168.123.202\c$\temp\test\test
995.txt


Received create file request. Creating File

\\192.168.123.202\c$\temp\test\test
996.txt


Received delete file request. Deleting File

\\192.168.123.202\c$\temp\test\test
996.txt


Received create file request. Creating File

\\192.168.123.202\c$\temp\test\test
997.txt


Received delete file request. Deleting File

\\192.168.123.202\c$\temp\test\test
997.txt


Received create file request. Creating File

\\192.168.123.202\c$\temp\test\test
998.txt


Received delete file request. Deleting File

\\192.168.123.202\c$\temp\test\test
998.txt


Received create file request. Creating File

\\192.168.123.202\c$\temp\test\test
999.txt


Received delete file request. Deleting File

\\192.168.123.202\c$\temp\test\test
999.txt
got a disconnect request from 192.168.123.109:3264
<<<<<<<<<<<<<PASTE<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

If you suspect that directory contents isn't updated on client system, you
could try calling FindFileFirst() API with dir. parameter: UNC path of the
dir where file was created. That API does directory scan, so it might help -
again if this is the problem.

Boris

"Jed" <jth_nospa...@community.nospam> wrote in message

news:6bf7df521ac928...@msnews.microsoft.com...

0 new messages