Commit f62f6e8f authored by Alexandre Julliard's avatar Alexandre Julliard

Don't cache file descriptors open on removable devices.

parent bc22e2f0
......@@ -403,8 +403,7 @@ static int receive_fd( obj_handle_t *handle )
#ifndef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
fd = cmsg.fd;
#endif
if (fd == -1) server_protocol_error( "no fd received for handle %d\n", *handle );
fcntl( fd, F_SETFD, 1 ); /* set close on exec flag */
if (fd != -1) fcntl( fd, F_SETFD, 1 ); /* set close on exec flag */
return fd;
}
if (!ret) break;
......@@ -418,41 +417,6 @@ static int receive_fd( obj_handle_t *handle )
/***********************************************************************
* store_cached_fd
*
* Store the cached fd value for a given handle back into the server.
* Returns the new fd, which can be different if there was already an
* fd in the cache for that handle.
*/
inline static int store_cached_fd( int *fd, obj_handle_t handle )
{
int ret;
SERVER_START_REQ( set_handle_cached_fd )
{
req->handle = handle;
req->fd = *fd;
if (!(ret = wine_server_call( req )))
{
if (reply->cur_fd != *fd)
{
/* someone was here before us */
close( *fd );
*fd = reply->cur_fd;
}
}
else
{
close( *fd );
*fd = -1;
}
}
SERVER_END_REQ;
return ret;
}
/***********************************************************************
* wine_server_fd_to_handle (NTDLL.@)
*
* Allocate a file handle for a Unix file descriptor.
......@@ -502,7 +466,7 @@ int wine_server_fd_to_handle( int fd, unsigned int access, int inherit, obj_hand
int wine_server_handle_to_fd( obj_handle_t handle, unsigned int access, int *unix_fd, int *flags )
{
obj_handle_t fd_handle;
int ret, fd = -1;
int ret, removable = -1, fd = -1;
*unix_fd = -1;
for (;;)
......@@ -511,8 +475,12 @@ int wine_server_handle_to_fd( obj_handle_t handle, unsigned int access, int *uni
{
req->handle = handle;
req->access = access;
if (!(ret = wine_server_call( req ))) fd = reply->fd;
if (flags) *flags = reply->flags;
if (!(ret = wine_server_call( req )))
{
fd = reply->fd;
removable = reply->removable;
if (flags) *flags = reply->flags;
}
}
SERVER_END_REQ;
if (ret) return ret;
......@@ -521,8 +489,39 @@ int wine_server_handle_to_fd( obj_handle_t handle, unsigned int access, int *uni
/* it wasn't in the cache, get it from the server */
fd = receive_fd( &fd_handle );
if (fd == -1) return STATUS_TOO_MANY_OPENED_FILES;
if (fd_handle != handle) removable = -1;
if (removable == -1)
{
FILE_FS_DEVICE_INFORMATION info;
if (FILE_GetDeviceInfo( fd, &info ) == STATUS_SUCCESS)
removable = (info.Characteristics & FILE_REMOVABLE_MEDIA) != 0;
}
else if (removable) break; /* don't cache it */
/* and store it back into the cache */
ret = store_cached_fd( &fd, fd_handle );
SERVER_START_REQ( set_handle_fd )
{
req->handle = handle;
req->fd = fd;
req->removable = removable;
if (!(ret = wine_server_call( req )))
{
if (reply->cur_fd != fd && reply->cur_fd != -1)
{
/* someone was here before us */
close( fd );
fd = reply->cur_fd;
}
}
else
{
close( fd );
fd = -1;
}
}
SERVER_END_REQ;
if (ret) return ret;
if (fd_handle == handle) break;
......
......@@ -538,20 +538,6 @@ struct set_handle_info_reply
struct set_handle_cached_fd_request
{
struct request_header __header;
obj_handle_t handle;
int fd;
};
struct set_handle_cached_fd_reply
{
struct reply_header __header;
int cur_fd;
};
struct dup_handle_request
{
struct request_header __header;
......@@ -803,6 +789,7 @@ struct get_handle_fd_reply
{
struct reply_header __header;
int fd;
int removable;
int flags;
};
#define FD_FLAG_OVERLAPPED 0x01
......@@ -813,6 +800,20 @@ struct get_handle_fd_reply
* only handle available data (don't wait) */
struct set_handle_fd_request
{
struct request_header __header;
obj_handle_t handle;
int fd;
int removable;
};
struct set_handle_fd_reply
{
struct reply_header __header;
int cur_fd;
};
struct flush_file_request
{
......@@ -3597,7 +3598,6 @@ enum request
REQ_get_apc,
REQ_close_handle,
REQ_set_handle_info,
REQ_set_handle_cached_fd,
REQ_dup_handle,
REQ_open_process,
REQ_open_thread,
......@@ -3614,6 +3614,7 @@ enum request
REQ_create_file,
REQ_alloc_file_handle,
REQ_get_handle_fd,
REQ_set_handle_fd,
REQ_flush_file,
REQ_lock_file,
REQ_unlock_file,
......@@ -3809,7 +3810,6 @@ union generic_request
struct get_apc_request get_apc_request;
struct close_handle_request close_handle_request;
struct set_handle_info_request set_handle_info_request;
struct set_handle_cached_fd_request set_handle_cached_fd_request;
struct dup_handle_request dup_handle_request;
struct open_process_request open_process_request;
struct open_thread_request open_thread_request;
......@@ -3826,6 +3826,7 @@ union generic_request
struct create_file_request create_file_request;
struct alloc_file_handle_request alloc_file_handle_request;
struct get_handle_fd_request get_handle_fd_request;
struct set_handle_fd_request set_handle_fd_request;
struct flush_file_request flush_file_request;
struct lock_file_request lock_file_request;
struct unlock_file_request unlock_file_request;
......@@ -4019,7 +4020,6 @@ union generic_reply
struct get_apc_reply get_apc_reply;
struct close_handle_reply close_handle_reply;
struct set_handle_info_reply set_handle_info_reply;
struct set_handle_cached_fd_reply set_handle_cached_fd_reply;
struct dup_handle_reply dup_handle_reply;
struct open_process_reply open_process_reply;
struct open_thread_reply open_thread_reply;
......@@ -4036,6 +4036,7 @@ union generic_reply
struct create_file_reply create_file_reply;
struct alloc_file_handle_reply alloc_file_handle_reply;
struct get_handle_fd_reply get_handle_fd_reply;
struct set_handle_fd_reply set_handle_fd_reply;
struct flush_file_reply flush_file_reply;
struct lock_file_reply lock_file_reply;
struct unlock_file_reply unlock_file_reply;
......@@ -4205,6 +4206,6 @@ union generic_reply
struct set_mailslot_info_reply set_mailslot_info_reply;
};
#define SERVER_PROTOCOL_VERSION 190
#define SERVER_PROTOCOL_VERSION 191
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
......@@ -176,6 +176,7 @@ struct device
struct object obj; /* object header */
struct list entry; /* entry in device hash list */
dev_t dev; /* device number */
int removable; /* removable device? (or -1 if unknown) */
struct list inode_hash[INODE_HASH_SIZE]; /* inodes hash table */
};
......@@ -595,6 +596,7 @@ static struct device *get_device( dev_t dev )
if ((device = alloc_object( &device_ops )))
{
device->dev = dev;
device->removable = -1;
for (i = 0; i < INODE_HASH_SIZE; i++) list_init( &device->inode_hash[i] );
list_add_head( &device_hash[hash], &device->entry );
}
......@@ -1648,11 +1650,31 @@ DECL_HANDLER(get_handle_fd)
if (cached_fd != -1) reply->fd = cached_fd;
else if (!get_error()) send_client_fd( current->process, unix_fd, req->handle );
}
if (fd->inode) reply->removable = fd->inode->device->removable;
reply->flags = fd->fd_ops->get_file_info( fd );
release_object( fd );
}
}
/* set the cached file descriptor of a handle */
DECL_HANDLER(set_handle_fd)
{
struct fd *fd;
reply->cur_fd = -1;
if ((fd = get_handle_fd_obj( current->process, req->handle, 0 )))
{
struct device *device = fd->inode ? fd->inode->device : NULL;
if (device && device->removable == -1) device->removable = req->removable;
/* only cache the fd on non-removable devices */
if (!device || !device->removable)
reply->cur_fd = set_handle_unix_fd( current->process, req->handle, req->fd );
release_object( fd );
}
}
/* get ready to unmount a Unix device */
DECL_HANDLER(unmount_device)
{
......
......@@ -426,10 +426,11 @@ int get_handle_unix_fd( struct process *process, obj_handle_t handle, unsigned i
}
/* set the cached fd for a handle if not set already, and return the current value */
static int set_handle_unix_fd( struct process *process, obj_handle_t handle, int fd )
int set_handle_unix_fd( struct process *process, obj_handle_t handle, int fd )
{
struct handle_entry *entry;
if (handle_is_global( handle )) return -1; /* no fd cache for global handles */
if (!(entry = get_handle( process, handle ))) return -1;
/* if no current fd set it, otherwise return current fd */
if (entry->fd == -1) entry->fd = fd;
......@@ -556,15 +557,6 @@ DECL_HANDLER(set_handle_info)
reply->old_flags = set_handle_flags( current->process, req->handle, req->mask, req->flags );
}
/* set the cached file descriptor of a handle */
DECL_HANDLER(set_handle_cached_fd)
{
int fd = req->fd;
if (handle_is_global(req->handle)) fd = -1; /* no fd cache for global handles */
reply->cur_fd = set_handle_unix_fd( current->process, req->handle, fd );
}
/* duplicate a handle */
DECL_HANDLER(dup_handle)
{
......
......@@ -40,6 +40,7 @@ extern struct object *get_handle_obj( struct process *process, obj_handle_t hand
unsigned int access, const struct object_ops *ops );
extern unsigned int get_handle_access( struct process *process, obj_handle_t handle );
extern int get_handle_unix_fd( struct process *process, obj_handle_t handle, unsigned int access );
extern int set_handle_unix_fd( struct process *process, obj_handle_t handle, int fd );
extern obj_handle_t duplicate_handle( struct process *src, obj_handle_t src_handle, struct process *dst,
unsigned int access, int inherit, int options );
extern obj_handle_t open_object( const struct namespace *namespace, const WCHAR *name, size_t len,
......
......@@ -442,15 +442,6 @@ enum apc_type { APC_NONE, APC_USER, APC_TIMER, APC_ASYNC_IO };
@END
/* Set the cached file descriptor of a handle */
@REQ(set_handle_cached_fd)
obj_handle_t handle; /* handle we are interested in */
int fd; /* file descriptor */
@REPLY
int cur_fd; /* current file descriptor */
@END
/* Duplicate a handle */
@REQ(dup_handle)
obj_handle_t src_process; /* src process handle */
......@@ -621,6 +612,7 @@ enum event_op { PULSE_EVENT, SET_EVENT, RESET_EVENT };
unsigned int access; /* wanted access rights */
@REPLY
int fd; /* file descriptor */
int removable; /* is device removable? (-1 if unknown) */
int flags; /* file read/write flags (see below) */
@END
#define FD_FLAG_OVERLAPPED 0x01 /* fd opened in overlapped mode */
......@@ -630,6 +622,15 @@ enum event_op { PULSE_EVENT, SET_EVENT, RESET_EVENT };
#define FD_FLAG_AVAILABLE 0x10 /* in overlap read/write operation,
* only handle available data (don't wait) */
/* Set the cached file descriptor of a handle */
@REQ(set_handle_fd)
obj_handle_t handle; /* handle we are interested in */
int fd; /* file descriptor */
int removable; /* is device removable? (-1 if unknown) */
@REPLY
int cur_fd; /* current file descriptor */
@END
/* Flush a file buffers */
@REQ(flush_file)
......
......@@ -124,7 +124,6 @@ DECL_HANDLER(queue_apc);
DECL_HANDLER(get_apc);
DECL_HANDLER(close_handle);
DECL_HANDLER(set_handle_info);
DECL_HANDLER(set_handle_cached_fd);
DECL_HANDLER(dup_handle);
DECL_HANDLER(open_process);
DECL_HANDLER(open_thread);
......@@ -141,6 +140,7 @@ DECL_HANDLER(open_semaphore);
DECL_HANDLER(create_file);
DECL_HANDLER(alloc_file_handle);
DECL_HANDLER(get_handle_fd);
DECL_HANDLER(set_handle_fd);
DECL_HANDLER(flush_file);
DECL_HANDLER(lock_file);
DECL_HANDLER(unlock_file);
......@@ -335,7 +335,6 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
(req_handler)req_get_apc,
(req_handler)req_close_handle,
(req_handler)req_set_handle_info,
(req_handler)req_set_handle_cached_fd,
(req_handler)req_dup_handle,
(req_handler)req_open_process,
(req_handler)req_open_thread,
......@@ -352,6 +351,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
(req_handler)req_create_file,
(req_handler)req_alloc_file_handle,
(req_handler)req_get_handle_fd,
(req_handler)req_set_handle_fd,
(req_handler)req_flush_file,
(req_handler)req_lock_file,
(req_handler)req_unlock_file,
......
......@@ -836,17 +836,6 @@ static void dump_set_handle_info_reply( const struct set_handle_info_reply *req
fprintf( stderr, " old_flags=%d", req->old_flags );
}
static void dump_set_handle_cached_fd_request( const struct set_handle_cached_fd_request *req )
{
fprintf( stderr, " handle=%p,", req->handle );
fprintf( stderr, " fd=%d", req->fd );
}
static void dump_set_handle_cached_fd_reply( const struct set_handle_cached_fd_reply *req )
{
fprintf( stderr, " cur_fd=%d", req->cur_fd );
}
static void dump_dup_handle_request( const struct dup_handle_request *req )
{
fprintf( stderr, " src_process=%p,", req->src_process );
......@@ -1047,9 +1036,22 @@ static void dump_get_handle_fd_request( const struct get_handle_fd_request *req
static void dump_get_handle_fd_reply( const struct get_handle_fd_reply *req )
{
fprintf( stderr, " fd=%d,", req->fd );
fprintf( stderr, " removable=%d,", req->removable );
fprintf( stderr, " flags=%d", req->flags );
}
static void dump_set_handle_fd_request( const struct set_handle_fd_request *req )
{
fprintf( stderr, " handle=%p,", req->handle );
fprintf( stderr, " fd=%d,", req->fd );
fprintf( stderr, " removable=%d", req->removable );
}
static void dump_set_handle_fd_reply( const struct set_handle_fd_reply *req )
{
fprintf( stderr, " cur_fd=%d", req->cur_fd );
}
static void dump_flush_file_request( const struct flush_file_request *req )
{
fprintf( stderr, " handle=%p", req->handle );
......@@ -3109,7 +3111,6 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_get_apc_request,
(dump_func)dump_close_handle_request,
(dump_func)dump_set_handle_info_request,
(dump_func)dump_set_handle_cached_fd_request,
(dump_func)dump_dup_handle_request,
(dump_func)dump_open_process_request,
(dump_func)dump_open_thread_request,
......@@ -3126,6 +3127,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_create_file_request,
(dump_func)dump_alloc_file_handle_request,
(dump_func)dump_get_handle_fd_request,
(dump_func)dump_set_handle_fd_request,
(dump_func)dump_flush_file_request,
(dump_func)dump_lock_file_request,
(dump_func)dump_unlock_file_request,
......@@ -3317,7 +3319,6 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_get_apc_reply,
(dump_func)dump_close_handle_reply,
(dump_func)dump_set_handle_info_reply,
(dump_func)dump_set_handle_cached_fd_reply,
(dump_func)dump_dup_handle_reply,
(dump_func)dump_open_process_reply,
(dump_func)dump_open_thread_reply,
......@@ -3334,6 +3335,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_create_file_reply,
(dump_func)dump_alloc_file_handle_reply,
(dump_func)dump_get_handle_fd_reply,
(dump_func)dump_set_handle_fd_reply,
(dump_func)dump_flush_file_reply,
(dump_func)dump_lock_file_reply,
(dump_func)0,
......@@ -3525,7 +3527,6 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
"get_apc",
"close_handle",
"set_handle_info",
"set_handle_cached_fd",
"dup_handle",
"open_process",
"open_thread",
......@@ -3542,6 +3543,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
"create_file",
"alloc_file_handle",
"get_handle_fd",
"set_handle_fd",
"flush_file",
"lock_file",
"unlock_file",
......
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