Commit 3b30002a authored by Jacek Caban's avatar Jacek Caban Committed by Alexandre Julliard

ntdll: Cache error information for cacheable handles with no fd.

parent 5ede16eb
...@@ -876,22 +876,25 @@ static BOOL add_fd_to_cache( HANDLE handle, int fd, enum server_fd_type type, ...@@ -876,22 +876,25 @@ static BOOL add_fd_to_cache( HANDLE handle, int fd, enum server_fd_type type,
/*********************************************************************** /***********************************************************************
* get_cached_fd * get_cached_fd
*/ */
static inline int get_cached_fd( HANDLE handle, enum server_fd_type *type, static inline NTSTATUS get_cached_fd( HANDLE handle, int *fd, enum server_fd_type *type,
unsigned int *access, unsigned int *options ) unsigned int *access, unsigned int *options )
{ {
unsigned int entry, idx = handle_to_index( handle, &entry ); unsigned int entry, idx = handle_to_index( handle, &entry );
int fd = -1; union fd_cache_entry cache;
if (entry < FD_CACHE_ENTRIES && fd_cache[entry]) if (entry >= FD_CACHE_ENTRIES || !fd_cache[entry]) return STATUS_INVALID_HANDLE;
{
union fd_cache_entry cache; cache.data = interlocked_cmpxchg64( &fd_cache[entry][idx].data, 0, 0 );
cache.data = interlocked_cmpxchg64( &fd_cache[entry][idx].data, 0, 0 ); if (!cache.data) return STATUS_INVALID_HANDLE;
fd = cache.s.fd - 1;
if (type) *type = cache.s.type; /* if fd type is invalid, fd stores an error value */
if (access) *access = cache.s.access; if (cache.s.type == FD_TYPE_INVALID) return cache.s.fd - 1;
if (options) *options = cache.s.options;
} *fd = cache.s.fd - 1;
return fd; if (type) *type = cache.s.type;
if (access) *access = cache.s.access;
if (options) *options = cache.s.options;
return STATUS_SUCCESS;
} }
...@@ -907,7 +910,7 @@ int server_remove_fd_from_cache( HANDLE handle ) ...@@ -907,7 +910,7 @@ int server_remove_fd_from_cache( HANDLE handle )
{ {
union fd_cache_entry cache; union fd_cache_entry cache;
cache.data = interlocked_xchg64( &fd_cache[entry][idx].data, 0 ); cache.data = interlocked_xchg64( &fd_cache[entry][idx].data, 0 );
fd = cache.s.fd - 1; if (cache.s.type != FD_TYPE_INVALID) fd = cache.s.fd - 1;
} }
return fd; return fd;
...@@ -924,19 +927,19 @@ int server_get_unix_fd( HANDLE handle, unsigned int wanted_access, int *unix_fd, ...@@ -924,19 +927,19 @@ int server_get_unix_fd( HANDLE handle, unsigned int wanted_access, int *unix_fd,
{ {
sigset_t sigset; sigset_t sigset;
obj_handle_t fd_handle; obj_handle_t fd_handle;
int ret = 0, fd; int ret, fd = -1;
unsigned int access = 0; unsigned int access = 0;
*unix_fd = -1; *unix_fd = -1;
*needs_close = 0; *needs_close = 0;
wanted_access &= FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA; wanted_access &= FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA;
fd = get_cached_fd( handle, type, &access, options ); ret = get_cached_fd( handle, &fd, type, &access, options );
if (fd != -1) goto done; if (ret != STATUS_INVALID_HANDLE) goto done;
server_enter_uninterrupted_section( &fd_cache_section, &sigset ); server_enter_uninterrupted_section( &fd_cache_section, &sigset );
fd = get_cached_fd( handle, type, &access, options ); ret = get_cached_fd( handle, &fd, type, &access, options );
if (fd == -1) if (ret == STATUS_INVALID_HANDLE)
{ {
SERVER_START_REQ( get_handle_fd ) SERVER_START_REQ( get_handle_fd )
{ {
...@@ -955,6 +958,10 @@ int server_get_unix_fd( HANDLE handle, unsigned int wanted_access, int *unix_fd, ...@@ -955,6 +958,10 @@ int server_get_unix_fd( HANDLE handle, unsigned int wanted_access, int *unix_fd,
} }
else ret = STATUS_TOO_MANY_OPENED_FILES; else ret = STATUS_TOO_MANY_OPENED_FILES;
} }
else if (reply->cacheable)
{
add_fd_to_cache( handle, ret, FD_TYPE_INVALID, 0, 0 );
}
} }
SERVER_END_REQ; SERVER_END_REQ;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment