diff --git a/dlls/ntdll/server.c b/dlls/ntdll/server.c index ce27d5d5243..5e67bd6414e 100644 --- a/dlls/ntdll/server.c +++ b/dlls/ntdll/server.c @@ -564,7 +564,7 @@ int server_get_unix_fd( HANDLE handle, unsigned int wanted_access, int *unix_fd, if ((fd = receive_fd( &fd_handle )) != -1) { assert( wine_server_ptr_handle(fd_handle) == handle ); - *needs_close = (reply->removable || + *needs_close = (!reply->cacheable || !add_fd_to_cache( handle, fd, reply->type, reply->access, reply->options )); } diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 1a78bc2e77a..0c43ecf6d03 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -1242,7 +1242,7 @@ struct get_handle_fd_reply { struct reply_header __header; int type; - int removable; + int cacheable; unsigned int access; unsigned int options; }; @@ -5487,6 +5487,6 @@ union generic_reply struct set_cursor_reply set_cursor_reply; }; -#define SERVER_PROTOCOL_VERSION 402 +#define SERVER_PROTOCOL_VERSION 403 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/server/fd.c b/server/fd.c index ca317c4a1a9..9111a657e91 100644 --- a/server/fd.c +++ b/server/fd.c @@ -197,6 +197,7 @@ struct fd char *unix_name; /* unix file name */ int unix_fd; /* unix file descriptor */ unsigned int no_fd_status;/* status to return when unix_fd is -1 */ + unsigned int cacheable :1;/* can the fd be cached on the client side? */ unsigned int signaled :1; /* is the fd signaled? */ unsigned int fs_locks :1; /* can we use filesystem locks for this fd? */ int poll_index; /* index of fd in poll array */ @@ -1546,6 +1547,7 @@ static struct fd *alloc_fd_object(void) fd->sharing = 0; fd->unix_fd = -1; fd->unix_name = NULL; + fd->cacheable = 0; fd->signaled = 1; fd->fs_locks = 1; fd->poll_index = -1; @@ -1580,6 +1582,7 @@ struct fd *alloc_pseudo_fd( const struct fd_ops *fd_user_ops, struct object *use fd->sharing = 0; fd->unix_name = NULL; fd->unix_fd = -1; + fd->cacheable = 0; fd->signaled = 0; fd->fs_locks = 0; fd->poll_index = -1; @@ -1608,6 +1611,7 @@ struct fd *dup_fd_object( struct fd *orig, unsigned int access, unsigned int sha fd->options = options; fd->sharing = sharing; fd->unix_fd = -1; + fd->cacheable = orig->cacheable; fd->signaled = 0; fd->fs_locks = 0; fd->poll_index = -1; @@ -1823,6 +1827,7 @@ struct fd *open_fd( struct fd *root, const char *name, int flags, mode_t *mode, } fd->inode = inode; fd->closed = closed_fd; + fd->cacheable = !inode->device->removable; list_add_head( &inode->open, &fd->inode_entry ); /* check directory options */ @@ -1869,6 +1874,7 @@ struct fd *open_fd( struct fd *root, const char *name, int flags, mode_t *mode, goto error; } free( closed_fd ); + fd->cacheable = 1; } return fd; @@ -1922,6 +1928,12 @@ int is_same_file_fd( struct fd *fd1, struct fd *fd2 ) return fd1->inode == fd2->inode; } +/* allow the fd to be cached (can't be reset once set) */ +void allow_fd_caching( struct fd *fd ) +{ + fd->cacheable = 1; +} + /* check if fd is on a removable device */ int is_fd_removable( struct fd *fd ) { @@ -2269,7 +2281,7 @@ DECL_HANDLER(get_handle_fd) if (unix_fd != -1) { reply->type = fd->fd_ops->get_fd_type( fd ); - reply->removable = is_fd_removable(fd); + reply->cacheable = fd->cacheable; reply->options = fd->options; reply->access = get_handle_access( current->process, req->handle ); send_client_fd( current->process, unix_fd, req->handle ); diff --git a/server/file.c b/server/file.c index 105c3396728..d17b25b8ca0 100644 --- a/server/file.c +++ b/server/file.c @@ -136,6 +136,7 @@ struct file *create_file_for_fd( int fd, unsigned int access, unsigned int shari release_object( file ); return NULL; } + allow_fd_caching( file->fd ); } return file; } diff --git a/server/file.h b/server/file.h index 9a348bfd572..26290a38969 100644 --- a/server/file.h +++ b/server/file.h @@ -71,6 +71,7 @@ extern int check_fd_events( struct fd *fd, int events ); extern void set_fd_events( struct fd *fd, int events ); extern obj_handle_t lock_fd( struct fd *fd, file_pos_t offset, file_pos_t count, int shared, int wait ); extern void unlock_fd( struct fd *fd, file_pos_t offset, file_pos_t count ); +extern void allow_fd_caching( struct fd *fd ); extern void set_fd_signaled( struct fd *fd, int signaled ); extern int is_fd_signaled( struct fd *fd ); diff --git a/server/mailslot.c b/server/mailslot.c index 97da8d2df83..051f0adb48f 100644 --- a/server/mailslot.c +++ b/server/mailslot.c @@ -297,6 +297,7 @@ static struct object *mailslot_open_file( struct object *obj, unsigned int acces release_object( writer ); return NULL; } + allow_fd_caching( writer->fd ); return &writer->obj; } @@ -442,9 +443,12 @@ static struct mailslot *create_mailslot( struct directory *root, fcntl( fds[1], F_SETFL, O_NONBLOCK ); shutdown( fds[0], SHUT_RD ); mailslot->write_fd = fds[0]; - mailslot->fd = create_anonymous_fd( &mailslot_fd_ops, fds[1], &mailslot->obj, - FILE_SYNCHRONOUS_IO_NONALERT ); - if (mailslot->fd) return mailslot; + if ((mailslot->fd = create_anonymous_fd( &mailslot_fd_ops, fds[1], &mailslot->obj, + FILE_SYNCHRONOUS_IO_NONALERT ))) + { + allow_fd_caching( mailslot->fd ); + return mailslot; + } } else file_set_error(); diff --git a/server/mapping.c b/server/mapping.c index 1cf53b9fe99..c8b8edfa2e6 100644 --- a/server/mapping.c +++ b/server/mapping.c @@ -515,6 +515,7 @@ static struct object *create_mapping( struct directory *root, const struct unico if ((unix_fd = create_temp_file( size )) == -1) goto error; if (!(mapping->fd = create_anonymous_fd( &mapping_fd_ops, unix_fd, &mapping->obj, FILE_SYNCHRONOUS_IO_NONALERT ))) goto error; + allow_fd_caching( mapping->fd ); } mapping->size = (size + page_mask) & ~((mem_size_t)page_mask); mapping->protect = protect; diff --git a/server/named_pipe.c b/server/named_pipe.c index 95f06b9aab0..29d5c5efdf8 100644 --- a/server/named_pipe.c +++ b/server/named_pipe.c @@ -838,6 +838,8 @@ static struct object *named_pipe_open_file( struct object *obj, unsigned int acc server->fd = create_anonymous_fd( &pipe_server_fd_ops, fds[0], &server->obj, server->options ); if (client->fd && server->fd) { + allow_fd_caching( client->fd ); + allow_fd_caching( server->fd ); fd_copy_completion( server->ioctl_fd, server->fd ); if (server->state == ps_wait_open) fd_async_wake_up( server->ioctl_fd, ASYNC_TYPE_WAIT, STATUS_SUCCESS ); diff --git a/server/protocol.def b/server/protocol.def index e41cd183ab8..5f1a8f99950 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1018,7 +1018,7 @@ enum event_op { PULSE_EVENT, SET_EVENT, RESET_EVENT }; obj_handle_t handle; /* handle to the file */ @REPLY int type; /* file type (see below) */ - int removable; /* is file removable? */ + int cacheable; /* can fd be cached in the client? */ unsigned int access; /* file access rights */ unsigned int options; /* file open options */ @END diff --git a/server/request.h b/server/request.h index 722fc25c679..7897673bb27 100644 --- a/server/request.h +++ b/server/request.h @@ -888,7 +888,7 @@ C_ASSERT( sizeof(struct get_handle_unix_name_reply) == 16 ); C_ASSERT( FIELD_OFFSET(struct get_handle_fd_request, handle) == 12 ); C_ASSERT( sizeof(struct get_handle_fd_request) == 16 ); C_ASSERT( FIELD_OFFSET(struct get_handle_fd_reply, type) == 8 ); -C_ASSERT( FIELD_OFFSET(struct get_handle_fd_reply, removable) == 12 ); +C_ASSERT( FIELD_OFFSET(struct get_handle_fd_reply, cacheable) == 12 ); C_ASSERT( FIELD_OFFSET(struct get_handle_fd_reply, access) == 16 ); C_ASSERT( FIELD_OFFSET(struct get_handle_fd_reply, options) == 20 ); C_ASSERT( sizeof(struct get_handle_fd_reply) == 24 ); diff --git a/server/sock.c b/server/sock.c index 24ad50c18d3..639421d3157 100644 --- a/server/sock.c +++ b/server/sock.c @@ -646,6 +646,7 @@ static struct object *create_socket( int family, int type, int protocol, unsigne release_object( sock ); return NULL; } + allow_fd_caching( sock->fd ); sock_reselect( sock ); clear_error(); return &sock->obj; @@ -718,6 +719,7 @@ static struct sock *accept_socket( obj_handle_t handle ) release_object( sock ); return NULL; } + allow_fd_caching( acceptsock->fd ); } clear_error(); sock->pmask &= ~FD_ACCEPT; diff --git a/server/trace.c b/server/trace.c index fd2318e102c..944d939cb84 100644 --- a/server/trace.c +++ b/server/trace.c @@ -1475,7 +1475,7 @@ 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, " type=%d", req->type ); - fprintf( stderr, ", removable=%d", req->removable ); + fprintf( stderr, ", cacheable=%d", req->cacheable ); fprintf( stderr, ", access=%08x", req->access ); fprintf( stderr, ", options=%08x", req->options ); }