From f85437c57fb44d511db97edbaa5b1f8abfe75fd3 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard <julliard@winehq.org> Date: Tue, 10 Apr 2007 22:25:07 +0200 Subject: [PATCH] server: Store the opening options in the file descriptor instead of in the individual objects. Allows moving the FD_FLAG_OVERLAPPED support to the generic get_handle_fd request handling. --- server/change.c | 2 +- server/fd.c | 24 +++++++++++++++--------- server/file.c | 21 ++++++++------------- server/file.h | 5 +++-- server/mailslot.c | 10 +++++----- server/named_pipe.c | 16 ++++------------ server/process.c | 2 +- server/queue.c | 2 +- server/request.c | 2 +- server/serial.c | 18 +----------------- server/signal.c | 2 +- server/sock.c | 44 +++++++++++++++++--------------------------- server/thread.c | 6 +++--- 13 files changed, 61 insertions(+), 93 deletions(-) diff --git a/server/change.c b/server/change.c index a12c68be103..00ffb9437c2 100644 --- a/server/change.c +++ b/server/change.c @@ -793,7 +793,7 @@ static inline struct fd *create_inotify_fd( void ) unix_fd = inotify_init(); if (unix_fd<0) return NULL; - return create_anonymous_fd( &inotify_fd_ops, unix_fd, NULL ); + return create_anonymous_fd( &inotify_fd_ops, unix_fd, NULL, 0 ); } static int map_flags( unsigned int filter ) diff --git a/server/fd.c b/server/fd.c index 504512e392f..c7ae7fbfa31 100644 --- a/server/fd.c +++ b/server/fd.c @@ -166,6 +166,7 @@ struct fd struct object *user; /* object using this file descriptor */ struct list locks; /* list of locks on this fd */ unsigned int access; /* file access (FILE_READ_DATA etc.) */ + unsigned int options; /* file options (FILE_DELETE_ON_CLOSE, FILE_SYNCHRONOUS...) */ unsigned int sharing; /* file sharing mode */ int unix_fd; /* unix file descriptor */ int signaled :1; /* is the fd signaled? */ @@ -1278,7 +1279,7 @@ void unlock_fd( struct fd *fd, file_pos_t start, file_pos_t count ) static void fd_dump( struct object *obj, int verbose ) { struct fd *fd = (struct fd *)obj; - fprintf( stderr, "Fd unix_fd=%d user=%p", fd->unix_fd, fd->user ); + fprintf( stderr, "Fd unix_fd=%d user=%p options=%08x", fd->unix_fd, fd->user, fd->options ); if (fd->inode) fprintf( stderr, " inode=%p unlink='%s'", fd->inode, fd->closed->unlink ); fprintf( stderr, "\n" ); } @@ -1359,6 +1360,7 @@ static struct fd *alloc_fd_object(void) fd->inode = NULL; fd->closed = NULL; fd->access = 0; + fd->options = 0; fd->sharing = 0; fd->unix_fd = -1; fd->signaled = 1; @@ -1463,6 +1465,7 @@ struct fd *open_fd( const char *name, int flags, mode_t *mode, unsigned int acce if (!(fd = alloc_fd_object())) return NULL; + fd->options = options; if (options & FILE_DELETE_ON_CLOSE) unlink_name = name; if (!(closed_fd = mem_alloc( sizeof(*closed_fd) + strlen(unlink_name) ))) { @@ -1570,7 +1573,8 @@ error: /* create an fd for an anonymous file */ /* if the function fails the unix fd is closed */ -struct fd *create_anonymous_fd( const struct fd_ops *fd_user_ops, int unix_fd, struct object *user ) +struct fd *create_anonymous_fd( const struct fd_ops *fd_user_ops, int unix_fd, struct object *user, + unsigned int options ) { struct fd *fd = alloc_fd_object(); @@ -1578,6 +1582,7 @@ struct fd *create_anonymous_fd( const struct fd_ops *fd_user_ops, int unix_fd, s { set_fd_user( fd, fd_user_ops, user ); fd->unix_fd = unix_fd; + fd->options = options; return fd; } close( unix_fd ); @@ -1590,6 +1595,12 @@ void *get_fd_user( struct fd *fd ) return fd->user; } +/* retrieve the opening options for the fd */ +unsigned int get_fd_options( struct fd *fd ) +{ + return fd->options; +} + /* retrieve the unix fd for an object */ int get_unix_fd( struct fd *fd ) { @@ -1733,15 +1744,8 @@ void fd_reselect_async( struct fd *fd, struct async_queue *queue ) void default_fd_queue_async( struct fd *fd, const async_data_t *data, int type, int count ) { - int flags; struct async *async; - fd->fd_ops->get_file_info( fd, &flags ); - if (!(flags & (FD_FLAG_OVERLAPPED|FD_FLAG_TIMEOUT))) - { - set_error( STATUS_INVALID_HANDLE ); - return; - } if ((async = fd_queue_async( fd, data, type, count ))) { release_object( async ); @@ -1907,6 +1911,8 @@ DECL_HANDLER(get_handle_fd) reply->type = fd->fd_ops->get_file_info( fd, &reply->flags ); if (reply->type != FD_TYPE_INVALID) { + if (!(fd->options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT))) + reply->flags |= FD_FLAG_OVERLAPPED; if (is_fd_removable(fd)) reply->flags |= FD_FLAG_REMOVABLE; if (!req->cached) { diff --git a/server/file.c b/server/file.c index e038af37212..e6f1c711f09 100644 --- a/server/file.c +++ b/server/file.c @@ -58,7 +58,6 @@ struct file struct object obj; /* object header */ struct fd *fd; /* file descriptor for this file */ unsigned int access; /* file access (FILE_READ_DATA etc.) */ - unsigned int options; /* file options (FILE_DELETE_ON_CLOSE, FILE_SYNCHRONOUS...) */ }; static unsigned int generic_file_map_access( unsigned int access ); @@ -102,7 +101,7 @@ static const struct fd_ops file_fd_ops = static inline int is_overlapped( const struct file *file ) { - return !(file->options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT)); + return !(get_fd_options( file->fd ) & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT)); } /* create a file from a file descriptor */ @@ -113,9 +112,9 @@ static struct file *create_file_for_fd( int fd, unsigned int access, unsigned in if ((file = alloc_object( &file_ops ))) { - file->access = file_map_access( &file->obj, access ); - file->options = FILE_SYNCHRONOUS_IO_NONALERT; - if (!(file->fd = create_anonymous_fd( &file_fd_ops, fd, &file->obj ))) + file->access = file_map_access( &file->obj, access ); + if (!(file->fd = create_anonymous_fd( &file_fd_ops, fd, &file->obj, + FILE_SYNCHRONOUS_IO_NONALERT ))) { release_object( file ); return NULL; @@ -124,13 +123,12 @@ static struct file *create_file_for_fd( int fd, unsigned int access, unsigned in return file; } -static struct object *create_file_obj( struct fd *fd, unsigned int access, unsigned int options ) +static struct object *create_file_obj( struct fd *fd, unsigned int access ) { struct file *file = alloc_object( &file_ops ); if (!file) return NULL; file->access = access; - file->options = options; file->fd = fd; grab_object( fd ); set_fd_user( fd, &file_fd_ops, &file->obj ); @@ -177,9 +175,9 @@ static struct object *create_file( const char *nameptr, data_size_t len, unsigne if (S_ISDIR(mode)) obj = create_dir_obj( fd ); else if (S_ISCHR(mode) && is_serial_fd( fd )) - obj = create_serial( fd, options ); + obj = create_serial( fd ); else - obj = create_file_obj( fd, access, options ); + obj = create_file_obj( fd, access ); release_object( fd ); @@ -215,7 +213,7 @@ static void file_dump( struct object *obj, int verbose ) { struct file *file = (struct file *)obj; assert( obj->ops == &file_ops ); - fprintf( stderr, "File fd=%p options=%08x\n", file->fd, file->options ); + fprintf( stderr, "File fd=%p\n", file->fd ); } static int file_get_poll_events( struct fd *fd ) @@ -236,10 +234,7 @@ static void file_flush( struct fd *fd, struct event **event ) static enum server_fd_type file_get_info( struct fd *fd, int *flags ) { - struct file *file = get_fd_user( fd ); - *flags = 0; - if (is_overlapped( file )) *flags |= FD_FLAG_OVERLAPPED; return FD_TYPE_FILE; } diff --git a/server/file.h b/server/file.h index 54d2d730920..e3a7cb59c3f 100644 --- a/server/file.h +++ b/server/file.h @@ -53,9 +53,10 @@ extern struct fd *alloc_pseudo_fd( const struct fd_ops *fd_user_ops, struct obje extern struct fd *open_fd( const char *name, int flags, mode_t *mode, unsigned int access, unsigned int sharing, unsigned int options ); extern struct fd *create_anonymous_fd( const struct fd_ops *fd_user_ops, - int unix_fd, struct object *user ); + int unix_fd, struct object *user, unsigned int options ); extern void *get_fd_user( struct fd *fd ); extern void set_fd_user( struct fd *fd, const struct fd_ops *ops, struct object *user ); +extern unsigned int get_fd_options( struct fd *fd ); extern int get_unix_fd( struct fd *fd ); extern int is_same_file_fd( struct fd *fd1, struct fd *fd2 ); extern int is_fd_removable( struct fd *fd ); @@ -123,7 +124,7 @@ extern struct object *create_dir_obj( struct fd *fd ); /* serial port functions */ extern int is_serial_fd( struct fd *fd ); -extern struct object *create_serial( struct fd *fd, unsigned int options ); +extern struct object *create_serial( struct fd *fd ); /* async I/O functions */ extern struct async_queue *create_async_queue( struct fd *fd ); diff --git a/server/mailslot.c b/server/mailslot.c index b29c84e5822..abc634901bd 100644 --- a/server/mailslot.c +++ b/server/mailslot.c @@ -215,7 +215,7 @@ static enum server_fd_type mailslot_get_info( struct fd *fd, int *flags ) { struct mailslot *mailslot = get_fd_user( fd ); assert( mailslot->obj.ops == &mailslot_ops ); - *flags = FD_FLAG_TIMEOUT | FD_FLAG_AVAILABLE; + *flags = 0; return FD_TYPE_MAILSLOT; } @@ -410,10 +410,10 @@ static struct mailslot *create_mailslot( struct directory *root, fcntl( fds[0], F_SETFL, O_NONBLOCK ); fcntl( fds[1], F_SETFL, O_NONBLOCK ); shutdown( fds[0], SHUT_RD ); - mailslot->fd = create_anonymous_fd( &mailslot_fd_ops, - fds[1], &mailslot->obj ); - mailslot->write_fd = create_anonymous_fd( &mail_writer_fd_ops, - fds[0], &mailslot->obj ); + mailslot->fd = create_anonymous_fd( &mailslot_fd_ops, fds[1], &mailslot->obj, + FILE_SYNCHRONOUS_IO_NONALERT ); + mailslot->write_fd = create_anonymous_fd( &mail_writer_fd_ops, fds[0], &mailslot->obj, + FILE_SYNCHRONOUS_IO_NONALERT ); if (mailslot->fd && mailslot->write_fd) return mailslot; } else file_set_error(); diff --git a/server/named_pipe.c b/server/named_pipe.c index 527e4c8293c..738e3689669 100644 --- a/server/named_pipe.c +++ b/server/named_pipe.c @@ -557,19 +557,13 @@ static inline int is_overlapped( unsigned int options ) static enum server_fd_type pipe_server_get_info( struct fd *fd, int *flags ) { - struct pipe_server *server = get_fd_user( fd ); - - *flags = FD_FLAG_AVAILABLE; - if (is_overlapped( server->options )) *flags |= FD_FLAG_OVERLAPPED; + *flags = 0; return FD_TYPE_PIPE; } static enum server_fd_type pipe_client_get_info( struct fd *fd, int *flags ) { - struct pipe_client *client = get_fd_user( fd ); - - *flags = FD_FLAG_AVAILABLE; - if (is_overlapped( client->flags )) *flags |= FD_FLAG_OVERLAPPED; + *flags = 0; return FD_TYPE_PIPE; } @@ -715,10 +709,8 @@ static struct object *named_pipe_open_file( struct object *obj, unsigned int acc setsockopt( fds[1], SOL_SOCKET, SO_SNDBUF, &pipe->outsize, sizeof(pipe->outsize) ); } - client->fd = create_anonymous_fd( &pipe_client_fd_ops, - fds[1], &client->obj ); - server->fd = create_anonymous_fd( &pipe_server_fd_ops, - fds[0], &server->obj ); + client->fd = create_anonymous_fd( &pipe_client_fd_ops, fds[1], &client->obj, options ); + server->fd = create_anonymous_fd( &pipe_server_fd_ops, fds[0], &server->obj, server->options ); if (client->fd && server->fd && res != 1) { if (server->state == ps_wait_open) diff --git a/server/process.c b/server/process.c index f06f5f46ae6..ee19aa4d71f 100644 --- a/server/process.c +++ b/server/process.c @@ -302,7 +302,7 @@ struct thread *create_process( int fd, struct thread *parent_thread, int inherit close( fd ); goto error; } - if (!(process->msg_fd = create_anonymous_fd( &process_fd_ops, fd, &process->obj ))) goto error; + if (!(process->msg_fd = create_anonymous_fd( &process_fd_ops, fd, &process->obj, 0 ))) goto error; /* create the handle table */ if (!parent_thread) process->handles = alloc_handle_table( process, 0 ); diff --git a/server/queue.c b/server/queue.c index 22f4dcd36a6..95fd3c9d535 100644 --- a/server/queue.c +++ b/server/queue.c @@ -1580,7 +1580,7 @@ DECL_HANDLER(set_queue_fd) if ((unix_fd = get_file_unix_fd( file )) != -1) { if ((unix_fd = dup( unix_fd )) != -1) - queue->fd = create_anonymous_fd( &msg_queue_fd_ops, unix_fd, &queue->obj ); + queue->fd = create_anonymous_fd( &msg_queue_fd_ops, unix_fd, &queue->obj, 0 ); else file_set_error(); } diff --git a/server/request.c b/server/request.c index 7dac5d11012..d9730d4ce96 100644 --- a/server/request.c +++ b/server/request.c @@ -726,7 +726,7 @@ static void acquire_lock(void) if (listen( fd, 5 ) == -1) fatal_perror( "listen" ); if (!(master_socket = alloc_object( &master_socket_ops )) || - !(master_socket->fd = create_anonymous_fd( &master_socket_fd_ops, fd, &master_socket->obj ))) + !(master_socket->fd = create_anonymous_fd( &master_socket_fd_ops, fd, &master_socket->obj, 0 ))) fatal_error( "out of memory\n" ); master_socket->timeout = NULL; set_fd_events( master_socket->fd, POLLIN ); diff --git a/server/serial.c b/server/serial.c index b9a3bbda17e..63b925d5223 100644 --- a/server/serial.c +++ b/server/serial.c @@ -69,7 +69,6 @@ struct serial { struct object obj; struct fd *fd; - unsigned int options; /* timeout values */ unsigned int readinterval; @@ -122,18 +121,12 @@ int is_serial_fd( struct fd *fd ) } /* create a serial object for a given fd */ -struct object *create_serial( struct fd *fd, unsigned int options ) +struct object *create_serial( struct fd *fd ) { struct serial *serial; - int unix_fd = get_unix_fd( fd ); - - /* set the fd back to blocking if necessary */ - if (options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT)) - fcntl( unix_fd, F_SETFL, 0 ); if (!(serial = alloc_object( &serial_ops ))) return NULL; - serial->options = options; serial->readinterval = 0; serial->readmult = 0; serial->readconst = 0; @@ -184,15 +177,6 @@ static enum server_fd_type serial_get_info( struct fd *fd, int *flags ) assert( serial->obj.ops == &serial_ops ); *flags = 0; - if (!(serial->options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT))) - *flags |= FD_FLAG_OVERLAPPED; - else if (!(serial->readinterval == MAXDWORD && - serial->readmult == 0 && serial->readconst == 0)) - *flags |= FD_FLAG_TIMEOUT; - if (serial->readinterval == MAXDWORD && - serial->readmult == 0 && serial->readconst == 0) - *flags |= FD_FLAG_AVAILABLE; - return FD_TYPE_SERIAL; } diff --git a/server/signal.c b/server/signal.c index 238edeface9..927699f63f1 100644 --- a/server/signal.c +++ b/server/signal.c @@ -114,7 +114,7 @@ static struct handler *create_handler( signal_callback callback ) handler->pending = 0; handler->callback = callback; - if (!(handler->fd = create_anonymous_fd( &handler_fd_ops, fd[0], &handler->obj ))) + if (!(handler->fd = create_anonymous_fd( &handler_fd_ops, fd[0], &handler->obj, 0 ))) { release_object( handler ); return NULL; diff --git a/server/sock.c b/server/sock.c index 51109c35bed..03cb3577d45 100644 --- a/server/sock.c +++ b/server/sock.c @@ -245,20 +245,17 @@ static void sock_wake_up( struct sock *sock, int pollev ) int i; int async_active = 0; - if ( sock->flags & WSA_FLAG_OVERLAPPED ) + if ( pollev & (POLLIN|POLLPRI) && async_waiting( sock->read_q )) { - if ( pollev & (POLLIN|POLLPRI) && async_waiting( sock->read_q )) - { - if (debug_level) fprintf( stderr, "activating read queue for socket %p\n", sock ); - async_wake_up( sock->read_q, STATUS_ALERTED ); - async_active = 1; - } - if ( pollev & POLLOUT && async_waiting( sock->write_q )) - { - if (debug_level) fprintf( stderr, "activating write queue for socket %p\n", sock ); - async_wake_up( sock->write_q, STATUS_ALERTED ); - async_active = 1; - } + if (debug_level) fprintf( stderr, "activating read queue for socket %p\n", sock ); + async_wake_up( sock->read_q, STATUS_ALERTED ); + async_active = 1; + } + if ( pollev & POLLOUT && async_waiting( sock->write_q )) + { + if (debug_level) fprintf( stderr, "activating write queue for socket %p\n", sock ); + async_wake_up( sock->write_q, STATUS_ALERTED ); + async_active = 1; } /* Do not signal events if there are still pending asynchronous IO requests */ @@ -485,10 +482,8 @@ static int sock_get_poll_events( struct fd *fd ) /* listening, wait for readable */ return (sock->hmask & FD_ACCEPT) ? 0 : POLLIN; - if (mask & (FD_READ) || (sock->flags & WSA_FLAG_OVERLAPPED && async_waiting( sock->read_q ))) - ev |= POLLIN | POLLPRI; - if (mask & FD_WRITE || (sock->flags & WSA_FLAG_OVERLAPPED && async_waiting( sock->write_q ))) - ev |= POLLOUT; + if (mask & FD_READ || async_waiting( sock->read_q )) ev |= POLLIN | POLLPRI; + if (mask & FD_WRITE || async_waiting( sock->write_q )) ev |= POLLOUT; /* We use POLLIN with 0 bytes recv() as FD_CLOSE indication for stream sockets. */ if ( sock->type == SOCK_STREAM && ( sock->mask & ~sock->hmask & FD_CLOSE) ) ev |= POLLIN; @@ -501,8 +496,7 @@ static enum server_fd_type sock_get_info( struct fd *fd, int *flags ) struct sock *sock = get_fd_user( fd ); assert( sock->obj.ops == &sock_ops ); - *flags = FD_FLAG_AVAILABLE; - if (sock->flags & WSA_FLAG_OVERLAPPED) *flags |= FD_FLAG_OVERLAPPED; + *flags = 0; if ( sock->type != SOCK_STREAM || sock->state & FD_WINE_CONNECTED ) { if ( !(sock->state & FD_READ ) ) *flags |= FD_FLAG_RECV_SHUTDOWN; @@ -519,12 +513,6 @@ static void sock_queue_async( struct fd *fd, const async_data_t *data, int type, assert( sock->obj.ops == &sock_ops ); - if ( !(sock->flags & WSA_FLAG_OVERLAPPED) ) - { - set_error( STATUS_INVALID_HANDLE ); - return; - } - switch (type) { case ASYNC_TYPE_READ: @@ -636,7 +624,8 @@ static struct object *create_socket( int family, int type, int protocol, unsigne sock->deferred = NULL; sock->read_q = NULL; sock->write_q = NULL; - if (!(sock->fd = create_anonymous_fd( &sock_fd_ops, sockfd, &sock->obj ))) + if (!(sock->fd = create_anonymous_fd( &sock_fd_ops, sockfd, &sock->obj, + (flags & WSA_FLAG_OVERLAPPED) ? 0 : FILE_SYNCHRONOUS_IO_NONALERT ))) { release_object( sock ); return NULL; @@ -705,7 +694,8 @@ static struct sock *accept_socket( obj_handle_t handle ) acceptsock->deferred = NULL; acceptsock->read_q = NULL; acceptsock->write_q = NULL; - if (!(acceptsock->fd = create_anonymous_fd( &sock_fd_ops, acceptfd, &acceptsock->obj ))) + if (!(acceptsock->fd = create_anonymous_fd( &sock_fd_ops, acceptfd, &acceptsock->obj, + get_fd_options( sock->fd ) ))) { release_object( acceptsock ); release_object( sock ); diff --git a/server/thread.c b/server/thread.c index 09e0367ce9b..2bac6362916 100644 --- a/server/thread.c +++ b/server/thread.c @@ -206,7 +206,7 @@ struct thread *create_thread( int fd, struct process *process ) release_object( thread ); return NULL; } - if (!(thread->request_fd = create_anonymous_fd( &thread_fd_ops, fd, &thread->obj ))) + if (!(thread->request_fd = create_anonymous_fd( &thread_fd_ops, fd, &thread->obj, 0 ))) { release_object( thread ); return NULL; @@ -993,7 +993,7 @@ DECL_HANDLER(init_thread) if (reply_fd == -1 || fcntl( reply_fd, F_SETFL, O_NONBLOCK ) == -1) goto error; - current->reply_fd = create_anonymous_fd( &thread_fd_ops, reply_fd, ¤t->obj ); + current->reply_fd = create_anonymous_fd( &thread_fd_ops, reply_fd, ¤t->obj, 0 ); reply_fd = -1; if (!current->reply_fd) goto error; @@ -1002,7 +1002,7 @@ DECL_HANDLER(init_thread) set_error( STATUS_TOO_MANY_OPENED_FILES ); /* most likely reason */ return; } - if (!(current->wait_fd = create_anonymous_fd( &thread_fd_ops, wait_fd, ¤t->obj ))) + if (!(current->wait_fd = create_anonymous_fd( &thread_fd_ops, wait_fd, ¤t->obj, 0 ))) return; if (!is_valid_address(req->teb) || !is_valid_address(req->peb) || !is_valid_address(req->ldt_copy)) -- GitLab